]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/ole/droptgt.cpp
No real changes, just use wxString::clear() instead of assignment.
[wxWidgets.git] / src / msw / ole / droptgt.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/ole/droptgt.cpp
3// Purpose: wxDropTarget implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created:
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// Declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#if defined(__BORLANDC__)
24 #pragma hdrstop
25#endif
26
27#if wxUSE_OLE && wxUSE_DRAG_AND_DROP
28
29#ifndef WX_PRECOMP
30 #include "wx/msw/wrapwin.h"
31 #include "wx/log.h"
32#endif
33
34#include "wx/msw/private.h"
35
36#ifdef __WXWINCE__
37 #include <winreg.h>
38 #include <ole2.h>
39#endif
40
41#ifdef __WIN32__
42 #if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS
43 #include <shlobj.h> // for DROPFILES structure
44 #endif
45#else
46 #include <shellapi.h>
47#endif
48
49#include "wx/dnd.h"
50
51#include "wx/msw/ole/oleutils.h"
52
53#include <initguid.h>
54
55// Some (very) old SDKs don't define IDropTargetHelper, so define our own
56// version of it here.
57struct wxIDropTargetHelper : public IUnknown
58{
59 virtual HRESULT STDMETHODCALLTYPE DragEnter(HWND hwndTarget,
60 IDataObject *pDataObject,
61 POINT *ppt,
62 DWORD dwEffect) = 0;
63 virtual HRESULT STDMETHODCALLTYPE DragLeave() = 0;
64 virtual HRESULT STDMETHODCALLTYPE DragOver(POINT *ppt, DWORD dwEffect) = 0;
65 virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObject,
66 POINT *ppt,
67 DWORD dwEffect) = 0;
68 virtual HRESULT STDMETHODCALLTYPE Show(BOOL fShow) = 0;
69};
70
71namespace
72{
73 DEFINE_GUID(wxCLSID_DragDropHelper,
74 0x4657278A,0x411B,0x11D2,0x83,0x9A,0x00,0xC0,0x4F,0xD9,0x18,0xD0);
75 DEFINE_GUID(wxIID_IDropTargetHelper,
76 0x4657278B,0x411B,0x11D2,0x83,0x9A,0x00,0xC0,0x4F,0xD9,0x18,0xD0);
77}
78
79// ----------------------------------------------------------------------------
80// IDropTarget interface: forward all interesting things to wxDropTarget
81// (the name is unfortunate, but wx_I_DropTarget is not at all the same thing
82// as wxDropTarget which is 'public' class, while this one is private)
83// ----------------------------------------------------------------------------
84
85class wxIDropTarget : public IDropTarget
86{
87public:
88 wxIDropTarget(wxDropTarget *p);
89 virtual ~wxIDropTarget();
90
91 // accessors for wxDropTarget
92 HWND GetHWND() const { return m_hwnd; }
93 void SetHwnd(HWND hwnd) { m_hwnd = hwnd; }
94
95 // IDropTarget methods
96 STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
97 STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD);
98 STDMETHODIMP DragLeave();
99 STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
100
101 DECLARE_IUNKNOWN_METHODS;
102
103protected:
104 IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop
105 wxDropTarget *m_pTarget; // the real target (we're just a proxy)
106
107 HWND m_hwnd; // window we're associated with
108
109 // get default drop effect for given keyboard flags
110 static DWORD GetDropEffect(DWORD flags, wxDragResult defaultAction, DWORD pdwEffect);
111
112 wxDECLARE_NO_COPY_CLASS(wxIDropTarget);
113};
114
115// ----------------------------------------------------------------------------
116// private functions
117// ----------------------------------------------------------------------------
118
119static wxDragResult ConvertDragEffectToResult(DWORD dwEffect);
120static DWORD ConvertDragResultToEffect(wxDragResult result);
121
122// ============================================================================
123// wxIDropTarget implementation
124// ============================================================================
125
126// Name : static wxIDropTarget::GetDropEffect
127// Purpose : determine the drop operation from keyboard/mouse state.
128// Returns : DWORD combined from DROPEFFECT_xxx constants
129// Params : [in] DWORD flags kbd & mouse flags as passed to
130// IDropTarget methods
131// [in] wxDragResult defaultAction the default action of the drop target
132// [in] DWORD pdwEffect the supported actions of the drop
133// source passed to IDropTarget methods
134// Notes : We do "move" normally and "copy" if <Ctrl> is pressed,
135// which is the standard behaviour (currently there is no
136// way to redefine it)
137DWORD wxIDropTarget::GetDropEffect(DWORD flags,
138 wxDragResult defaultAction,
139 DWORD pdwEffect)
140{
141 DWORD effectiveAction;
142 if ( defaultAction == wxDragCopy )
143 effectiveAction = flags & MK_SHIFT ? DROPEFFECT_MOVE : DROPEFFECT_COPY;
144 else
145 effectiveAction = flags & MK_CONTROL ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
146
147 if ( !(effectiveAction & pdwEffect) )
148 {
149 // the action is not supported by drag source, fall back to something
150 // that it does support
151 if ( pdwEffect & DROPEFFECT_MOVE )
152 effectiveAction = DROPEFFECT_MOVE;
153 else if ( pdwEffect & DROPEFFECT_COPY )
154 effectiveAction = DROPEFFECT_COPY;
155 else if ( pdwEffect & DROPEFFECT_LINK )
156 effectiveAction = DROPEFFECT_LINK;
157 else
158 effectiveAction = DROPEFFECT_NONE;
159 }
160
161 return effectiveAction;
162}
163
164wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget)
165{
166 m_pTarget = pTarget;
167 m_pIDataObject = NULL;
168}
169
170wxIDropTarget::~wxIDropTarget()
171{
172}
173
174BEGIN_IID_TABLE(wxIDropTarget)
175 ADD_IID(Unknown)
176 ADD_IID(DropTarget)
177END_IID_TABLE;
178
179IMPLEMENT_IUNKNOWN_METHODS(wxIDropTarget)
180
181// Name : wxIDropTarget::DragEnter
182// Purpose : Called when the mouse enters the window (dragging something)
183// Returns : S_OK
184// Params : [in] IDataObject *pIDataSource : source data
185// [in] DWORD grfKeyState : kbd & mouse state
186// [in] POINTL pt : mouse coordinates
187// [in/out]DWORD *pdwEffect : effect flag
188// In: Supported effects
189// Out: Resulting effect
190// Notes :
191STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
192 DWORD grfKeyState,
193 POINTL pt,
194 DWORD *pdwEffect)
195{
196 wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter"));
197
198 wxASSERT_MSG( m_pIDataObject == NULL,
199 wxT("drop target must have data object") );
200
201 // show the list of formats supported by the source data object for the
202 // debugging purposes, this is quite useful sometimes - please don't remove
203#if 0
204 IEnumFORMATETC *penumFmt;
205 if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) )
206 {
207 FORMATETC fmt;
208 while ( penumFmt->Next(1, &fmt, NULL) == S_OK )
209 {
210 wxLogDebug(wxT("Drop source supports format %s"),
211 wxDataObject::GetFormatName(fmt.cfFormat));
212 }
213
214 penumFmt->Release();
215 }
216 else
217 {
218 wxLogLastError(wxT("IDataObject::EnumFormatEtc"));
219 }
220#endif // 0
221
222 // for use in OnEnter and OnDrag calls
223 m_pTarget->MSWSetDataSource(pIDataSource);
224
225 // get hold of the data object
226 m_pIDataObject = pIDataSource;
227 m_pIDataObject->AddRef();
228
229 if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) {
230 // we don't accept this kind of data
231 *pdwEffect = DROPEFFECT_NONE;
232 }
233 else
234 {
235 // we need client coordinates to pass to wxWin functions
236 if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
237 {
238 wxLogLastError(wxT("ScreenToClient"));
239 }
240
241 // give some visual feedback
242 *pdwEffect = ConvertDragResultToEffect(
243 m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult(
244 GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect))
245 )
246 );
247 }
248
249 // update drag image
250 const wxDragResult res = ConvertDragEffectToResult(*pdwEffect);
251 m_pTarget->MSWUpdateDragImageOnEnter(pt.x, pt.y, res);
252 m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y, res);
253
254 return S_OK;
255}
256
257
258
259// Name : wxIDropTarget::DragOver
260// Purpose : Indicates that the mouse was moved inside the window represented
261// by this drop target.
262// Returns : S_OK
263// Params : [in] DWORD grfKeyState kbd & mouse state
264// [in] POINTL pt mouse coordinates
265// [in/out]LPDWORD pdwEffect current effect flag
266// Notes : We're called on every WM_MOUSEMOVE, so this function should be
267// very efficient.
268STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState,
269 POINTL pt,
270 LPDWORD pdwEffect)
271{
272 // there are too many of them... wxLogDebug("IDropTarget::DragOver");
273
274 wxDragResult result;
275 if ( m_pIDataObject ) {
276 result = ConvertDragEffectToResult(
277 GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
278 }
279 else {
280 // can't accept data anyhow normally
281 result = wxDragNone;
282 }
283
284 if ( result != wxDragNone ) {
285 // we need client coordinates to pass to wxWin functions
286 if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
287 {
288 wxLogLastError(wxT("ScreenToClient"));
289 }
290
291 *pdwEffect = ConvertDragResultToEffect(
292 m_pTarget->OnDragOver(pt.x, pt.y, result)
293 );
294 }
295 else {
296 *pdwEffect = DROPEFFECT_NONE;
297 }
298
299 // update drag image
300 m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y,
301 ConvertDragEffectToResult(*pdwEffect));
302
303 return S_OK;
304}
305
306// Name : wxIDropTarget::DragLeave
307// Purpose : Informs the drop target that the operation has left its window.
308// Returns : S_OK
309// Notes : good place to do any clean-up
310STDMETHODIMP wxIDropTarget::DragLeave()
311{
312 wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragLeave"));
313
314 // remove the UI feedback
315 m_pTarget->OnLeave();
316
317 // release the held object
318 RELEASE_AND_NULL(m_pIDataObject);
319
320 // update drag image
321 m_pTarget->MSWUpdateDragImageOnLeave();
322
323 return S_OK;
324}
325
326// Name : wxIDropTarget::Drop
327// Purpose : Instructs the drop target to paste data that was just now
328// dropped on it.
329// Returns : S_OK
330// Params : [in] IDataObject *pIDataSource the data to paste
331// [in] DWORD grfKeyState kbd & mouse state
332// [in] POINTL pt where the drop occurred?
333// [in/out]DWORD *pdwEffect operation effect
334// Notes :
335STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
336 DWORD grfKeyState,
337 POINTL pt,
338 DWORD *pdwEffect)
339{
340 wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::Drop"));
341
342 // TODO I don't know why there is this parameter, but so far I assume
343 // that it's the same we've already got in DragEnter
344 wxASSERT( m_pIDataObject == pIDataSource );
345
346 // we need client coordinates to pass to wxWin functions
347 if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
348 {
349 wxLogLastError(wxT("ScreenToClient"));
350 }
351
352 // first ask the drop target if it wants data
353 if ( m_pTarget->OnDrop(pt.x, pt.y) ) {
354 // it does, so give it the data source
355 m_pTarget->MSWSetDataSource(pIDataSource);
356
357 // and now it has the data
358 wxDragResult rc = ConvertDragEffectToResult(
359 GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
360 rc = m_pTarget->OnData(pt.x, pt.y, rc);
361 if ( wxIsDragResultOk(rc) ) {
362 // operation succeeded
363 *pdwEffect = ConvertDragResultToEffect(rc);
364 }
365 else {
366 *pdwEffect = DROPEFFECT_NONE;
367 }
368 }
369 else {
370 // OnDrop() returned false, no need to copy data
371 *pdwEffect = DROPEFFECT_NONE;
372 }
373
374 // release the held object
375 RELEASE_AND_NULL(m_pIDataObject);
376
377 // update drag image
378 m_pTarget->MSWUpdateDragImageOnData(pt.x, pt.y,
379 ConvertDragEffectToResult(*pdwEffect));
380
381 return S_OK;
382}
383
384// ============================================================================
385// wxDropTarget implementation
386// ============================================================================
387
388// ----------------------------------------------------------------------------
389// ctor/dtor
390// ----------------------------------------------------------------------------
391
392wxDropTarget::wxDropTarget(wxDataObject *dataObj)
393 : wxDropTargetBase(dataObj),
394 m_dropTargetHelper(NULL)
395{
396 // create an IDropTarget implementation which will notify us about d&d
397 // operations.
398 m_pIDropTarget = new wxIDropTarget(this);
399 m_pIDropTarget->AddRef();
400}
401
402wxDropTarget::~wxDropTarget()
403{
404 ReleaseInterface(m_pIDropTarget);
405}
406
407// ----------------------------------------------------------------------------
408// [un]register drop handler
409// ----------------------------------------------------------------------------
410
411bool wxDropTarget::Register(WXHWND hwnd)
412{
413 // FIXME
414 // RegisterDragDrop not available on Windows CE >= 400?
415 // Or maybe we can dynamically load them from ceshell.dll
416 // or similar.
417#if defined(__WXWINCE__) && _WIN32_WCE >= 400
418 wxUnusedVar(hwnd);
419 return false;
420#else
421 HRESULT hr;
422
423 // May exist in later WinCE versions
424#ifndef __WXWINCE__
425 hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE);
426 if ( FAILED(hr) ) {
427 wxLogApiError(wxT("CoLockObjectExternal"), hr);
428 return false;
429 }
430#endif
431
432 hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
433 if ( FAILED(hr) ) {
434 // May exist in later WinCE versions
435#ifndef __WXWINCE__
436 ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
437#endif
438 wxLogApiError(wxT("RegisterDragDrop"), hr);
439 return false;
440 }
441
442 // we will need the window handle for coords transformation later
443 m_pIDropTarget->SetHwnd((HWND)hwnd);
444
445 MSWInitDragImageSupport();
446
447 return true;
448#endif
449}
450
451void wxDropTarget::Revoke(WXHWND hwnd)
452{
453#if defined(__WXWINCE__) && _WIN32_WCE >= 400
454 // Not available, see note above
455 wxUnusedVar(hwnd);
456#else
457 HRESULT hr = ::RevokeDragDrop((HWND) hwnd);
458
459 if ( FAILED(hr) ) {
460 wxLogApiError(wxT("RevokeDragDrop"), hr);
461 }
462
463 // May exist in later WinCE versions
464#ifndef __WXWINCE__
465 ::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE);
466#endif
467
468 MSWEndDragImageSupport();
469
470 // remove window reference
471 m_pIDropTarget->SetHwnd(0);
472#endif
473}
474
475// ----------------------------------------------------------------------------
476// base class pure virtuals
477// ----------------------------------------------------------------------------
478
479// OnDrop() is called only if we previously returned true from
480// IsAcceptedData(), so no need to check anything here
481bool wxDropTarget::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
482{
483 return true;
484}
485
486// copy the data from the data source to the target data object
487bool wxDropTarget::GetData()
488{
489 wxDataFormat format = MSWGetSupportedFormat(m_pIDataSource);
490 if ( format == wxDF_INVALID ) {
491 return false;
492 }
493
494 STGMEDIUM stm;
495 FORMATETC fmtMemory;
496 fmtMemory.cfFormat = format;
497 fmtMemory.ptd = NULL;
498 fmtMemory.dwAspect = DVASPECT_CONTENT;
499 fmtMemory.lindex = -1;
500 fmtMemory.tymed = TYMED_HGLOBAL; // TODO to add other media
501
502 bool rc = false;
503
504 HRESULT hr = m_pIDataSource->GetData(&fmtMemory, &stm);
505 if ( SUCCEEDED(hr) ) {
506 IDataObject *dataObject = m_dataObject->GetInterface();
507
508 hr = dataObject->SetData(&fmtMemory, &stm, TRUE);
509 if ( SUCCEEDED(hr) ) {
510 rc = true;
511 }
512 else {
513 wxLogApiError(wxT("IDataObject::SetData()"), hr);
514 }
515 }
516 else {
517 wxLogApiError(wxT("IDataObject::GetData()"), hr);
518 }
519
520 return rc;
521}
522
523// ----------------------------------------------------------------------------
524// callbacks used by wxIDropTarget
525// ----------------------------------------------------------------------------
526
527// we need a data source, so wxIDropTarget gives it to us using this function
528void wxDropTarget::MSWSetDataSource(IDataObject *pIDataSource)
529{
530 m_pIDataSource = pIDataSource;
531}
532
533// determine if we accept data of this type
534bool wxDropTarget::MSWIsAcceptedData(IDataObject *pIDataSource) const
535{
536 return MSWGetSupportedFormat(pIDataSource) != wxDF_INVALID;
537}
538
539// ----------------------------------------------------------------------------
540// helper functions
541// ----------------------------------------------------------------------------
542
543wxDataFormat wxDropTarget::GetMatchingPair()
544{
545 return MSWGetSupportedFormat( m_pIDataSource );
546}
547
548wxDataFormat wxDropTarget::MSWGetSupportedFormat(IDataObject *pIDataSource) const
549{
550 // this strucutre describes a data of any type (first field will be
551 // changing) being passed through global memory block.
552 static FORMATETC s_fmtMemory = {
553 0,
554 NULL,
555 DVASPECT_CONTENT,
556 -1,
557 TYMED_HGLOBAL // TODO is it worth supporting other tymeds here?
558 };
559
560 // get the list of supported formats
561 size_t nFormats = m_dataObject->GetFormatCount(wxDataObject::Set);
562 wxDataFormat format;
563 wxDataFormat *formats;
564 formats = nFormats == 1 ? &format : new wxDataFormat[nFormats];
565
566 m_dataObject->GetAllFormats(formats, wxDataObject::Set);
567
568 // cycle through all supported formats
569 size_t n;
570 for ( n = 0; n < nFormats; n++ ) {
571 s_fmtMemory.cfFormat = formats[n];
572
573 // NB: don't use SUCCEEDED macro here: QueryGetData returns S_FALSE
574 // for file drag and drop (format == CF_HDROP)
575 if ( pIDataSource->QueryGetData(&s_fmtMemory) == S_OK ) {
576 format = formats[n];
577
578 break;
579 }
580 }
581
582 if ( formats != &format ) {
583 // free memory if we allocated it
584 delete [] formats;
585 }
586
587 return n < nFormats ? format : wxFormatInvalid;
588}
589
590// ----------------------------------------------------------------------------
591// drag image functions
592// ----------------------------------------------------------------------------
593
594void
595wxDropTarget::MSWEndDragImageSupport()
596{
597 // release drop target helper
598 if ( m_dropTargetHelper != NULL )
599 {
600 m_dropTargetHelper->Release();
601 m_dropTargetHelper = NULL;
602 }
603}
604
605void
606wxDropTarget::MSWInitDragImageSupport()
607{
608 // Use the default drop target helper to show shell drag images
609 CoCreateInstance(wxCLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER,
610 wxIID_IDropTargetHelper, (LPVOID*)&m_dropTargetHelper);
611}
612
613void
614wxDropTarget::MSWUpdateDragImageOnData(wxCoord x,
615 wxCoord y,
616 wxDragResult dragResult)
617{
618 // call corresponding event on drop target helper
619 if ( m_dropTargetHelper != NULL )
620 {
621 POINT pt = {x, y};
622 DWORD dwEffect = ConvertDragResultToEffect(dragResult);
623 m_dropTargetHelper->Drop(m_pIDataSource, &pt, dwEffect);
624 }
625}
626
627void
628wxDropTarget::MSWUpdateDragImageOnDragOver(wxCoord x,
629 wxCoord y,
630 wxDragResult dragResult)
631{
632 // call corresponding event on drop target helper
633 if ( m_dropTargetHelper != NULL )
634 {
635 POINT pt = {x, y};
636 DWORD dwEffect = ConvertDragResultToEffect(dragResult);
637 m_dropTargetHelper->DragOver(&pt, dwEffect);
638 }
639}
640
641void
642wxDropTarget::MSWUpdateDragImageOnEnter(wxCoord x,
643 wxCoord y,
644 wxDragResult dragResult)
645{
646 // call corresponding event on drop target helper
647 if ( m_dropTargetHelper != NULL )
648 {
649 POINT pt = {x, y};
650 DWORD dwEffect = ConvertDragResultToEffect(dragResult);
651 m_dropTargetHelper->DragEnter(m_pIDropTarget->GetHWND(), m_pIDataSource, &pt, dwEffect);
652 }
653}
654
655void
656wxDropTarget::MSWUpdateDragImageOnLeave()
657{
658 // call corresponding event on drop target helper
659 if ( m_dropTargetHelper != NULL )
660 {
661 m_dropTargetHelper->DragLeave();
662 }
663}
664
665// ----------------------------------------------------------------------------
666// private functions
667// ----------------------------------------------------------------------------
668
669static wxDragResult ConvertDragEffectToResult(DWORD dwEffect)
670{
671 switch ( dwEffect ) {
672 case DROPEFFECT_COPY:
673 return wxDragCopy;
674
675 case DROPEFFECT_LINK:
676 return wxDragLink;
677
678 case DROPEFFECT_MOVE:
679 return wxDragMove;
680
681 default:
682 wxFAIL_MSG(wxT("invalid value in ConvertDragEffectToResult"));
683 // fall through
684
685 case DROPEFFECT_NONE:
686 return wxDragNone;
687 }
688}
689
690static DWORD ConvertDragResultToEffect(wxDragResult result)
691{
692 switch ( result ) {
693 case wxDragCopy:
694 return DROPEFFECT_COPY;
695
696 case wxDragLink:
697 return DROPEFFECT_LINK;
698
699 case wxDragMove:
700 return DROPEFFECT_MOVE;
701
702 default:
703 wxFAIL_MSG(wxT("invalid value in ConvertDragResultToEffect"));
704 // fall through
705
706 case wxDragNone:
707 return DROPEFFECT_NONE;
708 }
709}
710
711#endif // wxUSE_OLE && wxUSE_DRAG_AND_DROP