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:
parent
19454fa092
commit
269a5a34a6
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
|
Loading…
Reference in New Issue
Block a user