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