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