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:
Vadim Zeitlin
1998-05-27 23:38:26 +00:00
parent 19454fa092
commit 269a5a34a6
2 changed files with 640 additions and 0 deletions

406
src/msw/ole/dataobj.cpp Normal file
View 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