]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/droptgt.cpp
4f0b716dde85f6b0974fd0a8531144ff297755b7
[wxWidgets.git] / src / msw / ole / droptgt.cpp
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.
57 struct 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
71 namespace
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
85 class wxIDropTarget : public IDropTarget
86 {
87 public:
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
103 protected:
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
119 static wxDragResult ConvertDragEffectToResult(DWORD dwEffect);
120 static 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)
137 DWORD 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
164 wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget)
165 {
166 m_pTarget = pTarget;
167 m_pIDataObject = NULL;
168 }
169
170 wxIDropTarget::~wxIDropTarget()
171 {
172 }
173
174 BEGIN_IID_TABLE(wxIDropTarget)
175 ADD_IID(Unknown)
176 ADD_IID(DropTarget)
177 END_IID_TABLE;
178
179 IMPLEMENT_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 :
191 STDMETHODIMP 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.
268 STDMETHODIMP 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
310 STDMETHODIMP 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 :
335 STDMETHODIMP 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
392 wxDropTarget::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
402 wxDropTarget::~wxDropTarget()
403 {
404 ReleaseInterface(m_pIDropTarget);
405 }
406
407 // ----------------------------------------------------------------------------
408 // [un]register drop handler
409 // ----------------------------------------------------------------------------
410
411 bool 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
451 void 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
481 bool 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
487 bool 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
528 void wxDropTarget::MSWSetDataSource(IDataObject *pIDataSource)
529 {
530 m_pIDataSource = pIDataSource;
531 }
532
533 // determine if we accept data of this type
534 bool wxDropTarget::MSWIsAcceptedData(IDataObject *pIDataSource) const
535 {
536 return MSWGetSupportedFormat(pIDataSource) != wxDF_INVALID;
537 }
538
539 // ----------------------------------------------------------------------------
540 // helper functions
541 // ----------------------------------------------------------------------------
542
543 wxDataFormat wxDropTarget::GetMatchingPair()
544 {
545 return MSWGetSupportedFormat( m_pIDataSource );
546 }
547
548 wxDataFormat 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
594 void
595 wxDropTarget::MSWEndDragImageSupport()
596 {
597 // release drop target helper
598 if ( m_dropTargetHelper != NULL )
599 {
600 m_dropTargetHelper->Release();
601 m_dropTargetHelper = NULL;
602 }
603 }
604
605 void
606 wxDropTarget::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
613 void
614 wxDropTarget::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
627 void
628 wxDropTarget::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
641 void
642 wxDropTarget::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
655 void
656 wxDropTarget::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
669 static 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
690 static 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