Display system-provided drag images during drag-and-drop in wxMSW.
This is especially useful when dragging files from Explorer as it provides big, informative drag images for them that can be easily displayed using Windows shell support for them. See #14697. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72668 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -585,6 +585,7 @@ wxMSW:
|
||||
- Better support for SAFEARRAY in OLE Automation code (PB).
|
||||
- Fix calling Iconize(false) on hidden top level windows (Christian Walther).
|
||||
- Don't send any events from wxSpinCtrl::SetRange() even if the value changed.
|
||||
- Display system drag images during drag and drop if available (PeterO).
|
||||
|
||||
|
||||
2.9.4: (released 2012-07-09)
|
||||
|
@@ -19,6 +19,7 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxIDropTarget;
|
||||
struct IDropTargetHelper;
|
||||
struct IDataObject;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -60,12 +61,26 @@ public:
|
||||
// GetData() when it's called from inside OnData()
|
||||
void MSWSetDataSource(IDataObject *pIDataSource);
|
||||
|
||||
// These functions take care of all things necessary to support native drag
|
||||
// images.
|
||||
//
|
||||
// {Init,End}DragImageSupport() are called during Register/Revoke,
|
||||
// UpdateDragImageOnXXX() functions are called on the corresponding drop
|
||||
// target events.
|
||||
void MSWInitDragImageSupport();
|
||||
void MSWEndDragImageSupport();
|
||||
void MSWUpdateDragImageOnData(wxCoord x, wxCoord y, wxDragResult res);
|
||||
void MSWUpdateDragImageOnDragOver(wxCoord x, wxCoord y, wxDragResult res);
|
||||
void MSWUpdateDragImageOnEnter(wxCoord x, wxCoord y, wxDragResult res);
|
||||
void MSWUpdateDragImageOnLeave();
|
||||
|
||||
private:
|
||||
// helper used by IsAcceptedData() and GetData()
|
||||
wxDataFormat MSWGetSupportedFormat(IDataObject *pIDataSource) const;
|
||||
|
||||
wxIDropTarget *m_pIDropTarget; // the pointer to our COM interface
|
||||
IDataObject *m_pIDataSource; // the pointer to the source data object
|
||||
IDropTargetHelper *m_dropTargetHelper; // the pointer to the drop target helper
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxDropTarget);
|
||||
};
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/vector.h"
|
||||
#include "wx/wxcrtvararg.h"
|
||||
#endif
|
||||
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
#if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__)
|
||||
|
||||
#include "wx/scopedarray.h"
|
||||
#include "wx/msw/private.h" // includes <windows.h>
|
||||
|
||||
#ifdef __WXWINCE__
|
||||
@@ -67,6 +69,9 @@
|
||||
#define GetTymedName(tymed) wxEmptyString
|
||||
#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
wxDataFormat HtmlFormatFixup(wxDataFormat format)
|
||||
{
|
||||
// Since the HTML format is dynamically registered, the wxDF_HTML
|
||||
@@ -82,6 +87,78 @@ wxDataFormat HtmlFormatFixup(wxDataFormat format)
|
||||
return format;
|
||||
}
|
||||
|
||||
// helper function for wxCopyStgMedium()
|
||||
HGLOBAL wxGlobalClone(HGLOBAL hglobIn)
|
||||
{
|
||||
HGLOBAL hglobOut = NULL;
|
||||
|
||||
LPVOID pvIn = GlobalLock(hglobIn);
|
||||
if (pvIn)
|
||||
{
|
||||
SIZE_T cb = GlobalSize(hglobIn);
|
||||
hglobOut = GlobalAlloc(GMEM_FIXED, cb);
|
||||
if (hglobOut)
|
||||
{
|
||||
CopyMemory(hglobOut, pvIn, cb);
|
||||
}
|
||||
GlobalUnlock(hglobIn);
|
||||
}
|
||||
|
||||
return hglobOut;
|
||||
}
|
||||
|
||||
// Copies the given STGMEDIUM structure.
|
||||
//
|
||||
// This is an local implementation of the function with the same name in
|
||||
// urlmon.lib but to use that function would require linking with urlmon.lib
|
||||
// and we don't want to require it, so simple reimplement it here.
|
||||
HRESULT wxCopyStgMedium(const STGMEDIUM *pmediumIn, STGMEDIUM *pmediumOut)
|
||||
{
|
||||
HRESULT hres = S_OK;
|
||||
STGMEDIUM stgmOut = *pmediumIn;
|
||||
|
||||
if (pmediumIn->pUnkForRelease == NULL &&
|
||||
!(pmediumIn->tymed & (TYMED_ISTREAM | TYMED_ISTORAGE)))
|
||||
{
|
||||
// Object needs to be cloned.
|
||||
if (pmediumIn->tymed == TYMED_HGLOBAL)
|
||||
{
|
||||
stgmOut.hGlobal = wxGlobalClone(pmediumIn->hGlobal);
|
||||
if (!stgmOut.hGlobal)
|
||||
{
|
||||
hres = E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hres = DV_E_TYMED; // Don't know how to clone GDI objects.
|
||||
}
|
||||
}
|
||||
|
||||
if ( SUCCEEDED(hres) )
|
||||
{
|
||||
switch ( stgmOut.tymed )
|
||||
{
|
||||
case TYMED_ISTREAM:
|
||||
stgmOut.pstm->AddRef();
|
||||
break;
|
||||
|
||||
case TYMED_ISTORAGE:
|
||||
stgmOut.pstg->AddRef();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( stgmOut.pUnkForRelease )
|
||||
stgmOut.pUnkForRelease->AddRef();
|
||||
|
||||
*pmediumOut = stgmOut;
|
||||
}
|
||||
|
||||
return hres;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxIEnumFORMATETC interface implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -142,8 +219,122 @@ private:
|
||||
bool m_mustDelete;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxIDataObject);
|
||||
|
||||
// The following code is need to be able to store system data the operating
|
||||
// system is using for it own purposes, e.g. drag images.
|
||||
|
||||
class SystemDataEntry
|
||||
{
|
||||
public:
|
||||
// Ctor takes ownership of the pointers.
|
||||
SystemDataEntry(FORMATETC *pformatetc, STGMEDIUM *pmedium)
|
||||
: pformatetc(pformatetc), pmedium(pmedium)
|
||||
{
|
||||
}
|
||||
|
||||
~SystemDataEntry()
|
||||
{
|
||||
delete pformatetc;
|
||||
delete pmedium;
|
||||
}
|
||||
|
||||
FORMATETC *pformatetc;
|
||||
STGMEDIUM *pmedium;
|
||||
};
|
||||
typedef wxVector<SystemDataEntry*> SystemData;
|
||||
|
||||
// get system data specified by the given format
|
||||
bool GetSystemData(wxDataFormat format, STGMEDIUM*) const;
|
||||
|
||||
// determines if the data object contains system data specified by the given format.
|
||||
bool HasSystemData(wxDataFormat format) const;
|
||||
|
||||
// save system data
|
||||
HRESULT SaveSystemData(FORMATETC*, STGMEDIUM*, BOOL fRelease);
|
||||
|
||||
// container for system data
|
||||
SystemData m_systemData;
|
||||
};
|
||||
|
||||
bool
|
||||
wxIDataObject::GetSystemData(wxDataFormat format, STGMEDIUM *pmedium) const
|
||||
{
|
||||
for ( SystemData::const_iterator it = m_systemData.begin();
|
||||
it != m_systemData.end();
|
||||
++it )
|
||||
{
|
||||
FORMATETC* formatEtc = (*it)->pformatetc;
|
||||
if ( formatEtc->cfFormat == format )
|
||||
{
|
||||
wxCopyStgMedium((*it)->pmedium, pmedium);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wxIDataObject::HasSystemData(wxDataFormat format) const
|
||||
{
|
||||
for ( SystemData::const_iterator it = m_systemData.begin();
|
||||
it != m_systemData.end();
|
||||
++it )
|
||||
{
|
||||
FORMATETC* formatEtc = (*it)->pformatetc;
|
||||
if ( formatEtc->cfFormat == format )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// save system data
|
||||
HRESULT
|
||||
wxIDataObject::SaveSystemData(FORMATETC *pformatetc,
|
||||
STGMEDIUM *pmedium,
|
||||
BOOL fRelease)
|
||||
{
|
||||
if ( pformatetc == NULL || pmedium == NULL )
|
||||
return E_INVALIDARG;
|
||||
|
||||
// remove entry if already available
|
||||
for ( SystemData::iterator it = m_systemData.begin();
|
||||
it != m_systemData.end();
|
||||
++it )
|
||||
{
|
||||
if ( pformatetc->tymed & (*it)->pformatetc->tymed &&
|
||||
pformatetc->dwAspect == (*it)->pformatetc->dwAspect &&
|
||||
pformatetc->cfFormat == (*it)->pformatetc->cfFormat )
|
||||
{
|
||||
delete (*it);
|
||||
m_systemData.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// create new format/medium
|
||||
FORMATETC* pnewformatEtc = new FORMATETC;
|
||||
STGMEDIUM* pnewmedium = new STGMEDIUM;
|
||||
|
||||
wxZeroMemory(*pnewformatEtc);
|
||||
wxZeroMemory(*pnewmedium);
|
||||
|
||||
// copy format
|
||||
*pnewformatEtc = *pformatetc;
|
||||
|
||||
// copy or take ownerschip of medium
|
||||
if ( fRelease )
|
||||
*pnewmedium = *pmedium;
|
||||
else
|
||||
wxCopyStgMedium(pmedium, pnewmedium);
|
||||
|
||||
// save entry
|
||||
m_systemData.push_back(new SystemDataEntry(pnewformatEtc, pnewmedium));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
@@ -289,6 +480,14 @@ wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
|
||||
|
||||
wxIDataObject::~wxIDataObject()
|
||||
{
|
||||
// delete system data
|
||||
for ( SystemData::iterator it = m_systemData.begin();
|
||||
it != m_systemData.end();
|
||||
++it )
|
||||
{
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
if ( m_mustDelete )
|
||||
{
|
||||
delete m_pDataObject;
|
||||
@@ -310,6 +509,13 @@ STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
|
||||
wxDataFormat format = (wxDataFormat::NativeFormat)pformatetcIn->cfFormat;
|
||||
format = HtmlFormatFixup(format);
|
||||
|
||||
// is this system data?
|
||||
if ( GetSystemData(format, pmedium) )
|
||||
{
|
||||
// pmedium is already filled with corresponding data, so we're ready.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
switch ( format )
|
||||
{
|
||||
case wxDF_BITMAP:
|
||||
@@ -445,6 +651,17 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
|
||||
m_pDataObject->SetData(wxDF_ENHMETAFILE, 0, &pmedium->hEnhMetaFile);
|
||||
break;
|
||||
|
||||
case TYMED_ISTREAM:
|
||||
// check if this format is supported
|
||||
if ( !m_pDataObject->IsSupported(pformatetc->cfFormat,
|
||||
wxDataObject::Set) )
|
||||
{
|
||||
// As this is not a supported format (content data), assume it
|
||||
// is system data and save it.
|
||||
return SaveSystemData(pformatetc, pmedium, fRelease);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYMED_MFPICT:
|
||||
// fall through - we pass METAFILEPICT through HGLOBAL
|
||||
case TYMED_HGLOBAL:
|
||||
@@ -453,15 +670,11 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
|
||||
|
||||
format = HtmlFormatFixup(format);
|
||||
|
||||
// this is quite weird, but for file drag and drop, explorer
|
||||
// calls our SetData() with the formats we do *not* support!
|
||||
//
|
||||
// as we can't fix this bug in explorer (it's a bug because it
|
||||
// should only use formats returned by EnumFormatEtc), do the
|
||||
// check here
|
||||
// check if this format is supported
|
||||
if ( !m_pDataObject->IsSupported(format, wxDataObject::Set) ) {
|
||||
// go away!
|
||||
return DV_E_FORMATETC;
|
||||
// As above, assume that unsupported format must be system
|
||||
// data and just save it.
|
||||
return SaveSystemData(pformatetc, pmedium, fRelease);
|
||||
}
|
||||
|
||||
// copy data
|
||||
@@ -595,6 +808,13 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
|
||||
wxGetFormatName(format));
|
||||
}
|
||||
else if ( HasSystemData(format) )
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok (system data)"),
|
||||
wxGetFormatName(format));
|
||||
// this is system data, so no further checks needed.
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: %s unsupported"),
|
||||
@@ -640,20 +860,31 @@ STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDir,
|
||||
wxDataObject::Direction dir = dwDir == DATADIR_GET ? wxDataObject::Get
|
||||
: wxDataObject::Set;
|
||||
|
||||
ULONG nFormatCount = wx_truncate_cast(ULONG, m_pDataObject->GetFormatCount(dir));
|
||||
wxDataFormat format;
|
||||
wxDataFormat *formats;
|
||||
formats = nFormatCount == 1 ? &format : new wxDataFormat[nFormatCount];
|
||||
m_pDataObject->GetAllFormats(formats, dir);
|
||||
// format count is total of user specified and system formats.
|
||||
const size_t ourFormatCount = m_pDataObject->GetFormatCount(dir);
|
||||
const size_t sysFormatCount = m_systemData.size();
|
||||
|
||||
wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
|
||||
const ULONG
|
||||
nFormatCount = wx_truncate_cast(ULONG, ourFormatCount + sysFormatCount);
|
||||
|
||||
// fill format array with formats ...
|
||||
wxScopedArray<wxDataFormat> formats(new wxDataFormat[nFormatCount]);
|
||||
|
||||
// ... from content data (supported formats)
|
||||
m_pDataObject->GetAllFormats(formats.get(), dir);
|
||||
|
||||
// ... from system data
|
||||
for ( size_t j = 0; j < sysFormatCount; j++ )
|
||||
{
|
||||
SystemDataEntry* entry = m_systemData[j];
|
||||
wxDataFormat& format = formats[ourFormatCount + j];
|
||||
format = entry->pformatetc->cfFormat;
|
||||
}
|
||||
|
||||
wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats.get(), nFormatCount);
|
||||
pEnum->AddRef();
|
||||
*ppenumFormatEtc = pEnum;
|
||||
|
||||
if ( formats != &format ) {
|
||||
delete [] formats;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@@ -63,6 +63,7 @@ public:
|
||||
virtual ~wxIDropTarget();
|
||||
|
||||
// accessors for wxDropTarget
|
||||
HWND GetHWND() const { return m_hwnd; }
|
||||
void SetHwnd(HWND hwnd) { m_hwnd = hwnd; }
|
||||
|
||||
// IDropTarget methods
|
||||
@@ -192,13 +193,6 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) {
|
||||
// we don't accept this kind of data
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// for use in OnEnter and OnDrag calls
|
||||
m_pTarget->MSWSetDataSource(pIDataSource);
|
||||
|
||||
@@ -206,6 +200,12 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
|
||||
m_pIDataObject = pIDataSource;
|
||||
m_pIDataObject->AddRef();
|
||||
|
||||
if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) {
|
||||
// we don't accept this kind of data
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need client coordinates to pass to wxWin functions
|
||||
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
|
||||
{
|
||||
@@ -218,10 +218,18 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
|
||||
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// update drag image
|
||||
const wxDragResult res = ConvertDragEffectToResult(*pdwEffect);
|
||||
m_pTarget->MSWUpdateDragImageOnEnter(pt.x, pt.y, res);
|
||||
m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y, res);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Name : wxIDropTarget::DragOver
|
||||
// Purpose : Indicates that the mouse was moved inside the window represented
|
||||
// by this drop target.
|
||||
@@ -262,6 +270,10 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState,
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y,
|
||||
ConvertDragEffectToResult(*pdwEffect));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -279,6 +291,9 @@ STDMETHODIMP wxIDropTarget::DragLeave()
|
||||
// release the held object
|
||||
RELEASE_AND_NULL(m_pIDataObject);
|
||||
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnLeave();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -333,6 +348,10 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
|
||||
// release the held object
|
||||
RELEASE_AND_NULL(m_pIDataObject);
|
||||
|
||||
// update drag image
|
||||
m_pTarget->MSWUpdateDragImageOnData(pt.x, pt.y,
|
||||
ConvertDragEffectToResult(*pdwEffect));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -345,7 +364,8 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxDropTarget::wxDropTarget(wxDataObject *dataObj)
|
||||
: wxDropTargetBase(dataObj)
|
||||
: wxDropTargetBase(dataObj),
|
||||
m_dropTargetHelper(NULL)
|
||||
{
|
||||
// create an IDropTarget implementation which will notify us about d&d
|
||||
// operations.
|
||||
@@ -396,6 +416,8 @@ bool wxDropTarget::Register(WXHWND hwnd)
|
||||
// we will need the window handle for coords transformation later
|
||||
m_pIDropTarget->SetHwnd((HWND)hwnd);
|
||||
|
||||
MSWInitDragImageSupport();
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
@@ -417,6 +439,9 @@ void wxDropTarget::Revoke(WXHWND hwnd)
|
||||
::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE);
|
||||
#endif
|
||||
|
||||
MSWEndDragImageSupport();
|
||||
|
||||
// remove window reference
|
||||
m_pIDropTarget->SetHwnd(0);
|
||||
#endif
|
||||
}
|
||||
@@ -437,9 +462,6 @@ bool wxDropTarget::GetData()
|
||||
{
|
||||
wxDataFormat format = MSWGetSupportedFormat(m_pIDataSource);
|
||||
if ( format == wxDF_INVALID ) {
|
||||
// this is strange because IsAcceptedData() succeeded previously!
|
||||
wxFAIL_MSG(wxT("strange - did supported formats list change?"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -539,6 +561,81 @@ wxDataFormat wxDropTarget::MSWGetSupportedFormat(IDataObject *pIDataSource) cons
|
||||
return n < nFormats ? format : wxFormatInvalid;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// drag image functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
wxDropTarget::MSWEndDragImageSupport()
|
||||
{
|
||||
// release drop target helper
|
||||
if ( m_dropTargetHelper != NULL )
|
||||
{
|
||||
m_dropTargetHelper->Release();
|
||||
m_dropTargetHelper = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wxDropTarget::MSWInitDragImageSupport()
|
||||
{
|
||||
// Use the default drop target helper to show shell drag images
|
||||
CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_IDropTargetHelper, (LPVOID*)&m_dropTargetHelper);
|
||||
}
|
||||
|
||||
void
|
||||
wxDropTarget::MSWUpdateDragImageOnData(wxCoord x,
|
||||
wxCoord y,
|
||||
wxDragResult dragResult)
|
||||
{
|
||||
// call corresponding event on drop target helper
|
||||
if ( m_dropTargetHelper != NULL )
|
||||
{
|
||||
POINT pt = {x, y};
|
||||
DWORD dwEffect = ConvertDragResultToEffect(dragResult);
|
||||
m_dropTargetHelper->Drop(m_pIDataSource, &pt, dwEffect);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wxDropTarget::MSWUpdateDragImageOnDragOver(wxCoord x,
|
||||
wxCoord y,
|
||||
wxDragResult dragResult)
|
||||
{
|
||||
// call corresponding event on drop target helper
|
||||
if ( m_dropTargetHelper != NULL )
|
||||
{
|
||||
POINT pt = {x, y};
|
||||
DWORD dwEffect = ConvertDragResultToEffect(dragResult);
|
||||
m_dropTargetHelper->DragOver(&pt, dwEffect);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wxDropTarget::MSWUpdateDragImageOnEnter(wxCoord x,
|
||||
wxCoord y,
|
||||
wxDragResult dragResult)
|
||||
{
|
||||
// call corresponding event on drop target helper
|
||||
if ( m_dropTargetHelper != NULL )
|
||||
{
|
||||
POINT pt = {x, y};
|
||||
DWORD dwEffect = ConvertDragResultToEffect(dragResult);
|
||||
m_dropTargetHelper->DragEnter(m_pIDropTarget->GetHWND(), m_pIDataSource, &pt, dwEffect);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wxDropTarget::MSWUpdateDragImageOnLeave()
|
||||
{
|
||||
// call corresponding event on drop target helper
|
||||
if ( m_dropTargetHelper != NULL )
|
||||
{
|
||||
m_dropTargetHelper->DragLeave();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user