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
8 Author: Leon Finker 11/2000
9 Modifications: replaced ATL by STL, Martin Fuchs 7/2003
10 **************************************************************************/
12 // dragdropimp.cpp: implementation of the IDataObjectImpl class.
13 //////////////////////////////////////////////////////////////////////
18 //#include "dragdropimpl.h"
20 //////////////////////////////////////////////////////////////////////
21 // IDataObjectImpl Class
22 //////////////////////////////////////////////////////////////////////
24 IDataObjectImpl::IDataObjectImpl(IDropSourceImpl
* pDropSource
)
25 : super(IID_IDataObject
),
26 m_pDropSource(pDropSource
),
31 IDataObjectImpl::~IDataObjectImpl()
33 for(StorageArray::iterator it
=_storage
.begin(); it
!=_storage
.end(); ++it
)
34 ReleaseStgMedium(it
->_medium
);
37 STDMETHODIMP
IDataObjectImpl::GetData(
38 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatetcIn
,
39 /* [out] */ STGMEDIUM __RPC_FAR
*pmedium
)
41 if (pformatetcIn
== NULL
|| pmedium
== NULL
)
44 pmedium
->hGlobal
= NULL
;
46 for(StorageArray::iterator it
=_storage
.begin(); it
!=_storage
.end(); ++it
)
48 if (pformatetcIn
->tymed
& it
->_format
->tymed
&&
49 pformatetcIn
->dwAspect
== it
->_format
->dwAspect
&&
50 pformatetcIn
->cfFormat
== it
->_format
->cfFormat
)
52 CopyMedium(pmedium
, it
->_medium
, it
->_format
);
57 return DV_E_FORMATETC
;
60 STDMETHODIMP
IDataObjectImpl::GetDataHere(
61 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatetc
,
62 /* [out][in] */ STGMEDIUM __RPC_FAR
*pmedium
)
67 STDMETHODIMP
IDataObjectImpl::QueryGetData(
68 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatetc
)
70 if (pformatetc
== NULL
)
73 //support others if needed DVASPECT_THUMBNAIL //DVASPECT_ICON //DVASPECT_DOCPRINT
74 if (!(DVASPECT_CONTENT
& pformatetc
->dwAspect
))
75 return (DV_E_DVASPECT
);
77 HRESULT hr
= DV_E_TYMED
;
79 for(StorageArray::iterator it
=_storage
.begin(); it
!=_storage
.end(); ++it
)
81 if (pformatetc
->tymed
& it
->_format
->tymed
)
83 if (pformatetc
->cfFormat
== it
->_format
->cfFormat
)
95 STDMETHODIMP
IDataObjectImpl::GetCanonicalFormatEtc(
96 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatectIn
,
97 /* [out] */ FORMATETC __RPC_FAR
*pformatetcOut
)
99 if (pformatetcOut
== NULL
)
102 return DATA_S_SAMEFORMATETC
;
105 STDMETHODIMP
IDataObjectImpl::SetData(
106 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatetc
,
107 /* [unique][in] */ STGMEDIUM __RPC_FAR
*pmedium
,
108 /* [in] */ BOOL fRelease
)
110 if (pformatetc
== NULL
|| pmedium
== NULL
)
113 assert(pformatetc
->tymed
== pmedium
->tymed
);
114 FORMATETC
* fetc
=new FORMATETC
;
115 STGMEDIUM
* pStgMed
= new STGMEDIUM
;
117 if (fetc
== NULL
|| pStgMed
== NULL
)
118 return E_OUTOFMEMORY
;
120 ZeroMemory(fetc
, sizeof(FORMATETC
));
121 ZeroMemory(pStgMed
, sizeof(STGMEDIUM
));
128 CopyMedium(pStgMed
, pmedium
, pformatetc
);
132 storage
._format
= fetc
;
133 storage
._medium
= pStgMed
;
135 _storage
.push_back(storage
);
140 void IDataObjectImpl::CopyMedium(STGMEDIUM
* pMedDest
, STGMEDIUM
* pMedSrc
, FORMATETC
* pFmtSrc
)
142 switch(pMedSrc
->tymed
)
145 pMedDest
->hGlobal
= (HGLOBAL
)OleDuplicateData(pMedSrc
->hGlobal
, pFmtSrc
->cfFormat
, 0);
148 pMedDest
->hBitmap
= (HBITMAP
)OleDuplicateData(pMedSrc
->hBitmap
, pFmtSrc
->cfFormat
, 0);
151 pMedDest
->hMetaFilePict
= (HMETAFILEPICT
)OleDuplicateData(pMedSrc
->hMetaFilePict
, pFmtSrc
->cfFormat
, 0);
154 pMedDest
->hEnhMetaFile
= (HENHMETAFILE
)OleDuplicateData(pMedSrc
->hEnhMetaFile
, pFmtSrc
->cfFormat
, 0);
157 pMedDest
->lpszFileName
= (LPOLESTR
)OleDuplicateData(pMedSrc
->lpszFileName
, pFmtSrc
->cfFormat
, 0);
160 pMedDest
->pstm
= pMedSrc
->pstm
;
161 pMedSrc
->pstm
->AddRef();
164 pMedDest
->pstg
= pMedSrc
->pstg
;
165 pMedSrc
->pstg
->AddRef();
171 pMedDest
->tymed
= pMedSrc
->tymed
;
172 pMedDest
->pUnkForRelease
= pMedSrc
->pUnkForRelease
;
175 STDMETHODIMP
IDataObjectImpl::EnumFormatEtc(
176 /* [in] */ DWORD dwDirection
,
177 /* [out] */ IEnumFORMATETC __RPC_FAR
*__RPC_FAR
*ppenumFormatEtc
)
179 if (ppenumFormatEtc
== NULL
)
182 *ppenumFormatEtc
=NULL
;
186 *ppenumFormatEtc
= new EnumFormatEtcImpl(_storage
);
188 if (!*ppenumFormatEtc
)
189 return E_OUTOFMEMORY
;
191 (*ppenumFormatEtc
)->AddRef();
203 STDMETHODIMP
IDataObjectImpl::DAdvise(
204 /* [in] */ FORMATETC __RPC_FAR
*pformatetc
,
205 /* [in] */ DWORD advf
,
206 /* [unique][in] */ IAdviseSink __RPC_FAR
*pAdvSink
,
207 /* [out] */ DWORD __RPC_FAR
*pdwConnection
)
209 return OLE_E_ADVISENOTSUPPORTED
;
212 STDMETHODIMP
IDataObjectImpl::DUnadvise(
213 /* [in] */ DWORD dwConnection
)
218 HRESULT STDMETHODCALLTYPE
IDataObjectImpl::EnumDAdvise(
219 /* [out] */ IEnumSTATDATA __RPC_FAR
*__RPC_FAR
*ppenumAdvise
)
221 return OLE_E_ADVISENOTSUPPORTED
;
224 //////////////////////////////////////////////////////////////////////
225 // IDropSourceImpl Class
226 //////////////////////////////////////////////////////////////////////
228 STDMETHODIMP
IDropSourceImpl::QueryContinueDrag(
229 /* [in] */ BOOL fEscapePressed
,
230 /* [in] */ DWORD grfKeyState
)
233 return DRAGDROP_S_CANCEL
;
234 if (!(grfKeyState
& (MK_LBUTTON
|MK_RBUTTON
)))
237 return DRAGDROP_S_DROP
;
244 STDMETHODIMP
IDropSourceImpl::GiveFeedback(
245 /* [in] */ DWORD dwEffect
)
247 return DRAGDROP_S_USEDEFAULTCURSORS
;
250 //////////////////////////////////////////////////////////////////////
251 // EnumFormatEtcImpl Class
252 //////////////////////////////////////////////////////////////////////
254 EnumFormatEtcImpl::EnumFormatEtcImpl(const FormatArray
& ArrFE
)
255 : super(IID_IEnumFORMATETC
),
259 for(FormatArray::const_iterator it
=ArrFE
.begin(); it
!=ArrFE
.end(); ++it
)
260 m_pFmtEtc
.push_back(*it
);
263 EnumFormatEtcImpl::EnumFormatEtcImpl(const StorageArray
& ArrFE
)
264 : super(IID_IEnumFORMATETC
),
268 for(StorageArray::const_iterator it
=ArrFE
.begin(); it
!=ArrFE
.end(); ++it
)
269 m_pFmtEtc
.push_back(*it
->_format
);
272 STDMETHODIMP
EnumFormatEtcImpl::Next(ULONG celt
,LPFORMATETC lpFormatEtc
, ULONG
* pceltFetched
)
274 if (pceltFetched
!= NULL
)
277 ULONG cReturn
= celt
;
279 if (celt
<= 0 || lpFormatEtc
== NULL
|| m_iCur
>= m_pFmtEtc
.size())
282 if (pceltFetched
== NULL
&& celt
!= 1) // pceltFetched can be NULL only for 1 item request
285 while (m_iCur
< m_pFmtEtc
.size() && cReturn
> 0)
287 *lpFormatEtc
++ = m_pFmtEtc
[m_iCur
++];
290 if (pceltFetched
!= NULL
)
291 *pceltFetched
= celt
- cReturn
;
293 return (cReturn
== 0) ? S_OK
: S_FALSE
;
296 STDMETHODIMP
EnumFormatEtcImpl::Skip(ULONG celt
)
298 if ((m_iCur
+ int(celt
)) >= m_pFmtEtc
.size())
305 STDMETHODIMP
EnumFormatEtcImpl::Reset(void)
311 STDMETHODIMP
EnumFormatEtcImpl::Clone(IEnumFORMATETC
** ppCloneEnumFormatEtc
)
313 if (ppCloneEnumFormatEtc
== NULL
)
316 EnumFormatEtcImpl
* newEnum
= new EnumFormatEtcImpl(m_pFmtEtc
);
319 return E_OUTOFMEMORY
;
322 newEnum
->m_iCur
= m_iCur
;
323 *ppCloneEnumFormatEtc
= newEnum
;
328 //////////////////////////////////////////////////////////////////////
329 // IDropTargetImpl Class
330 //////////////////////////////////////////////////////////////////////
331 IDropTargetImpl::IDropTargetImpl(HWND hTargetWnd
)
334 m_pDropTargetHelper(NULL
),
335 m_pSupportedFrmt(NULL
),
336 m_hTargetWnd(hTargetWnd
)
338 assert(m_hTargetWnd
!= NULL
);
340 if (FAILED(CoCreateInstance(CLSID_DragDropHelper
, NULL
, CLSCTX_INPROC_SERVER
,
341 IID_IDropTargetHelper
,(LPVOID
*)&m_pDropTargetHelper
)))
342 m_pDropTargetHelper
= NULL
;
345 IDropTargetImpl::~IDropTargetImpl()
347 if (m_pDropTargetHelper
!= NULL
)
349 m_pDropTargetHelper
->Release();
350 m_pDropTargetHelper
= NULL
;
354 HRESULT STDMETHODCALLTYPE
IDropTargetImpl::QueryInterface( /* [in] */ REFIID riid
,
355 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
358 if (IID_IUnknown
==riid
|| IID_IDropTarget
==riid
)
361 if (*ppvObject
!= NULL
)
363 ((LPUNKNOWN
)*ppvObject
)->AddRef();
367 return E_NOINTERFACE
;
370 ULONG STDMETHODCALLTYPE
IDropTargetImpl::Release()
372 long nTemp
= --m_cRefCount
;
382 bool IDropTargetImpl::QueryDrop(DWORD grfKeyState
, LPDWORD pdwEffect
)
384 DWORD dwOKEffects
= *pdwEffect
;
388 *pdwEffect
= DROPEFFECT_NONE
;
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
);
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
;
410 *pdwEffect
= DROPEFFECT_NONE
;
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
;
421 return (DROPEFFECT_NONE
== *pdwEffect
)?false:true;
424 HRESULT STDMETHODCALLTYPE
IDropTargetImpl::DragEnter(
425 /* [unique][in] */ IDataObject __RPC_FAR
*pDataObj
,
426 /* [in] */ DWORD grfKeyState
,
427 /* [in] */ POINTL pt
,
428 /* [out][in] */ DWORD __RPC_FAR
*pdwEffect
)
430 if (pDataObj
== NULL
)
433 if (m_pDropTargetHelper
)
434 m_pDropTargetHelper
->DragEnter(m_hTargetWnd
, pDataObj
, (LPPOINT
)&pt
, *pdwEffect
);
436 //IEnumFORMATETC* pEnum;
437 //pDataObj->EnumFormatEtc(DATADIR_GET,&pEnum);
440 //pEnum->Next(1,&ftm,0);
442 m_pSupportedFrmt
= NULL
;
444 for(FormatArray::iterator it
=m_formatetc
.begin(); it
!=m_formatetc
.end(); ++it
)
446 m_bAllowDrop
= (pDataObj
->QueryGetData(&*it
) == S_OK
)? true: false;
450 m_pSupportedFrmt
= &*it
;
455 QueryDrop(grfKeyState
, pdwEffect
);
460 HRESULT STDMETHODCALLTYPE
IDropTargetImpl::DragOver(
461 /* [in] */ DWORD grfKeyState
,
462 /* [in] */ POINTL pt
,
463 /* [out][in] */ DWORD __RPC_FAR
*pdwEffect
)
465 if (m_pDropTargetHelper
)
466 m_pDropTargetHelper
->DragOver((LPPOINT
)&pt
, *pdwEffect
);
468 QueryDrop(grfKeyState
, pdwEffect
);
473 HRESULT STDMETHODCALLTYPE
IDropTargetImpl::DragLeave()
475 if (m_pDropTargetHelper
)
476 m_pDropTargetHelper
->DragLeave();
478 m_bAllowDrop
= false;
479 m_pSupportedFrmt
= NULL
;
484 HRESULT STDMETHODCALLTYPE
IDropTargetImpl::Drop(
485 /* [unique][in] */ IDataObject __RPC_FAR
*pDataObj
,
486 /* [in] */ DWORD grfKeyState
, /* [in] */ POINTL pt
,
487 /* [out][in] */ DWORD __RPC_FAR
*pdwEffect
)
489 if (pDataObj
== NULL
)
492 if (m_pDropTargetHelper
)
493 m_pDropTargetHelper
->Drop(pDataObj
, (LPPOINT
)&pt
, *pdwEffect
);
495 if (QueryDrop(grfKeyState
, pdwEffect
))
497 if (m_bAllowDrop
&& m_pSupportedFrmt
!= NULL
)
501 if (pDataObj
->GetData(m_pSupportedFrmt
, &medium
) == S_OK
)
503 if (OnDrop(m_pSupportedFrmt
, medium
, pdwEffect
)) //does derive class wants us to free medium?
504 ReleaseStgMedium(&medium
);
509 m_bAllowDrop
= false;
510 *pdwEffect
= DROPEFFECT_NONE
;
511 m_pSupportedFrmt
= NULL
;