]> git.saurik.com Git - wxWidgets.git/blame - src/msw/ole/droptgt.cpp
Don't use DDEExec registry key in wxMSW wxExecute() if it's empty.
[wxWidgets.git] / src / msw / ole / droptgt.cpp
CommitLineData
bbf1f0e5 1///////////////////////////////////////////////////////////////////////////////
521bf4ff 2// Name: src/msw/ole/droptgt.cpp
bbf1f0e5
KB
3// Purpose: wxDropTarget implementation
4// Author: Vadim Zeitlin
3f480da3
VZ
5// Modified by:
6// Created:
bbf1f0e5 7// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 8// Licence: wxWindows licence
bbf1f0e5
KB
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// Declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
bbf1f0e5 19// For compilers that support precompilation, includes "wx.h".
bbf1f0e5
KB
20#include "wx/wxprec.h"
21
22#if defined(__BORLANDC__)
e4db172a 23 #pragma hdrstop
bbf1f0e5
KB
24#endif
25
21709999 26#if wxUSE_OLE && wxUSE_DRAG_AND_DROP
bbf1f0e5 27
e4db172a 28#ifndef WX_PRECOMP
57bd4c60 29 #include "wx/msw/wrapwin.h"
e4db172a
WS
30 #include "wx/log.h"
31#endif
32
4676948b 33#include "wx/msw/private.h"
bbf1f0e5 34
4676948b
JS
35#ifdef __WXWINCE__
36 #include <winreg.h>
37 #include <ole2.h>
38#endif
39
bbf1f0e5 40#ifdef __WIN32__
b64f0a5f 41 #if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS
3f480da3
VZ
42 #include <shlobj.h> // for DROPFILES structure
43 #endif
bbf1f0e5 44#else
3f480da3 45 #include <shellapi.h>
bbf1f0e5
KB
46#endif
47
9e2896e5 48#include "wx/dnd.h"
bbf1f0e5 49
3f480da3 50#include "wx/msw/ole/oleutils.h"
bbf1f0e5 51
4d604ad3
VZ
52#include <initguid.h>
53
54// Some (very) old SDKs don't define IDropTargetHelper, so define our own
55// version of it here.
56struct 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
70namespace
71{
b3d774bf
VZ
72 DEFINE_GUID(wxCLSID_DragDropHelper,
73 0x4657278A,0x411B,0x11D2,0x83,0x9A,0x00,0xC0,0x4F,0xD9,0x18,0xD0);
4d604ad3
VZ
74 DEFINE_GUID(wxIID_IDropTargetHelper,
75 0x4657278B,0x411B,0x11D2,0x83,0x9A,0x00,0xC0,0x4F,0xD9,0x18,0xD0);
76}
77
bbf1f0e5
KB
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
84class wxIDropTarget : public IDropTarget
85{
86public:
8ee9d618 87 wxIDropTarget(wxDropTarget *p);
33ac7e6f 88 virtual ~wxIDropTarget();
bbf1f0e5 89
8ee9d618 90 // accessors for wxDropTarget
40375032 91 HWND GetHWND() const { return m_hwnd; }
8ee9d618 92 void SetHwnd(HWND hwnd) { m_hwnd = hwnd; }
bbf1f0e5 93
8ee9d618
VZ
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;
bbf1f0e5
KB
101
102protected:
8ee9d618
VZ
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
bbf1f0e5 107
8ee9d618 108 // get default drop effect for given keyboard flags
c25db584 109 static DWORD GetDropEffect(DWORD flags, wxDragResult defaultAction, DWORD pdwEffect);
22f3361e 110
c0c133e1 111 wxDECLARE_NO_COPY_CLASS(wxIDropTarget);
bbf1f0e5
KB
112};
113
c9057ae1
VZ
114// ----------------------------------------------------------------------------
115// private functions
116// ----------------------------------------------------------------------------
117
118static wxDragResult ConvertDragEffectToResult(DWORD dwEffect);
119static DWORD ConvertDragResultToEffect(wxDragResult result);
120
bbf1f0e5
KB
121// ============================================================================
122// wxIDropTarget implementation
123// ============================================================================
124
8ee9d618 125// Name : static wxIDropTarget::GetDropEffect
bbf1f0e5 126// Purpose : determine the drop operation from keyboard/mouse state.
3f480da3 127// Returns : DWORD combined from DROPEFFECT_xxx constants
08291def
VZ
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
03647350 131// [in] DWORD pdwEffect the supported actions of the drop
08291def 132// source passed to IDropTarget methods
bbf1f0e5 133// Notes : We do "move" normally and "copy" if <Ctrl> is pressed,
3f480da3 134// which is the standard behaviour (currently there is no
bbf1f0e5 135// way to redefine it)
c25db584
VZ
136DWORD wxIDropTarget::GetDropEffect(DWORD flags,
137 wxDragResult defaultAction,
138 DWORD pdwEffect)
bbf1f0e5 139{
c25db584
VZ
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;
bbf1f0e5
KB
161}
162
163wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget)
3f480da3 164{
bbf1f0e5 165 m_pTarget = pTarget;
3f480da3 166 m_pIDataObject = NULL;
bbf1f0e5
KB
167}
168
3f480da3
VZ
169wxIDropTarget::~wxIDropTarget()
170{
bbf1f0e5
KB
171}
172
173BEGIN_IID_TABLE(wxIDropTarget)
174 ADD_IID(Unknown)
175 ADD_IID(DropTarget)
176END_IID_TABLE;
177
178IMPLEMENT_IUNKNOWN_METHODS(wxIDropTarget)
179
bbf1f0e5
KB
180// Name : wxIDropTarget::DragEnter
181// Purpose : Called when the mouse enters the window (dragging something)
182// Returns : S_OK
08291def
VZ
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
3f480da3 189// Notes :
bbf1f0e5
KB
190STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
191 DWORD grfKeyState,
192 POINTL pt,
193 DWORD *pdwEffect)
194{
c5639a87 195 wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter"));
bbf1f0e5 196
c5639a87 197 wxASSERT_MSG( m_pIDataObject == NULL,
9a83f860 198 wxT("drop target must have data object") );
c5639a87
VZ
199
200 // show the list of formats supported by the source data object for the
444ad3a7 201 // debugging purposes, this is quite useful sometimes - please don't remove
c5639a87
VZ
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 {
9a83f860 209 wxLogDebug(wxT("Drop source supports format %s"),
c5639a87
VZ
210 wxDataObject::GetFormatName(fmt.cfFormat));
211 }
212
213 penumFmt->Release();
214 }
215 else
216 {
9a83f860 217 wxLogLastError(wxT("IDataObject::EnumFormatEtc"));
c5639a87
VZ
218 }
219#endif // 0
bbf1f0e5 220
81a1c686
RR
221 // for use in OnEnter and OnDrag calls
222 m_pTarget->MSWSetDataSource(pIDataSource);
03647350 223
8ee9d618
VZ
224 // get hold of the data object
225 m_pIDataObject = pIDataSource;
226 m_pIDataObject->AddRef();
bbf1f0e5 227
40375032
VZ
228 if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) {
229 // we don't accept this kind of data
230 *pdwEffect = DROPEFFECT_NONE;
231 }
232 else
8ee9d618 233 {
40375032
VZ
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 );
8ee9d618 246 }
bbf1f0e5 247
40375032
VZ
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);
8ee9d618
VZ
252
253 return S_OK;
bbf1f0e5
KB
254}
255
40375032
VZ
256
257
bbf1f0e5
KB
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
08291def
VZ
262// Params : [in] DWORD grfKeyState kbd & mouse state
263// [in] POINTL pt mouse coordinates
264// [in/out]LPDWORD pdwEffect current effect flag
3f480da3 265// Notes : We're called on every WM_MOUSEMOVE, so this function should be
bbf1f0e5
KB
266// very efficient.
267STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState,
268 POINTL pt,
269 LPDWORD pdwEffect)
270{
8ee9d618 271 // there are too many of them... wxLogDebug("IDropTarget::DragOver");
bbf1f0e5 272
8ee9d618
VZ
273 wxDragResult result;
274 if ( m_pIDataObject ) {
917ae499 275 result = ConvertDragEffectToResult(
c25db584 276 GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
8ee9d618
VZ
277 }
278 else {
279 // can't accept data anyhow normally
280 result = wxDragNone;
281 }
c9057ae1 282
4095fb14
VZ
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 }
c9057ae1 289
4095fb14
VZ
290 *pdwEffect = ConvertDragResultToEffect(
291 m_pTarget->OnDragOver(pt.x, pt.y, result)
292 );
293 }
294 else {
295 *pdwEffect = DROPEFFECT_NONE;
296 }
8ee9d618 297
40375032
VZ
298 // update drag image
299 m_pTarget->MSWUpdateDragImageOnDragOver(pt.x, pt.y,
300 ConvertDragEffectToResult(*pdwEffect));
301
8ee9d618 302 return S_OK;
bbf1f0e5
KB
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
309STDMETHODIMP wxIDropTarget::DragLeave()
310{
c5639a87 311 wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragLeave"));
bbf1f0e5
KB
312
313 // remove the UI feedback
314 m_pTarget->OnLeave();
315
316 // release the held object
317 RELEASE_AND_NULL(m_pIDataObject);
3f480da3 318
40375032
VZ
319 // update drag image
320 m_pTarget->MSWUpdateDragImageOnLeave();
321
bbf1f0e5
KB
322 return S_OK;
323}
324
325// Name : wxIDropTarget::Drop
3f480da3 326// Purpose : Instructs the drop target to paste data that was just now
bbf1f0e5
KB
327// dropped on it.
328// Returns : S_OK
08291def
VZ
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
3f480da3
VZ
333// Notes :
334STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
335 DWORD grfKeyState,
336 POINTL pt,
bbf1f0e5
KB
337 DWORD *pdwEffect)
338{
c5639a87 339 wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::Drop"));
9e2896e5
VZ
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
8ee9d618
VZ
345 // we need client coordinates to pass to wxWin functions
346 if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
347 {
f6bcfd97 348 wxLogLastError(wxT("ScreenToClient"));
8ee9d618
VZ
349 }
350
9e2896e5
VZ
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
81a1c686 354 m_pTarget->MSWSetDataSource(pIDataSource);
9e2896e5
VZ
355
356 // and now it has the data
917ae499 357 wxDragResult rc = ConvertDragEffectToResult(
c25db584 358 GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
87a1e308 359 rc = m_pTarget->OnData(pt.x, pt.y, rc);
8ee9d618 360 if ( wxIsDragResultOk(rc) ) {
9e2896e5 361 // operation succeeded
8ee9d618 362 *pdwEffect = ConvertDragResultToEffect(rc);
9e2896e5 363 }
c25db584
VZ
364 else {
365 *pdwEffect = DROPEFFECT_NONE;
366 }
367 }
368 else {
369 // OnDrop() returned false, no need to copy data
370 *pdwEffect = DROPEFFECT_NONE;
bbf1f0e5 371 }
bbf1f0e5 372
9e2896e5
VZ
373 // release the held object
374 RELEASE_AND_NULL(m_pIDataObject);
bbf1f0e5 375
40375032
VZ
376 // update drag image
377 m_pTarget->MSWUpdateDragImageOnData(pt.x, pt.y,
378 ConvertDragEffectToResult(*pdwEffect));
379
9e2896e5 380 return S_OK;
bbf1f0e5
KB
381}
382
383// ============================================================================
384// wxDropTarget implementation
385// ============================================================================
386
387// ----------------------------------------------------------------------------
388// ctor/dtor
389// ----------------------------------------------------------------------------
390
9e2896e5 391wxDropTarget::wxDropTarget(wxDataObject *dataObj)
40375032
VZ
392 : wxDropTargetBase(dataObj),
393 m_dropTargetHelper(NULL)
bbf1f0e5 394{
9e2896e5
VZ
395 // create an IDropTarget implementation which will notify us about d&d
396 // operations.
397 m_pIDropTarget = new wxIDropTarget(this);
398 m_pIDropTarget->AddRef();
bbf1f0e5
KB
399}
400
401wxDropTarget::~wxDropTarget()
402{
9e2896e5 403 ReleaseInterface(m_pIDropTarget);
bbf1f0e5
KB
404}
405
406// ----------------------------------------------------------------------------
407// [un]register drop handler
408// ----------------------------------------------------------------------------
409
410bool wxDropTarget::Register(WXHWND hwnd)
411{
a40b3f5d
JS
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
abf912c5 417 wxUnusedVar(hwnd);
0a0e6a5b 418 return false;
a40b3f5d 419#else
4cb88a72
JS
420 HRESULT hr;
421
422 // May exist in later WinCE versions
423#ifndef __WXWINCE__
424 hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE);
9e2896e5 425 if ( FAILED(hr) ) {
161f4f73 426 wxLogApiError(wxT("CoLockObjectExternal"), hr);
0a0e6a5b 427 return false;
9e2896e5 428 }
4cb88a72 429#endif
bbf1f0e5 430
9e2896e5
VZ
431 hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
432 if ( FAILED(hr) ) {
4cb88a72
JS
433 // May exist in later WinCE versions
434#ifndef __WXWINCE__
9e2896e5 435 ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
4cb88a72 436#endif
161f4f73 437 wxLogApiError(wxT("RegisterDragDrop"), hr);
0a0e6a5b 438 return false;
9e2896e5 439 }
bbf1f0e5 440
8ee9d618
VZ
441 // we will need the window handle for coords transformation later
442 m_pIDropTarget->SetHwnd((HWND)hwnd);
443
40375032
VZ
444 MSWInitDragImageSupport();
445
0a0e6a5b 446 return true;
a40b3f5d 447#endif
bbf1f0e5
KB
448}
449
450void wxDropTarget::Revoke(WXHWND hwnd)
451{
a40b3f5d
JS
452#if defined(__WXWINCE__) && _WIN32_WCE >= 400
453 // Not available, see note above
abf912c5 454 wxUnusedVar(hwnd);
a40b3f5d 455#else
9e2896e5 456 HRESULT hr = ::RevokeDragDrop((HWND) hwnd);
bbf1f0e5 457
9e2896e5 458 if ( FAILED(hr) ) {
161f4f73 459 wxLogApiError(wxT("RevokeDragDrop"), hr);
9e2896e5 460 }
bbf1f0e5 461
4cb88a72
JS
462 // May exist in later WinCE versions
463#ifndef __WXWINCE__
9e2896e5 464 ::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE);
4cb88a72 465#endif
8ee9d618 466
40375032
VZ
467 MSWEndDragImageSupport();
468
469 // remove window reference
8ee9d618 470 m_pIDropTarget->SetHwnd(0);
a40b3f5d 471#endif
bbf1f0e5
KB
472}
473
474// ----------------------------------------------------------------------------
9e2896e5 475// base class pure virtuals
bbf1f0e5 476// ----------------------------------------------------------------------------
9e2896e5 477
0a0e6a5b 478// OnDrop() is called only if we previously returned true from
9e2896e5
VZ
479// IsAcceptedData(), so no need to check anything here
480bool wxDropTarget::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
481{
0a0e6a5b 482 return true;
9e2896e5
VZ
483}
484
485// copy the data from the data source to the target data object
486bool wxDropTarget::GetData()
bbf1f0e5 487{
81a1c686 488 wxDataFormat format = MSWGetSupportedFormat(m_pIDataSource);
9e2896e5 489 if ( format == wxDF_INVALID ) {
0a0e6a5b 490 return false;
9e2896e5
VZ
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
0a0e6a5b 501 bool rc = false;
9e2896e5
VZ
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) ) {
0a0e6a5b 509 rc = true;
9e2896e5
VZ
510 }
511 else {
444ad3a7 512 wxLogApiError(wxT("IDataObject::SetData()"), hr);
9e2896e5
VZ
513 }
514 }
515 else {
444ad3a7 516 wxLogApiError(wxT("IDataObject::GetData()"), hr);
bbf1f0e5 517 }
bbf1f0e5 518
9e2896e5 519 return rc;
bbf1f0e5
KB
520}
521
9e2896e5
VZ
522// ----------------------------------------------------------------------------
523// callbacks used by wxIDropTarget
524// ----------------------------------------------------------------------------
bbf1f0e5 525
9e2896e5 526// we need a data source, so wxIDropTarget gives it to us using this function
81a1c686 527void wxDropTarget::MSWSetDataSource(IDataObject *pIDataSource)
bbf1f0e5 528{
9e2896e5 529 m_pIDataSource = pIDataSource;
bbf1f0e5
KB
530}
531
9e2896e5 532// determine if we accept data of this type
81a1c686 533bool wxDropTarget::MSWIsAcceptedData(IDataObject *pIDataSource) const
bbf1f0e5 534{
81a1c686 535 return MSWGetSupportedFormat(pIDataSource) != wxDF_INVALID;
bbf1f0e5
KB
536}
537
9e2896e5
VZ
538// ----------------------------------------------------------------------------
539// helper functions
540// ----------------------------------------------------------------------------
541
51c9c13c
RR
542wxDataFormat wxDropTarget::GetMatchingPair()
543{
81a1c686 544 return MSWGetSupportedFormat( m_pIDataSource );
51c9c13c
RR
545}
546
81a1c686 547wxDataFormat wxDropTarget::MSWGetSupportedFormat(IDataObject *pIDataSource) const
bbf1f0e5 548{
9e2896e5
VZ
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);
33ac7e6f 561 wxDataFormat format;
c5639a87 562 wxDataFormat *formats;
9e2896e5
VZ
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
90bc25c7 586 return n < nFormats ? format : wxFormatInvalid;
bbf1f0e5
KB
587}
588
40375032
VZ
589// ----------------------------------------------------------------------------
590// drag image functions
591// ----------------------------------------------------------------------------
592
593void
594wxDropTarget::MSWEndDragImageSupport()
595{
596 // release drop target helper
597 if ( m_dropTargetHelper != NULL )
598 {
599 m_dropTargetHelper->Release();
600 m_dropTargetHelper = NULL;
601 }
602}
603
604void
605wxDropTarget::MSWInitDragImageSupport()
606{
607 // Use the default drop target helper to show shell drag images
b3d774bf 608 CoCreateInstance(wxCLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER,
4d604ad3 609 wxIID_IDropTargetHelper, (LPVOID*)&m_dropTargetHelper);
40375032
VZ
610}
611
612void
613wxDropTarget::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
626void
627wxDropTarget::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
640void
641wxDropTarget::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
654void
655wxDropTarget::MSWUpdateDragImageOnLeave()
656{
657 // call corresponding event on drop target helper
658 if ( m_dropTargetHelper != NULL )
659 {
660 m_dropTargetHelper->DragLeave();
661 }
662}
663
c9057ae1
VZ
664// ----------------------------------------------------------------------------
665// private functions
666// ----------------------------------------------------------------------------
667
668static wxDragResult ConvertDragEffectToResult(DWORD dwEffect)
669{
670 switch ( dwEffect ) {
671 case DROPEFFECT_COPY:
672 return wxDragCopy;
673
e6d318c2
RD
674 case DROPEFFECT_LINK:
675 return wxDragLink;
676
c9057ae1
VZ
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
689static DWORD ConvertDragResultToEffect(wxDragResult result)
690{
691 switch ( result ) {
692 case wxDragCopy:
693 return DROPEFFECT_COPY;
694
e6d318c2
RD
695 case wxDragLink:
696 return DROPEFFECT_LINK;
697
c9057ae1
VZ
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
e4db172a 710#endif // wxUSE_OLE && wxUSE_DRAG_AND_DROP