wxDataObject and wxDropSource implementations
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@53 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
406
src/msw/ole/dataobj.cpp
Normal file
406
src/msw/ole/dataobj.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: msw/ole/dataobj.cpp
|
||||
// Purpose: implementation of wx[I]DataObject class
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 10.05.98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
||||
// Licence: wxWindows license
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "dataobj.h"
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/msw/ole/oleutils.h>
|
||||
#include <wx/msw/ole/dataobj.h>
|
||||
|
||||
#ifndef __WIN32__
|
||||
#include <ole2.h>
|
||||
#include <olestd.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __DEBUG__
|
||||
static const char *GetTymedName(DWORD tymed);
|
||||
#else
|
||||
#define GetTymedName(tymed) ""
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxIEnumFORMATETC interface implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
class wxIEnumFORMATETC : public IEnumFORMATETC
|
||||
{
|
||||
public:
|
||||
wxIEnumFORMATETC(CLIPFORMAT cf);
|
||||
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
|
||||
// IEnumFORMATETC
|
||||
STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
|
||||
STDMETHODIMP Skip(ULONG celt);
|
||||
STDMETHODIMP Reset();
|
||||
STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
|
||||
|
||||
private:
|
||||
FORMATETC m_format; // (unique @@@) format we can provide data in
|
||||
ULONG m_nCurrent; // current enum position (currently either 0 or 1)
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxIDataObject implementation of IDataObject interface
|
||||
// ----------------------------------------------------------------------------
|
||||
class wxIDataObject : public IDataObject
|
||||
{
|
||||
public:
|
||||
wxIDataObject(wxDataObject *pDataObject);
|
||||
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
|
||||
// IDataObject
|
||||
STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
|
||||
STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
|
||||
STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
|
||||
STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
|
||||
STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
|
||||
STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
|
||||
STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
|
||||
STDMETHODIMP DUnadvise(DWORD dwConnection);
|
||||
STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
|
||||
|
||||
private:
|
||||
wxDataObject *m_pDataObject; // pointer to C++ class we belong to
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxIEnumFORMATETC
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BEGIN_IID_TABLE(wxIEnumFORMATETC)
|
||||
ADD_IID(Unknown)
|
||||
ADD_IID(EnumFORMATETC)
|
||||
END_IID_TABLE;
|
||||
|
||||
IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
|
||||
|
||||
wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf)
|
||||
{
|
||||
m_format.cfFormat = cf;
|
||||
m_format.ptd = NULL;
|
||||
m_format.dwAspect = DVASPECT_CONTENT;
|
||||
m_format.lindex = -1;
|
||||
m_format.tymed = TYMED_HGLOBAL;
|
||||
m_cRef = 0;
|
||||
m_nCurrent = 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
|
||||
FORMATETC *rgelt,
|
||||
ULONG *pceltFetched)
|
||||
{
|
||||
wxLogTrace("wxIEnumFORMATETC::Next");
|
||||
|
||||
if ( celt > 1 )
|
||||
return S_FALSE;
|
||||
|
||||
if ( m_nCurrent == 0 ) {
|
||||
*rgelt = m_format;
|
||||
m_nCurrent++;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
|
||||
{
|
||||
wxLogTrace("wxIEnumFORMATETC::Skip");
|
||||
|
||||
if ( m_nCurrent == 0 )
|
||||
m_nCurrent++;
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Reset()
|
||||
{
|
||||
wxLogTrace("wxIEnumFORMATETC::Reset");
|
||||
|
||||
m_nCurrent = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
|
||||
{
|
||||
wxLogTrace("wxIEnumFORMATETC::Clone");
|
||||
|
||||
wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(m_format.cfFormat);
|
||||
pNew->AddRef();
|
||||
*ppenum = pNew;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxIDataObject
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BEGIN_IID_TABLE(wxIDataObject)
|
||||
ADD_IID(Unknown)
|
||||
ADD_IID(DataObject)
|
||||
END_IID_TABLE;
|
||||
|
||||
IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
|
||||
|
||||
wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
|
||||
{
|
||||
m_cRef = 0;
|
||||
m_pDataObject = pDataObject;
|
||||
}
|
||||
|
||||
// get data functions
|
||||
STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
|
||||
{
|
||||
wxLogTrace("wxIDataObject::GetData");
|
||||
|
||||
// is data is in our format?
|
||||
HRESULT hr = QueryGetData(pformatetcIn);
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
// alloc memory
|
||||
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
|
||||
m_pDataObject->GetDataSize());
|
||||
if ( hGlobal == NULL ) {
|
||||
wxLogLastError("GlobalAlloc");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
// copy data
|
||||
pmedium->tymed = TYMED_HGLOBAL;
|
||||
pmedium->hGlobal = hGlobal;
|
||||
pmedium->pUnkForRelease = NULL;
|
||||
|
||||
hr = GetDataHere(pformatetcIn, pmedium);
|
||||
if ( FAILED(hr) ) {
|
||||
GlobalFree(hGlobal);
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
|
||||
STGMEDIUM *pmedium)
|
||||
{
|
||||
wxLogTrace("wxIDataObject::GetDataHere");
|
||||
|
||||
// put data in caller provided medium
|
||||
if ( pmedium->tymed != TYMED_HGLOBAL )
|
||||
return DV_E_TYMED;
|
||||
|
||||
// copy data
|
||||
void *pBuf = GlobalLock(pmedium->hGlobal);
|
||||
if ( pBuf == NULL ) {
|
||||
wxLogLastError("GlobalLock");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
m_pDataObject->GetDataHere(pBuf);
|
||||
|
||||
GlobalUnlock(pmedium->hGlobal);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// set data functions (not implemented)
|
||||
STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
|
||||
STGMEDIUM *pmedium,
|
||||
BOOL fRelease)
|
||||
{
|
||||
wxLogTrace("wxIDataObject::SetData");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// information functions
|
||||
STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
|
||||
{
|
||||
// do we accept data in this format?
|
||||
if ( pformatetc == NULL ) {
|
||||
wxLogTrace("wxIDataObject::QueryGetData: invalid ptr.");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// the only one allowed by current COM implementation
|
||||
if ( pformatetc->lindex != -1 ) {
|
||||
wxLogTrace("wxIDataObject::QueryGetData: bad lindex %d",
|
||||
pformatetc->lindex);
|
||||
return DV_E_LINDEX;
|
||||
}
|
||||
|
||||
// we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
|
||||
if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
|
||||
wxLogTrace("wxIDataObject::QueryGetData: bad dwAspect %d",
|
||||
pformatetc->dwAspect);
|
||||
return DV_E_DVASPECT;
|
||||
}
|
||||
|
||||
// @@ we only transfer data by global memory (bad for large amounts of it!)
|
||||
if ( !(pformatetc->tymed & TYMED_HGLOBAL) ) {
|
||||
wxLogTrace("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL.",
|
||||
GetTymedName(pformatetc->tymed));
|
||||
return DV_E_TYMED;
|
||||
}
|
||||
|
||||
// and now check the type of data requested
|
||||
if ( m_pDataObject->IsSupportedFormat(pformatetc->cfFormat) ) {
|
||||
wxLogTrace("wxIDataObject::QueryGetData: %s ok",
|
||||
wxDataObject::GetFormatName(pformatetc->cfFormat));
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
wxLogTrace("wxIDataObject::QueryGetData: %s unsupported",
|
||||
wxDataObject::GetFormatName(pformatetc->cfFormat));
|
||||
return DV_E_FORMATETC;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
|
||||
FORMATETC *pFormatetcOut)
|
||||
{
|
||||
wxLogTrace("wxIDataObject::GetCanonicalFormatEtc");
|
||||
|
||||
// @@ implementation is trivial, we might want something better here
|
||||
if ( pFormatetcOut != NULL )
|
||||
pFormatetcOut->ptd = NULL;
|
||||
return DATA_S_SAMEFORMATETC;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
|
||||
IEnumFORMATETC **ppenumFormatEtc)
|
||||
{
|
||||
wxLogTrace("wxIDataObject::EnumFormatEtc");
|
||||
|
||||
if ( dwDirection == DATADIR_SET ) {
|
||||
// we don't allow setting of data anyhow
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
wxIEnumFORMATETC *pEnum =
|
||||
new wxIEnumFORMATETC(m_pDataObject->GetPreferredFormat());
|
||||
pEnum->AddRef();
|
||||
*ppenumFormatEtc = pEnum;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// advise sink functions (not implemented)
|
||||
STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc,
|
||||
DWORD advf,
|
||||
IAdviseSink *pAdvSink,
|
||||
DWORD *pdwConnection)
|
||||
{
|
||||
return OLE_E_ADVISENOTSUPPORTED;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::DUnadvise(DWORD dwConnection)
|
||||
{
|
||||
return OLE_E_ADVISENOTSUPPORTED;
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
|
||||
{
|
||||
return OLE_E_ADVISENOTSUPPORTED;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxDataObject
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxDataObject::wxDataObject()
|
||||
{
|
||||
m_pIDataObject = new wxIDataObject(this);
|
||||
m_pIDataObject->AddRef();
|
||||
}
|
||||
|
||||
wxDataObject::~wxDataObject()
|
||||
{
|
||||
m_pIDataObject->Release();
|
||||
}
|
||||
|
||||
#ifdef __DEBUG__
|
||||
|
||||
const char *wxDataObject::GetFormatName(wxDataFormat format)
|
||||
{
|
||||
static char s_szBuf[128];
|
||||
switch ( format ) {
|
||||
case CF_TEXT: return "CF_TEXT";
|
||||
case CF_BITMAP: return "CF_BITMAP";
|
||||
case CF_METAFILEPICT: return "CF_METAFILEPICT";
|
||||
case CF_SYLK: return "CF_SYLK";
|
||||
case CF_DIF: return "CF_DIF";
|
||||
case CF_TIFF: return "CF_TIFF";
|
||||
case CF_OEMTEXT: return "CF_OEMTEXT";
|
||||
case CF_DIB: return "CF_DIB";
|
||||
case CF_PALETTE: return "CF_PALETTE";
|
||||
case CF_PENDATA: return "CF_PENDATA";
|
||||
case CF_RIFF: return "CF_RIFF";
|
||||
case CF_WAVE: return "CF_WAVE";
|
||||
case CF_UNICODETEXT: return "CF_UNICODETEXT";
|
||||
case CF_ENHMETAFILE: return "CF_ENHMETAFILE";
|
||||
case CF_HDROP: return "CF_HDROP";
|
||||
case CF_LOCALE: return "CF_LOCALE";
|
||||
default:
|
||||
sprintf(s_szBuf, "clipboard format %d (unknown)", format);
|
||||
return s_szBuf;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
static const char *GetTymedName(DWORD tymed)
|
||||
{
|
||||
static char s_szBuf[128];
|
||||
switch ( tymed ) {
|
||||
case TYMED_HGLOBAL: return "TYMED_HGLOBAL";
|
||||
case TYMED_FILE: return "TYMED_FILE";
|
||||
case TYMED_ISTREAM: return "TYMED_ISTREAM";
|
||||
case TYMED_ISTORAGE: return "TYMED_ISTORAGE";
|
||||
case TYMED_GDI: return "TYMED_GDI";
|
||||
case TYMED_MFPICT: return "TYMED_MFPICT";
|
||||
case TYMED_ENHMF: return "TYMED_ENHMF";
|
||||
default:
|
||||
sprintf(s_szBuf, "type of media format %d (unknown)", tymed);
|
||||
return s_szBuf;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //DEBUG
|
Reference in New Issue
Block a user