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
|
234
src/msw/ole/dropsrc.cpp
Normal file
234
src/msw/ole/dropsrc.cpp
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: msw/ole/dropsrc.cpp
|
||||||
|
// Purpose: implementation of wxIDropSource and wxDropSource
|
||||||
|
// 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 "dropsrc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For compilers that support precompilation, includes "wx.h".
|
||||||
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
#if defined(__BORLANDC__)
|
||||||
|
#pragma hdrstop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <wx/setup.h>
|
||||||
|
|
||||||
|
#if USE_DRAG_AND_DROP
|
||||||
|
|
||||||
|
#include <wx/log.h>
|
||||||
|
#include <wx/msw/ole/oleutils.h>
|
||||||
|
#include <wx/msw/ole/dataobj.h>
|
||||||
|
#include <wx/msw/ole/dropsrc.h>
|
||||||
|
|
||||||
|
#ifndef __WIN32__
|
||||||
|
#include <ole2.h>
|
||||||
|
#include <olestd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxIDropSource implementation of IDropSource interface
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class wxIDropSource : public IDropSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxIDropSource(wxDropSource *pDropSource);
|
||||||
|
|
||||||
|
DECLARE_IUNKNOWN_METHODS;
|
||||||
|
|
||||||
|
// IDropSource
|
||||||
|
STDMETHODIMP QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
|
||||||
|
STDMETHODIMP GiveFeedback(DWORD dwEffect);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DWORD m_grfInitKeyState; // button which started the d&d operation
|
||||||
|
wxDropSource *m_pDropSource; // pointer to C++ class we belong to
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Implementation
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxIDropSource implementation
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
BEGIN_IID_TABLE(wxIDropSource)
|
||||||
|
ADD_IID(Unknown)
|
||||||
|
ADD_IID(DropSource)
|
||||||
|
END_IID_TABLE;
|
||||||
|
|
||||||
|
IMPLEMENT_IUNKNOWN_METHODS(wxIDropSource)
|
||||||
|
|
||||||
|
wxIDropSource::wxIDropSource(wxDropSource *pDropSource)
|
||||||
|
{
|
||||||
|
wxASSERT( pDropSource != NULL );
|
||||||
|
|
||||||
|
m_pDropSource = pDropSource;
|
||||||
|
m_grfInitKeyState = 0;
|
||||||
|
m_cRef = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name : wxIDropSource::QueryContinueDrag
|
||||||
|
// Purpose : decide if drag operation must be continued or not
|
||||||
|
// Returns : HRESULT: S_OK if we should continue
|
||||||
|
// DRAGDROP_S_DROP to drop right now
|
||||||
|
// DRAGDROP_S_CANCEL to cancel everything
|
||||||
|
// Params : [in] BOOL fEscapePressed <Esc> pressed since last call?
|
||||||
|
// [in] DWORD grfKeyState mask containing state of kbd keys
|
||||||
|
// Notes : as there is no reasonably simple portable way to implement this
|
||||||
|
// function, we currently don't give the possibility to override the
|
||||||
|
// default behaviour implemented here
|
||||||
|
STDMETHODIMP wxIDropSource::QueryContinueDrag(BOOL fEscapePressed,
|
||||||
|
DWORD grfKeyState)
|
||||||
|
{
|
||||||
|
if ( fEscapePressed )
|
||||||
|
return DRAGDROP_S_CANCEL;
|
||||||
|
|
||||||
|
// initialize ourself with the drag begin button
|
||||||
|
if ( m_grfInitKeyState == 0 ) {
|
||||||
|
m_grfInitKeyState = grfKeyState & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !(grfKeyState & m_grfInitKeyState) ) {
|
||||||
|
// button which started d&d released, go!
|
||||||
|
return DRAGDROP_S_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name : wxIDropSource::GiveFeedback
|
||||||
|
// Purpose : give UI feedback according to current state of operation
|
||||||
|
// Returns : STDMETHODIMP
|
||||||
|
// Params : [in] DWORD dwEffect - what would happen if we dropped now
|
||||||
|
// Notes : default implementation is ok in more than 99% of cases
|
||||||
|
STDMETHODIMP wxIDropSource::GiveFeedback(DWORD dwEffect)
|
||||||
|
{
|
||||||
|
wxDropSource::DragResult effect;
|
||||||
|
if ( dwEffect & DROPEFFECT_COPY )
|
||||||
|
effect = wxDropSource::Copy;
|
||||||
|
else if ( dwEffect & DROPEFFECT_MOVE )
|
||||||
|
effect = wxDropSource::Move;
|
||||||
|
else
|
||||||
|
effect = wxDropSource::None;
|
||||||
|
|
||||||
|
if ( m_pDropSource->GiveFeedback(effect,
|
||||||
|
(dwEffect & DROPEFFECT_SCROLL) != 0 ) )
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
return DRAGDROP_S_USEDEFAULTCURSORS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxDropSource implementation
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ctors
|
||||||
|
|
||||||
|
// common part of all ctors
|
||||||
|
void wxDropSource::Init()
|
||||||
|
{
|
||||||
|
m_pIDropSource = new wxIDropSource(this);
|
||||||
|
m_pIDropSource->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDropSource::wxDropSource()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
m_pData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDropSource::wxDropSource(wxDataObject& data)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
SetData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxDropSource::SetData(wxDataObject& data)
|
||||||
|
{
|
||||||
|
m_pData = &data;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDropSource::~wxDropSource()
|
||||||
|
{
|
||||||
|
m_pIDropSource->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name : DoDragDrop
|
||||||
|
// Purpose : start drag and drop operation
|
||||||
|
// Returns : DragResult - the code of performed operation
|
||||||
|
// Params : [in] bool bAllowMove: if false, only copy is allowed
|
||||||
|
// Notes : you must call SetData() before if you had used def ctor
|
||||||
|
wxDropSource::DragResult wxDropSource::DoDragDrop(bool bAllowMove)
|
||||||
|
{
|
||||||
|
wxCHECK_RET( m_pData != NULL, None );
|
||||||
|
|
||||||
|
DWORD dwEffect;
|
||||||
|
HRESULT hr = ::DoDragDrop(m_pData->GetInterface(),
|
||||||
|
m_pIDropSource,
|
||||||
|
bAllowMove ? DROPEFFECT_COPY | DROPEFFECT_MOVE
|
||||||
|
: DROPEFFECT_COPY,
|
||||||
|
&dwEffect);
|
||||||
|
|
||||||
|
if ( hr == DRAGDROP_S_CANCEL ) {
|
||||||
|
return Cancel;
|
||||||
|
}
|
||||||
|
else if ( hr == DRAGDROP_S_DROP ) {
|
||||||
|
if ( dwEffect & DROPEFFECT_COPY ) {
|
||||||
|
return Copy;
|
||||||
|
}
|
||||||
|
else if ( dwEffect & DROPEFFECT_MOVE ) {
|
||||||
|
// consistency check: normally, we shouldn't get "move" at all
|
||||||
|
// here if !bAllowMove, but in practice it does happen quite often
|
||||||
|
if ( bAllowMove )
|
||||||
|
return Move;
|
||||||
|
else
|
||||||
|
return Copy;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// not copy or move
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( FAILED(hr) ) {
|
||||||
|
wxLogApiError("DoDragDrop", hr);
|
||||||
|
wxLogError("Drag & drop operation failed.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wxLogDebug("Unexpected success return code %08lx from DoDragDrop.", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name : wxDropSource::GiveFeedback
|
||||||
|
// Purpose : visually inform the user about d&d operation state
|
||||||
|
// Returns : bool: true if we do all ourselves or false for default feedback
|
||||||
|
// Params : [in] DragResult effect - what would happen if we dropped now
|
||||||
|
// [in] bool bScrolling - true if target is scrolling
|
||||||
|
// Notes : here we just leave this stuff for default implementation
|
||||||
|
bool wxDropSource::GiveFeedback(DragResult effect, bool bScrolling)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //USE_DRAG_AND_DROP
|
Reference in New Issue
Block a user