ReactOS  0.4.14-dev-77-gd9e7c48
dragdropimpl.cpp
Go to the documentation of this file.
1 #include <precomp.h>
2 
3 /**************************************************************************
4  THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
5  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
6  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
7  PARTICULAR PURPOSE.
8  Author: Leon Finker 11/2000
9  Modifications: replaced ATL by STL, Martin Fuchs 7/2003
10 **************************************************************************/
11 
12 // dragdropimp.cpp: implementation of the IDataObjectImpl class.
14 
15 //#include <shlobj.h>
16 //#include <assert.h>
17 
18 //#include "dragdropimpl.h"
19 
21 // IDataObjectImpl Class
23 
26  m_pDropSource(pDropSource),
27  m_cRefCount(0)
28 {
29 }
30 
32 {
33  for(StorageArray::iterator it=_storage.begin(); it!=_storage.end(); ++it)
34  ReleaseStgMedium(it->_medium);
35 }
36 
38  /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
39  /* [out] */ STGMEDIUM __RPC_FAR *pmedium)
40 {
41  if (pformatetcIn == NULL || pmedium == NULL)
42  return E_INVALIDARG;
43 
44  pmedium->hGlobal = NULL;
45 
46  for(StorageArray::iterator it=_storage.begin(); it!=_storage.end(); ++it)
47  {
48  if (pformatetcIn->tymed & it->_format->tymed &&
49  pformatetcIn->dwAspect == it->_format->dwAspect &&
50  pformatetcIn->cfFormat == it->_format->cfFormat)
51  {
52  CopyMedium(pmedium, it->_medium, it->_format);
53  return S_OK;
54  }
55  }
56 
57  return DV_E_FORMATETC;
58 }
59 
61  /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
62  /* [out][in] */ STGMEDIUM __RPC_FAR *pmedium)
63 {
64  return E_NOTIMPL;
65 }
66 
68  /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc)
69 {
70  if (pformatetc == NULL)
71  return E_INVALIDARG;
72 
73  //support others if needed DVASPECT_THUMBNAIL //DVASPECT_ICON //DVASPECT_DOCPRINT
74  if (!(DVASPECT_CONTENT & pformatetc->dwAspect))
75  return (DV_E_DVASPECT);
76 
78 
79  for(StorageArray::iterator it=_storage.begin(); it!=_storage.end(); ++it)
80  {
81  if (pformatetc->tymed & it->_format->tymed)
82  {
83  if (pformatetc->cfFormat == it->_format->cfFormat)
84  return S_OK;
85  else
87  }
88  else
89  hr = DV_E_TYMED;
90  }
91 
92  return hr;
93 }
94 
96  /* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn,
97  /* [out] */ FORMATETC __RPC_FAR *pformatetcOut)
98 {
99  if (pformatetcOut == NULL)
100  return E_INVALIDARG;
101 
102  return DATA_S_SAMEFORMATETC;
103 }
104 
106  /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
107  /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
108  /* [in] */ BOOL fRelease)
109 {
110  if (pformatetc == NULL || pmedium == NULL)
111  return E_INVALIDARG;
112 
113  assert(pformatetc->tymed == pmedium->tymed);
114  FORMATETC* fetc=new FORMATETC;
115  STGMEDIUM* pStgMed = new STGMEDIUM;
116 
117  if (fetc == NULL || pStgMed == NULL)
118  return E_OUTOFMEMORY;
119 
120  ZeroMemory(fetc, sizeof(FORMATETC));
121  ZeroMemory(pStgMed, sizeof(STGMEDIUM));
122 
123  *fetc = *pformatetc;
124 
125  if (fRelease)
126  *pStgMed = *pmedium;
127  else
128  CopyMedium(pStgMed, pmedium, pformatetc);
129 
130  DataStorage storage;
131 
132  storage._format = fetc;
133  storage._medium = pStgMed;
134 
135  _storage.push_back(storage);
136 
137  return S_OK;
138 }
139 
140 void IDataObjectImpl::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc)
141 {
142  switch(pMedSrc->tymed)
143  {
144  case TYMED_HGLOBAL:
145  pMedDest->hGlobal = (HGLOBAL)OleDuplicateData(pMedSrc->hGlobal, pFmtSrc->cfFormat, 0);
146  break;
147  case TYMED_GDI:
148  pMedDest->hBitmap = (HBITMAP)OleDuplicateData(pMedSrc->hBitmap, pFmtSrc->cfFormat, 0);
149  break;
150  case TYMED_MFPICT:
151  pMedDest->hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(pMedSrc->hMetaFilePict, pFmtSrc->cfFormat, 0);
152  break;
153  case TYMED_ENHMF:
154  pMedDest->hEnhMetaFile = (HENHMETAFILE)OleDuplicateData(pMedSrc->hEnhMetaFile, pFmtSrc->cfFormat, 0);
155  break;
156  case TYMED_FILE:
157  pMedDest->lpszFileName = (LPOLESTR)OleDuplicateData(pMedSrc->lpszFileName, pFmtSrc->cfFormat, 0);
158  break;
159  case TYMED_ISTREAM:
160  pMedDest->pstm = pMedSrc->pstm;
161  pMedSrc->pstm->AddRef();
162  break;
163  case TYMED_ISTORAGE:
164  pMedDest->pstg = pMedSrc->pstg;
165  pMedSrc->pstg->AddRef();
166  break;
167  case TYMED_NULL:
168  default:
169  break;
170  }
171  pMedDest->tymed = pMedSrc->tymed;
172  pMedDest->pUnkForRelease = pMedSrc->pUnkForRelease;
173 }
174 
176  /* [in] */ DWORD dwDirection,
177  /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc)
178 {
179  if (ppenumFormatEtc == NULL)
180  return E_POINTER;
181 
182  *ppenumFormatEtc=NULL;
183  switch (dwDirection)
184  {
185  case DATADIR_GET:
186  *ppenumFormatEtc = new EnumFormatEtcImpl(_storage);
187 
188  if (!*ppenumFormatEtc)
189  return E_OUTOFMEMORY;
190 
191  (*ppenumFormatEtc)->AddRef();
192  break;
193 
194  case DATADIR_SET:
195  default:
196  return E_NOTIMPL;
197  break;
198  }
199 
200  return S_OK;
201 }
202 
204  /* [in] */ FORMATETC __RPC_FAR *pformatetc,
205  /* [in] */ DWORD advf,
206  /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
207  /* [out] */ DWORD __RPC_FAR *pdwConnection)
208 {
210 }
211 
213  /* [in] */ DWORD dwConnection)
214 {
215  return E_NOTIMPL;
216 }
217 
219  /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise)
220 {
222 }
223 
225 // IDropSourceImpl Class
227 
229  /* [in] */ BOOL fEscapePressed,
230  /* [in] */ DWORD grfKeyState)
231 {
232  if (fEscapePressed)
233  return DRAGDROP_S_CANCEL;
234  if (!(grfKeyState & (MK_LBUTTON|MK_RBUTTON)))
235  {
236  m_bDropped = true;
237  return DRAGDROP_S_DROP;
238  }
239 
240  return S_OK;
241 
242 }
243 
245  /* [in] */ DWORD dwEffect)
246 {
248 }
249 
251 // EnumFormatEtcImpl Class
253 
256  m_cRefCount(0),
257  m_iCur(0)
258 {
259  for(FormatArray::const_iterator it=ArrFE.begin(); it!=ArrFE.end(); ++it)
260  m_pFmtEtc.push_back(*it);
261 }
262 
265  m_cRefCount(0),
266  m_iCur(0)
267 {
268  for(StorageArray::const_iterator it=ArrFE.begin(); it!=ArrFE.end(); ++it)
269  m_pFmtEtc.push_back(*it->_format);
270 }
271 
273 {
274  if (pceltFetched != NULL)
275  *pceltFetched=0;
276 
277  ULONG cReturn = celt;
278 
279  if (celt <= 0 || lpFormatEtc == NULL || m_iCur >= m_pFmtEtc.size())
280  return S_FALSE;
281 
282  if (pceltFetched == NULL && celt != 1) // pceltFetched can be NULL only for 1 item request
283  return S_FALSE;
284 
285  while (m_iCur < m_pFmtEtc.size() && cReturn > 0)
286  {
287  *lpFormatEtc++ = m_pFmtEtc[m_iCur++];
288  --cReturn;
289  }
290  if (pceltFetched != NULL)
291  *pceltFetched = celt - cReturn;
292 
293  return (cReturn == 0) ? S_OK : S_FALSE;
294 }
295 
297 {
298  if ((m_iCur + int(celt)) >= m_pFmtEtc.size())
299  return S_FALSE;
300 
301  m_iCur += celt;
302  return S_OK;
303 }
304 
306 {
307  m_iCur = 0;
308  return S_OK;
309 }
310 
312 {
313  if (ppCloneEnumFormatEtc == NULL)
314  return E_POINTER;
315 
317 
318  if (!newEnum)
319  return E_OUTOFMEMORY;
320 
321  newEnum->AddRef();
322  newEnum->m_iCur = m_iCur;
323  *ppCloneEnumFormatEtc = newEnum;
324 
325  return S_OK;
326 }
327 
329 // IDropTargetImpl Class
332  : m_cRefCount(0),
333  m_bAllowDrop(false),
334  m_pDropTargetHelper(NULL),
335  m_pSupportedFrmt(NULL),
336  m_hTargetWnd(hTargetWnd)
337 {
339 
340  if (FAILED(CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER,
341  IID_IDropTargetHelper,(LPVOID*)&m_pDropTargetHelper)))
343 }
344 
346 {
347  if (m_pDropTargetHelper != NULL)
348  {
351  }
352 }
353 
355  /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
356 {
357  *ppvObject = NULL;
358  if (IID_IUnknown==riid || IID_IDropTarget==riid)
359  *ppvObject=this;
360 
361  if (*ppvObject != NULL)
362  {
363  ((LPUNKNOWN)*ppvObject)->AddRef();
364  return S_OK;
365  }
366 
367  return E_NOINTERFACE;
368 }
369 
371 {
372  long nTemp = --m_cRefCount;
373 
374  assert(nTemp >= 0);
375 
376  if (nTemp == 0)
377  delete this;
378 
379  return nTemp;
380 }
381 
382 bool IDropTargetImpl::QueryDrop(DWORD grfKeyState, LPDWORD pdwEffect)
383 {
384  DWORD dwOKEffects = *pdwEffect;
385 
386  if (!m_bAllowDrop)
387  {
388  *pdwEffect = DROPEFFECT_NONE;
389  return false;
390  }
391 
392  //CTRL+SHIFT -- DROPEFFECT_LINK
393  //CTRL -- DROPEFFECT_COPY
394  //SHIFT -- DROPEFFECT_MOVE
395  //no modifier -- DROPEFFECT_MOVE or whatever is allowed by src
396  *pdwEffect = (grfKeyState & MK_CONTROL) ?
397  ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY ):
398  ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_MOVE : DROPEFFECT_NONE );
399  if (*pdwEffect == 0)
400  {
401  // No modifier keys used by user while dragging.
402  if (DROPEFFECT_COPY & dwOKEffects)
403  *pdwEffect = DROPEFFECT_COPY;
404  else if (DROPEFFECT_MOVE & dwOKEffects)
405  *pdwEffect = DROPEFFECT_MOVE;
406  else if (DROPEFFECT_LINK & dwOKEffects)
407  *pdwEffect = DROPEFFECT_LINK;
408  else
409  {
410  *pdwEffect = DROPEFFECT_NONE;
411  }
412  }
413  else
414  {
415  // Check if the drag source application allows the drop effect desired by user.
416  // The drag source specifies this in DoDragDrop
417  if (!(*pdwEffect & dwOKEffects))
418  *pdwEffect = DROPEFFECT_NONE;
419  }
420 
421  return (DROPEFFECT_NONE == *pdwEffect)?false:true;
422 }
423 
425  /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
426  /* [in] */ DWORD grfKeyState,
427  /* [in] */ POINTL pt,
428  /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
429 {
430  if (pDataObj == NULL)
431  return E_INVALIDARG;
432 
434  m_pDropTargetHelper->DragEnter(m_hTargetWnd, pDataObj, (LPPOINT)&pt, *pdwEffect);
435 
436  //IEnumFORMATETC* pEnum;
437  //pDataObj->EnumFormatEtc(DATADIR_GET,&pEnum);
438  //FORMATETC ftm;
439  //for()
440  //pEnum->Next(1,&ftm,0);
441  //pEnum->Release();
443 
444  for(FormatArray::iterator it=m_formatetc.begin(); it!=m_formatetc.end(); ++it)
445  {
446  m_bAllowDrop = (pDataObj->QueryGetData(&*it) == S_OK)? true: false;
447 
448  if (m_bAllowDrop)
449  {
450  m_pSupportedFrmt = &*it;
451  break;
452  }
453  }
454 
455  QueryDrop(grfKeyState, pdwEffect);
456 
457  return S_OK;
458 }
459 
461  /* [in] */ DWORD grfKeyState,
462  /* [in] */ POINTL pt,
463  /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
464 {
466  m_pDropTargetHelper->DragOver((LPPOINT)&pt, *pdwEffect);
467 
468  QueryDrop(grfKeyState, pdwEffect);
469 
470  return S_OK;
471 }
472 
474 {
477 
478  m_bAllowDrop = false;
480 
481  return S_OK;
482 }
483 
485  /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
486  /* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt,
487  /* [out][in] */ DWORD __RPC_FAR *pdwEffect)
488 {
489  if (pDataObj == NULL)
490  return E_INVALIDARG;
491 
493  m_pDropTargetHelper->Drop(pDataObj, (LPPOINT)&pt, *pdwEffect);
494 
495  if (QueryDrop(grfKeyState, pdwEffect))
496  {
498  {
499  STGMEDIUM medium;
500 
501  if (pDataObj->GetData(m_pSupportedFrmt, &medium) == S_OK)
502  {
503  if (OnDrop(m_pSupportedFrmt, medium, pdwEffect)) //does derive class wants us to free medium?
504  ReleaseStgMedium(&medium);
505  }
506  }
507  }
508 
509  m_bAllowDrop = false;
510  *pdwEffect = DROPEFFECT_NONE;
512 
513  return S_OK;
514 }
HANDLE HGLOBAL
Definition: windef.h:243
structure containing information for one format of EnumFormatEtcImpl
Definition: dragdropimpl.h:18
implementation of IDropSource interface
Definition: dragdropimpl.h:50
virtual HRESULT STDMETHODCALLTYPE Next(ULONG, LPFORMATETC, ULONG *)
#define REFIID
Definition: guiddef.h:118
EnumFormatEtcImpl(const FormatArray &ArrFE)
#define E_NOINTERFACE
Definition: winerror.h:2364
#define MK_SHIFT
Definition: winuser.h:2344
HRESULT hr
Definition: shlfolder.c:183
iterator end()
Definition: _vector.h:184
#define DATA_S_SAMEFORMATETC
Definition: winerror.h:2674
#define MK_LBUTTON
Definition: winuser.h:2342
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2036
FORMATETC * _format
Definition: dragdropimpl.h:19
#define pt(x, y)
Definition: drawing.c:79
HRESULT Drop([in] IDataObject *pDataObject, [in] POINT *ppt, [in] DWORD dwEffect)
REFIID riid
Definition: precomp.h:44
IUnknown * LPUNKNOWN
Definition: unknwn.idl:40
FORMATETC * m_pSupportedFrmt
Definition: dragdropimpl.h:175
bool QueryDrop(DWORD grfKeyState, LPDWORD pdwEffect)
FormatArray m_formatetc
Definition: dragdropimpl.h:174
virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
#define assert(x)
Definition: debug.h:53
#define ZeroMemory
Definition: winbase.h:1635
const GUID IID_IDataObject
#define DV_E_CLIPFORMAT
Definition: winerror.h:2639
implementation of IEnumFORMATETC interface
Definition: dragdropimpl.h:27
HANDLE WINAPI OleDuplicateData(HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags)
Definition: ole2impl.c:425
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
static LPOLESTR
Definition: stg_prop.c:27
HRESULT DragOver([in] POINT *ppt, [in] DWORD dwEffect)
#define DRAGDROP_S_CANCEL
Definition: winerror.h:2647
const DWORD DROPEFFECT_COPY
Definition: oleidl.idl:930
virtual HRESULT STDMETHODCALLTYPE Reset(void)
const DWORD DROPEFFECT_NONE
Definition: oleidl.idl:929
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
virtual HRESULT STDMETHODCALLTYPE QueryGetData(FORMATETC __RPC_FAR *pformatetc)
unsigned int BOOL
Definition: ntddk_ex.h:94
FormatArray m_pFmtEtc
Definition: dragdropimpl.h:34
#define STDMETHODIMP
Definition: basetyps.h:43
ULONG Release()
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
STGMEDIUM * _medium
Definition: dragdropimpl.h:20
virtual HRESULT STDMETHODCALLTYPE DUnadvise(DWORD dwConnection)
#define __RPC_FAR
Definition: rpc.h:56
value_type * iterator
Definition: _vector.h:124
#define MK_RBUTTON
Definition: winuser.h:2343
virtual HRESULT STDMETHODCALLTYPE DAdvise(FORMATETC __RPC_FAR *pformatetc, DWORD advf, IAdviseSink __RPC_FAR *pAdvSink, DWORD __RPC_FAR *pdwConnection)
virtual HRESULT STDMETHODCALLTYPE EnumDAdvise(IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise)
virtual ~IDataObjectImpl()
#define DV_E_FORMATETC
Definition: winerror.h:2633
HRESULT DragLeave()
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
void push_back(const _Tp &__x=_STLP_DEFAULT_CONSTRUCTED(_Tp))
Definition: _vector.h:376
virtual ~IDropTargetImpl()
const DWORD DROPEFFECT_LINK
Definition: oleidl.idl:932
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
virtual HRESULT STDMETHODCALLTYPE DragLeave()
unsigned long DWORD
Definition: ntddk_ex.h:95
#define DRAGDROP_S_USEDEFAULTCURSORS
Definition: winerror.h:2648
const GUID IID_IEnumFORMATETC
StorageArray _storage
Definition: dragdropimpl.h:88
ULONG AddRef()
#define DV_E_TYMED
Definition: winerror.h:2638
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumFORMATETC **)
virtual HRESULT STDMETHODCALLTYPE EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc)
void CopyMedium(STGMEDIUM *pMedDest, STGMEDIUM *pMedSrc, FORMATETC *pFmtSrc)
iterator begin()
Definition: _vector.h:182
virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)
#define DV_E_DVASPECT
Definition: winerror.h:2640
#define false
Definition: stdbool.h:38
REFIID LPVOID * ppvObject
Definition: precomp.h:44
virtual ULONG STDMETHODCALLTYPE Release()
virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3234
#define OLE_E_ADVISENOTSUPPORTED
Definition: winerror.h:2617
IDropTargetImpl(HWND m_hTargetWnd)
const value_type * const_iterator
Definition: _vector.h:125
#define S_OK
Definition: intsafe.h:59
HRESULT DragEnter([in] HWND hwndTarget, [in] IDataObject *pDataObject, [in] POINT *ppt, [in] DWORD dwEffect)
virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect)
const DWORD DROPEFFECT_MOVE
Definition: oleidl.idl:931
#define DRAGDROP_S_DROP
Definition: winerror.h:2646
#define E_NOTIMPL
Definition: ddrawi.h:99
virtual HRESULT STDMETHODCALLTYPE GetDataHere(FORMATETC __RPC_FAR *pformatetc, STGMEDIUM __RPC_FAR *pmedium)
virtual HRESULT STDMETHODCALLTYPE SetData(FORMATETC __RPC_FAR *pformatetc, STGMEDIUM __RPC_FAR *pmedium, BOOL fRelease)
#define MK_CONTROL
Definition: winuser.h:2345
IDropTargetHelper * m_pDropTargetHelper
Definition: dragdropimpl.h:172
uint32_t * LPDWORD
Definition: typedefs.h:57
size_type size() const
Definition: _vector.h:192
unsigned int ULONG
Definition: retypes.h:1
virtual HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(FORMATETC __RPC_FAR *pformatectIn, FORMATETC __RPC_FAR *pformatetcOut)
virtual HRESULT STDMETHODCALLTYPE GetData(FORMATETC __RPC_FAR *pformatetcIn, STGMEDIUM __RPC_FAR *pmedium)
static HBITMAP
Definition: button.c:44
#define E_POINTER
Definition: winerror.h:2365
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG)
nsrefcnt AddRef()
virtual bool OnDrop(FORMATETC *pFmtEtc, STGMEDIUM &medium, DWORD *pdwEffect)=0
virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)
IDataObjectImpl(IDropSourceImpl *pDropSource)