Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendragdrop.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS Explorer 00003 * 00004 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <precomp.h> 00022 00023 static const IDropTargetVtbl IDropTargetImpl_Vtbl; 00024 00025 /* 00026 * IDropTarget 00027 */ 00028 00029 typedef struct 00030 { 00031 const IDropTargetVtbl *lpVtbl; 00032 LONG Ref; 00033 HWND hwndTarget; 00034 IDropTargetHelper *DropTargetHelper; 00035 PVOID Context; 00036 BOOL CanDrop; 00037 DROPTARGET_CALLBACKS Callbacks; 00038 DWORD FormatsCount; 00039 FORMATETC Formats[0]; 00040 } IDropTargetImpl; 00041 00042 static IUnknown * 00043 IUnknown_from_impl(IDropTargetImpl *This) 00044 { 00045 return (IUnknown *)&This->lpVtbl; 00046 } 00047 00048 static IDropTarget * 00049 IDropTarget_from_impl(IDropTargetImpl *This) 00050 { 00051 return (IDropTarget *)&This->lpVtbl; 00052 } 00053 00054 static IDropTargetImpl * 00055 impl_from_IDropTarget(IDropTarget *iface) 00056 { 00057 return (IDropTargetImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDropTargetImpl, 00058 lpVtbl)); 00059 } 00060 00061 static VOID 00062 IDropTargetImpl_Free(IDropTargetImpl *This) 00063 { 00064 IDropTargetHelper_Release(This->DropTargetHelper); 00065 } 00066 00067 static ULONG STDMETHODCALLTYPE 00068 IDropTargetImpl_Release(IN OUT IDropTarget *iface) 00069 { 00070 IDropTargetImpl *This = impl_from_IDropTarget(iface); 00071 ULONG Ret; 00072 00073 Ret = InterlockedDecrement(&This->Ref); 00074 if (Ret == 0) 00075 IDropTargetImpl_Free(This); 00076 00077 return Ret; 00078 } 00079 00080 static ULONG STDMETHODCALLTYPE 00081 IDropTargetImpl_AddRef(IN OUT IDropTarget *iface) 00082 { 00083 IDropTargetImpl *This = impl_from_IDropTarget(iface); 00084 00085 return InterlockedIncrement(&This->Ref); 00086 } 00087 00088 static HRESULT STDMETHODCALLTYPE 00089 IDropTargetImpl_QueryInterface(IN OUT IDropTarget *iface, 00090 IN REFIID riid, 00091 OUT LPVOID *ppvObj) 00092 { 00093 IDropTargetImpl *This; 00094 00095 if (ppvObj == NULL) 00096 return E_POINTER; 00097 00098 This = impl_from_IDropTarget(iface); 00099 00100 if (IsEqualIID(riid, 00101 &IID_IUnknown)) 00102 { 00103 *ppvObj = IUnknown_from_impl(This); 00104 } 00105 else if (IsEqualIID(riid, 00106 &IID_IDropTarget)) 00107 { 00108 *ppvObj = IDropTarget_from_impl(This); 00109 } 00110 else 00111 { 00112 *ppvObj = NULL; 00113 return E_NOINTERFACE; 00114 } 00115 00116 IDropTargetImpl_AddRef(iface); 00117 return S_OK; 00118 } 00119 00120 IDropTarget * 00121 CreateDropTarget(IN HWND hwndTarget, 00122 IN DWORD nSupportedFormats, 00123 IN const FORMATETC *Formats OPTIONAL, 00124 IN PVOID Context OPTIONAL, 00125 IN const DROPTARGET_CALLBACKS *Callbacks OPTIONAL) 00126 { 00127 IDropTargetImpl *This; 00128 HRESULT hr; 00129 00130 This = (IDropTargetImpl *)HeapAlloc(hProcessHeap, 00131 0, 00132 FIELD_OFFSET(IDropTargetImpl, 00133 Formats[nSupportedFormats])); 00134 if (This != NULL) 00135 { 00136 ZeroMemory(This, 00137 sizeof(*This)); 00138 00139 This->lpVtbl = &IDropTargetImpl_Vtbl; 00140 This->Ref = 1; 00141 This->hwndTarget = hwndTarget; 00142 This->FormatsCount = nSupportedFormats; 00143 if (nSupportedFormats != 0) 00144 { 00145 CopyMemory(This->Formats, 00146 Formats, 00147 sizeof(Formats[0]) * nSupportedFormats); 00148 } 00149 00150 This->Context = Context; 00151 if (Callbacks != NULL) 00152 { 00153 CopyMemory(&This->Callbacks, 00154 Callbacks, 00155 sizeof(*Callbacks)); 00156 } 00157 00158 hr = CoCreateInstance(&CLSID_DragDropHelper, 00159 NULL, 00160 CLSCTX_INPROC_SERVER, 00161 &IID_IDropTargetHelper, 00162 (PVOID)&This->DropTargetHelper); 00163 00164 if (!SUCCEEDED(hr)) 00165 { 00166 HeapFree(hProcessHeap, 00167 0, 00168 This); 00169 return NULL; 00170 } 00171 00172 return IDropTarget_from_impl(This); 00173 } 00174 00175 return NULL; 00176 } 00177 00178 static const FORMATETC * 00179 IDropTargetImpl_FindSupportedFormat(IN OUT IDropTargetImpl *This, 00180 IN IDataObject *pDataObject) 00181 { 00182 FORMATETC *Current, *Last; 00183 HRESULT hr; 00184 00185 /* NOTE: we could use IDataObject::EnumFormatEtc(), 00186 but this appears to be a lot easier! */ 00187 Last = This->Formats + This->FormatsCount; 00188 for (Current = This->Formats; 00189 Current != Last; 00190 Current++) 00191 { 00192 hr = IDataObject_QueryGetData(pDataObject, 00193 Current); 00194 if (SUCCEEDED(hr)) 00195 return Current; 00196 } 00197 00198 return NULL; 00199 } 00200 00201 static HRESULT STDMETHODCALLTYPE 00202 IDropTargetImpl_DragEnter(IN OUT IDropTarget *iface, 00203 IN IDataObject *pDataObject, 00204 IN DWORD grfKeyState, 00205 IN POINTL pt, 00206 IN OUT DWORD *pdwEffect) 00207 { 00208 IDropTargetImpl *This = impl_from_IDropTarget(iface); 00209 const FORMATETC *Format; 00210 HRESULT hr; 00211 00212 if (pDataObject == NULL) 00213 return E_INVALIDARG; 00214 00215 This->CanDrop = FALSE; 00216 00217 hr = IDropTargetHelper_DragEnter(This->DropTargetHelper, 00218 This->hwndTarget, 00219 pDataObject, 00220 (POINT *)&pt, 00221 *pdwEffect); 00222 00223 if (SUCCEEDED(hr)) 00224 { 00225 Format = IDropTargetImpl_FindSupportedFormat(This, 00226 pDataObject); 00227 if (Format != NULL) 00228 { 00229 /* We found a format that we support! */ 00230 if (This->Callbacks.OnDragEnter != NULL) 00231 { 00232 hr = This->Callbacks.OnDragEnter(iface, 00233 This->Context, 00234 Format, 00235 grfKeyState, 00236 pt, 00237 pdwEffect); 00238 if (SUCCEEDED(hr)) 00239 { 00240 if (hr == S_OK) 00241 This->CanDrop = TRUE; 00242 else 00243 { 00244 /* Special return value by the callback routine, 00245 doesn't want to allow dragging */ 00246 *pdwEffect = DROPEFFECT_NONE; 00247 } 00248 00249 hr = S_OK; 00250 } 00251 else 00252 { 00253 *pdwEffect = DROPEFFECT_NONE; 00254 hr = S_OK; 00255 } 00256 } 00257 else 00258 *pdwEffect = DROPEFFECT_NONE; 00259 } 00260 else 00261 *pdwEffect = DROPEFFECT_NONE; 00262 } 00263 00264 return hr; 00265 } 00266 00267 static HRESULT STDMETHODCALLTYPE 00268 IDropTargetImpl_DragOver(IN OUT IDropTarget *iface, 00269 IN DWORD grfKeyState, 00270 IN POINTL pt, 00271 IN OUT DWORD *pdwEffect) 00272 { 00273 IDropTargetImpl *This = impl_from_IDropTarget(iface); 00274 HRESULT hr; 00275 00276 hr = IDropTargetHelper_DragOver(This->DropTargetHelper, 00277 (POINT *)&pt, 00278 *pdwEffect); 00279 00280 if (SUCCEEDED(hr)) 00281 { 00282 if (This->CanDrop) 00283 { 00284 if (This->Callbacks.OnDragOver != NULL) 00285 { 00286 hr = This->Callbacks.OnDragOver(iface, 00287 This->Context, 00288 grfKeyState, 00289 pt, 00290 pdwEffect); 00291 if (SUCCEEDED(hr)) 00292 { 00293 if (hr != S_OK) 00294 { 00295 /* Special return value by the callback routine, 00296 doesn't want to allow dropping here */ 00297 *pdwEffect = DROPEFFECT_NONE; 00298 } 00299 00300 hr = S_OK; 00301 } 00302 else 00303 { 00304 *pdwEffect = DROPEFFECT_NONE; 00305 hr = S_OK; 00306 } 00307 } 00308 else 00309 *pdwEffect = DROPEFFECT_NONE; 00310 } 00311 else 00312 *pdwEffect = DROPEFFECT_NONE; 00313 } 00314 00315 return hr; 00316 } 00317 00318 static HRESULT STDMETHODCALLTYPE 00319 IDropTargetImpl_DragLeave(IN OUT IDropTarget *iface) 00320 { 00321 IDropTargetImpl *This = impl_from_IDropTarget(iface); 00322 HRESULT hr; 00323 00324 hr = IDropTargetHelper_DragLeave(This->DropTargetHelper); 00325 if (SUCCEEDED(hr)) 00326 { 00327 if (This->Callbacks.OnDragLeave != NULL) 00328 { 00329 hr = This->Callbacks.OnDragLeave(iface, 00330 This->Context); 00331 } 00332 } 00333 00334 return hr; 00335 } 00336 00337 static HRESULT STDMETHODCALLTYPE 00338 IDropTargetImpl_Drop(IN OUT IDropTarget *iface, 00339 IN IDataObject *pDataObject, 00340 IN DWORD grfKeyState, 00341 IN POINTL pt, 00342 IN OUT DWORD *pdwEffect) 00343 { 00344 IDropTargetImpl *This = impl_from_IDropTarget(iface); 00345 const FORMATETC *Format; 00346 HRESULT hr; 00347 00348 if (pDataObject == NULL) 00349 return E_INVALIDARG; 00350 00351 hr = IDropTargetHelper_Drop(This->DropTargetHelper, 00352 pDataObject, 00353 (POINT *)&pt, 00354 *pdwEffect); 00355 00356 if (SUCCEEDED(hr) && This->CanDrop) 00357 { 00358 Format = IDropTargetImpl_FindSupportedFormat(This, 00359 pDataObject); 00360 if (Format != NULL) 00361 { 00362 /* We found a format that we support! */ 00363 if (This->Callbacks.OnDrop != NULL) 00364 { 00365 hr = This->Callbacks.OnDrop(iface, 00366 This->Context, 00367 Format, 00368 grfKeyState, 00369 pt, 00370 pdwEffect); 00371 if (SUCCEEDED(hr)) 00372 { 00373 if (hr == S_OK) 00374 This->CanDrop = TRUE; 00375 else 00376 { 00377 /* Special return value by the callback routine, 00378 doesn't want to allow dragging */ 00379 *pdwEffect = DROPEFFECT_NONE; 00380 } 00381 00382 hr = S_OK; 00383 } 00384 else 00385 { 00386 *pdwEffect = DROPEFFECT_NONE; 00387 hr = S_OK; 00388 } 00389 } 00390 else 00391 *pdwEffect = DROPEFFECT_NONE; 00392 } 00393 else 00394 *pdwEffect = DROPEFFECT_NONE; 00395 } 00396 00397 return hr; 00398 } 00399 00400 static const IDropTargetVtbl IDropTargetImpl_Vtbl = 00401 { 00402 /* IUnknown */ 00403 IDropTargetImpl_QueryInterface, 00404 IDropTargetImpl_AddRef, 00405 IDropTargetImpl_Release, 00406 /* IDropTarget */ 00407 IDropTargetImpl_DragEnter, 00408 IDropTargetImpl_DragOver, 00409 IDropTargetImpl_DragLeave, 00410 IDropTargetImpl_Drop 00411 }; Generated on Fri May 25 2012 04:16:35 for ReactOS by
1.7.6.1
|