4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 static const IDropTargetVtbl IDropTargetImpl_Vtbl
;
31 const IDropTargetVtbl
*lpVtbl
;
34 IDropTargetHelper
*DropTargetHelper
;
37 DROPTARGET_CALLBACKS Callbacks
;
43 IUnknown_from_impl(IDropTargetImpl
*This
)
45 return (IUnknown
*)&This
->lpVtbl
;
49 IDropTarget_from_impl(IDropTargetImpl
*This
)
51 return (IDropTarget
*)&This
->lpVtbl
;
54 static IDropTargetImpl
*
55 impl_from_IDropTarget(IDropTarget
*iface
)
57 return (IDropTargetImpl
*)((ULONG_PTR
)iface
- FIELD_OFFSET(IDropTargetImpl
,
62 IDropTargetImpl_Free(IDropTargetImpl
*This
)
64 IDropTargetHelper_Release(This
->DropTargetHelper
);
67 static ULONG STDMETHODCALLTYPE
68 IDropTargetImpl_Release(IN OUT IDropTarget
*iface
)
70 IDropTargetImpl
*This
= impl_from_IDropTarget(iface
);
73 Ret
= InterlockedDecrement(&This
->Ref
);
75 IDropTargetImpl_Free(This
);
80 static ULONG STDMETHODCALLTYPE
81 IDropTargetImpl_AddRef(IN OUT IDropTarget
*iface
)
83 IDropTargetImpl
*This
= impl_from_IDropTarget(iface
);
85 return InterlockedIncrement(&This
->Ref
);
88 static HRESULT STDMETHODCALLTYPE
89 IDropTargetImpl_QueryInterface(IN OUT IDropTarget
*iface
,
93 IDropTargetImpl
*This
;
98 This
= impl_from_IDropTarget(iface
);
103 *ppvObj
= IUnknown_from_impl(This
);
105 else if (IsEqualIID(riid
,
108 *ppvObj
= IDropTarget_from_impl(This
);
113 return E_NOINTERFACE
;
116 IDropTargetImpl_AddRef(iface
);
121 CreateDropTarget(IN HWND hwndTarget
,
122 IN DWORD nSupportedFormats
,
123 IN
const FORMATETC
*Formats OPTIONAL
,
124 IN PVOID Context OPTIONAL
,
125 IN
const DROPTARGET_CALLBACKS
*Callbacks OPTIONAL
)
127 IDropTargetImpl
*This
;
130 This
= (IDropTargetImpl
*)HeapAlloc(hProcessHeap
,
132 FIELD_OFFSET(IDropTargetImpl
,
133 Formats
[nSupportedFormats
]));
139 This
->lpVtbl
= &IDropTargetImpl_Vtbl
;
141 This
->hwndTarget
= hwndTarget
;
142 This
->FormatsCount
= nSupportedFormats
;
143 if (nSupportedFormats
!= 0)
145 CopyMemory(This
->Formats
,
147 sizeof(Formats
[0]) * nSupportedFormats
);
150 This
->Context
= Context
;
151 if (Callbacks
!= NULL
)
153 CopyMemory(&This
->Callbacks
,
158 hr
= CoCreateInstance(&CLSID_DragDropHelper
,
160 CLSCTX_INPROC_SERVER
,
161 &IID_IDropTargetHelper
,
162 (PVOID
)&This
->DropTargetHelper
);
166 HeapFree(hProcessHeap
,
172 return IDropTarget_from_impl(This
);
178 static const FORMATETC
*
179 IDropTargetImpl_FindSupportedFormat(IN OUT IDropTargetImpl
*This
,
180 IN IDataObject
*pDataObject
)
182 FORMATETC
*Current
, *Last
;
185 /* NOTE: we could use IDataObject::EnumFormatEtc(),
186 but this appears to be a lot easier! */
187 Last
= This
->Formats
+ This
->FormatsCount
;
188 for (Current
= This
->Formats
;
192 hr
= IDataObject_QueryGetData(pDataObject
,
201 static HRESULT STDMETHODCALLTYPE
202 IDropTargetImpl_DragEnter(IN OUT IDropTarget
*iface
,
203 IN IDataObject
*pDataObject
,
204 IN DWORD grfKeyState
,
206 IN OUT DWORD
*pdwEffect
)
208 IDropTargetImpl
*This
= impl_from_IDropTarget(iface
);
209 const FORMATETC
*Format
;
212 if (pDataObject
== NULL
)
215 This
->CanDrop
= FALSE
;
217 hr
= IDropTargetHelper_DragEnter(This
->DropTargetHelper
,
225 Format
= IDropTargetImpl_FindSupportedFormat(This
,
229 /* We found a format that we support! */
230 if (This
->Callbacks
.OnDragEnter
!= NULL
)
232 hr
= This
->Callbacks
.OnDragEnter(iface
,
241 This
->CanDrop
= TRUE
;
244 /* Special return value by the callback routine,
245 doesn't want to allow dragging */
246 *pdwEffect
= DROPEFFECT_NONE
;
253 *pdwEffect
= DROPEFFECT_NONE
;
258 *pdwEffect
= DROPEFFECT_NONE
;
261 *pdwEffect
= DROPEFFECT_NONE
;
267 static HRESULT STDMETHODCALLTYPE
268 IDropTargetImpl_DragOver(IN OUT IDropTarget
*iface
,
269 IN DWORD grfKeyState
,
271 IN OUT DWORD
*pdwEffect
)
273 IDropTargetImpl
*This
= impl_from_IDropTarget(iface
);
276 hr
= IDropTargetHelper_DragOver(This
->DropTargetHelper
,
284 if (This
->Callbacks
.OnDragOver
!= NULL
)
286 hr
= This
->Callbacks
.OnDragOver(iface
,
295 /* Special return value by the callback routine,
296 doesn't want to allow dropping here */
297 *pdwEffect
= DROPEFFECT_NONE
;
304 *pdwEffect
= DROPEFFECT_NONE
;
309 *pdwEffect
= DROPEFFECT_NONE
;
312 *pdwEffect
= DROPEFFECT_NONE
;
318 static HRESULT STDMETHODCALLTYPE
319 IDropTargetImpl_DragLeave(IN OUT IDropTarget
*iface
)
321 IDropTargetImpl
*This
= impl_from_IDropTarget(iface
);
324 hr
= IDropTargetHelper_DragLeave(This
->DropTargetHelper
);
327 if (This
->Callbacks
.OnDragLeave
!= NULL
)
329 hr
= This
->Callbacks
.OnDragLeave(iface
,
337 static HRESULT STDMETHODCALLTYPE
338 IDropTargetImpl_Drop(IN OUT IDropTarget
*iface
,
339 IN IDataObject
*pDataObject
,
340 IN DWORD grfKeyState
,
342 IN OUT DWORD
*pdwEffect
)
344 IDropTargetImpl
*This
= impl_from_IDropTarget(iface
);
345 const FORMATETC
*Format
;
348 if (pDataObject
== NULL
)
351 hr
= IDropTargetHelper_Drop(This
->DropTargetHelper
,
356 if (SUCCEEDED(hr
) && This
->CanDrop
)
358 Format
= IDropTargetImpl_FindSupportedFormat(This
,
362 /* We found a format that we support! */
363 if (This
->Callbacks
.OnDrop
!= NULL
)
365 hr
= This
->Callbacks
.OnDrop(iface
,
374 This
->CanDrop
= TRUE
;
377 /* Special return value by the callback routine,
378 doesn't want to allow dragging */
379 *pdwEffect
= DROPEFFECT_NONE
;
386 *pdwEffect
= DROPEFFECT_NONE
;
391 *pdwEffect
= DROPEFFECT_NONE
;
394 *pdwEffect
= DROPEFFECT_NONE
;
400 static const IDropTargetVtbl IDropTargetImpl_Vtbl
=
403 IDropTargetImpl_QueryInterface
,
404 IDropTargetImpl_AddRef
,
405 IDropTargetImpl_Release
,
407 IDropTargetImpl_DragEnter
,
408 IDropTargetImpl_DragOver
,
409 IDropTargetImpl_DragLeave
,