1 /**************************************************************************
2 THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
3 ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
4 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
6 Author: Leon Finker 1/2001
7 **************************************************************************/
8 // IDataObjectImpl.cpp: implementation of the CIDataObjectImpl class.
9 //////////////////////////////////////////////////////////////////////
13 #include "DragDropImpl.h"
15 //////////////////////////////////////////////////////////////////////
17 //////////////////////////////////////////////////////////////////////
19 CIDataObject::CIDataObject(CIDropSource
* pDropSource
):
20 m_cRefCount(0), m_pDropSource(pDropSource
)
24 CIDataObject::~CIDataObject()
26 for(int i
= 0; i
< m_StgMedium
.GetSize(); ++i
)
28 ReleaseStgMedium(m_StgMedium
[i
]);
29 delete m_StgMedium
[i
];
31 for(int j
= 0; j
< m_ArrFormatEtc
.GetSize(); ++j
)
32 delete m_ArrFormatEtc
[j
];
35 STDMETHODIMP
CIDataObject::QueryInterface(/* [in] */ REFIID riid
,
36 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
39 if (IID_IUnknown
==riid
|| IID_IDataObject
==riid
)
41 /*if(riid == IID_IAsyncOperation)
42 *ppvObject=(IAsyncOperation*)this;*/
45 ((LPUNKNOWN
)*ppvObject
)->AddRef();
51 STDMETHODIMP_(ULONG
) CIDataObject::AddRef( void)
56 STDMETHODIMP_(ULONG
) CIDataObject::Release( void)
59 nTemp
= --m_cRefCount
;
65 STDMETHODIMP
CIDataObject::GetData(
66 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatetcIn
,
67 /* [out] */ STGMEDIUM __RPC_FAR
*pmedium
)
69 if(pformatetcIn
== NULL
|| pmedium
== NULL
)
71 pmedium
->hGlobal
= NULL
;
73 ATLASSERT(m_StgMedium
.GetSize() == m_ArrFormatEtc
.GetSize());
74 for(int i
=0; i
< m_ArrFormatEtc
.GetSize(); ++i
)
76 if(pformatetcIn
->tymed
& m_ArrFormatEtc
[i
]->tymed
&&
77 pformatetcIn
->dwAspect
== m_ArrFormatEtc
[i
]->dwAspect
&&
78 pformatetcIn
->cfFormat
== m_ArrFormatEtc
[i
]->cfFormat
)
80 CopyMedium(pmedium
, m_StgMedium
[i
], m_ArrFormatEtc
[i
]);
84 return DV_E_FORMATETC
;
87 STDMETHODIMP
CIDataObject::GetDataHere(
88 /* [unique][in] */ FORMATETC __RPC_FAR
* /*pformatetc*/,
89 /* [out][in] */ STGMEDIUM __RPC_FAR
* /*pmedium*/)
94 STDMETHODIMP
CIDataObject::QueryGetData(
95 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatetc
)
97 if(pformatetc
== NULL
)
100 //support others if needed DVASPECT_THUMBNAIL //DVASPECT_ICON //DVASPECT_DOCPRINT
101 if (!(DVASPECT_CONTENT
& pformatetc
->dwAspect
))
102 return (DV_E_DVASPECT
);
103 HRESULT hr
= DV_E_TYMED
;
104 for(int i
= 0; i
< m_ArrFormatEtc
.GetSize(); ++i
)
106 if(pformatetc
->tymed
& m_ArrFormatEtc
[i
]->tymed
)
108 if(pformatetc
->cfFormat
== m_ArrFormatEtc
[i
]->cfFormat
)
111 hr
= DV_E_CLIPFORMAT
;
119 STDMETHODIMP
CIDataObject::GetCanonicalFormatEtc(
120 /* [unique][in] */ FORMATETC __RPC_FAR
* /*pformatectIn*/,
121 /* [out] */ FORMATETC __RPC_FAR
*pformatetcOut
)
123 if (pformatetcOut
== NULL
)
125 return DATA_S_SAMEFORMATETC
;
128 STDMETHODIMP
CIDataObject::SetData(
129 /* [unique][in] */ FORMATETC __RPC_FAR
*pformatetc
,
130 /* [unique][in] */ STGMEDIUM __RPC_FAR
*pmedium
,
131 /* [in] */ BOOL fRelease
)
133 if(pformatetc
== NULL
|| pmedium
== NULL
)
136 ATLASSERT(pformatetc
->tymed
== pmedium
->tymed
);
137 FORMATETC
* fetc
=new FORMATETC
;
138 STGMEDIUM
* pStgMed
= new STGMEDIUM
;
140 if(fetc
== NULL
|| pStgMed
== NULL
)
141 return E_OUTOFMEMORY
;
143 SecureZeroMemory(fetc
,sizeof(FORMATETC
));
144 SecureZeroMemory(pStgMed
,sizeof(STGMEDIUM
));
147 m_ArrFormatEtc
.Add(fetc
);
153 CopyMedium(pStgMed
, pmedium
, pformatetc
);
155 m_StgMedium
.Add(pStgMed
);
159 void CIDataObject::CopyMedium(STGMEDIUM
* pMedDest
, STGMEDIUM
* pMedSrc
, FORMATETC
* pFmtSrc
)
161 switch(pMedSrc
->tymed
)
164 pMedDest
->hGlobal
= (HGLOBAL
)OleDuplicateData(pMedSrc
->hGlobal
,pFmtSrc
->cfFormat
, NULL
);
167 pMedDest
->hBitmap
= (HBITMAP
)OleDuplicateData(pMedSrc
->hBitmap
,pFmtSrc
->cfFormat
, NULL
);
170 pMedDest
->hMetaFilePict
= (HMETAFILEPICT
)OleDuplicateData(pMedSrc
->hMetaFilePict
,pFmtSrc
->cfFormat
, NULL
);
173 pMedDest
->hEnhMetaFile
= (HENHMETAFILE
)OleDuplicateData(pMedSrc
->hEnhMetaFile
,pFmtSrc
->cfFormat
, NULL
);
176 pMedSrc
->lpszFileName
= (LPOLESTR
)OleDuplicateData(pMedSrc
->lpszFileName
,pFmtSrc
->cfFormat
, NULL
);
179 pMedDest
->pstm
= pMedSrc
->pstm
;
180 pMedSrc
->pstm
->AddRef();
183 pMedDest
->pstg
= pMedSrc
->pstg
;
184 pMedSrc
->pstg
->AddRef();
190 pMedDest
->tymed
= pMedSrc
->tymed
;
191 pMedDest
->pUnkForRelease
= NULL
;
192 if(pMedSrc
->pUnkForRelease
!= NULL
)
194 pMedDest
->pUnkForRelease
= pMedSrc
->pUnkForRelease
;
195 pMedSrc
->pUnkForRelease
->AddRef();
198 STDMETHODIMP
CIDataObject::EnumFormatEtc(
199 /* [in] */ DWORD dwDirection
,
200 /* [out] */ IEnumFORMATETC __RPC_FAR
*__RPC_FAR
*ppenumFormatEtc
)
202 if(ppenumFormatEtc
== NULL
)
205 *ppenumFormatEtc
=NULL
;
209 *ppenumFormatEtc
= new CEnumFormatEtc(m_ArrFormatEtc
);
210 if(*ppenumFormatEtc
== NULL
)
211 return E_OUTOFMEMORY
;
212 (*ppenumFormatEtc
)->AddRef();
224 STDMETHODIMP
CIDataObject::DAdvise(
225 /* [in] */ FORMATETC __RPC_FAR
* /*pformatetc*/,
226 /* [in] */ DWORD
/*advf*/,
227 /* [unique][in] */ IAdviseSink __RPC_FAR
* /*pAdvSink*/,
228 /* [out] */ DWORD __RPC_FAR
* /*pdwConnection*/)
230 return OLE_E_ADVISENOTSUPPORTED
;
233 STDMETHODIMP
CIDataObject::DUnadvise(
234 /* [in] */ DWORD
/*dwConnection*/)
239 HRESULT STDMETHODCALLTYPE
CIDataObject::EnumDAdvise(
240 /* [out] */ IEnumSTATDATA __RPC_FAR
*__RPC_FAR
* /*ppenumAdvise*/)
242 return OLE_E_ADVISENOTSUPPORTED
;
245 //////////////////////////////////////////////////////////////////////
246 // CIDropSource Class
247 //////////////////////////////////////////////////////////////////////
249 STDMETHODIMP
CIDropSource::QueryInterface(/* [in] */ REFIID riid
,
250 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
253 if (IID_IUnknown
==riid
|| IID_IDropSource
==riid
)
256 if (*ppvObject
!= NULL
)
258 ((LPUNKNOWN
)*ppvObject
)->AddRef();
261 return E_NOINTERFACE
;
264 STDMETHODIMP_(ULONG
) CIDropSource::AddRef( void)
266 return ++m_cRefCount
;
269 STDMETHODIMP_(ULONG
) CIDropSource::Release( void)
272 nTemp
= --m_cRefCount
;
273 ATLASSERT(nTemp
>= 0);
279 STDMETHODIMP
CIDropSource::QueryContinueDrag(
280 /* [in] */ BOOL fEscapePressed
,
281 /* [in] */ DWORD grfKeyState
)
284 return DRAGDROP_S_CANCEL
;
285 if(!(grfKeyState
& (MK_LBUTTON
|MK_RBUTTON
)))
288 return DRAGDROP_S_DROP
;
295 STDMETHODIMP
CIDropSource::GiveFeedback(
296 /* [in] */ DWORD
/*dwEffect*/)
298 return DRAGDROP_S_USEDEFAULTCURSORS
;
301 //////////////////////////////////////////////////////////////////////
302 // CEnumFormatEtc Class
303 //////////////////////////////////////////////////////////////////////
305 CEnumFormatEtc::CEnumFormatEtc(const CSimpleArray
<FORMATETC
>& ArrFE
):
306 m_cRefCount(0),m_iCur(0)
308 ATLTRACE("CEnumFormatEtc::CEnumFormatEtc()\n");
309 for(int i
= 0; i
< ArrFE
.GetSize(); ++i
)
310 m_pFmtEtc
.Add(ArrFE
[i
]);
313 CEnumFormatEtc::CEnumFormatEtc(const CSimpleArray
<FORMATETC
*>& ArrFE
):
314 m_cRefCount(0),m_iCur(0)
316 for(int i
= 0; i
< ArrFE
.GetSize(); ++i
)
317 m_pFmtEtc
.Add(*ArrFE
[i
]);
320 STDMETHODIMP
CEnumFormatEtc::QueryInterface(REFIID refiid
, void FAR
* FAR
* ppv
)
323 if (IID_IUnknown
==refiid
|| IID_IEnumFORMATETC
==refiid
)
328 ((LPUNKNOWN
)*ppv
)->AddRef();
331 return E_NOINTERFACE
;
334 STDMETHODIMP_(ULONG
) CEnumFormatEtc::AddRef(void)
336 return ++m_cRefCount
;
339 STDMETHODIMP_(ULONG
) CEnumFormatEtc::Release(void)
341 long nTemp
= --m_cRefCount
;
342 ATLASSERT(nTemp
>= 0);
349 STDMETHODIMP
CEnumFormatEtc::Next( ULONG celt
,LPFORMATETC lpFormatEtc
, ULONG FAR
*pceltFetched
)
351 if(pceltFetched
!= NULL
)
354 ULONG cReturn
= celt
;
356 if(celt
<= 0 || lpFormatEtc
== NULL
|| m_iCur
>= m_pFmtEtc
.GetSize())
359 if(pceltFetched
== NULL
&& celt
!= 1) // pceltFetched can be NULL only for 1 item request
362 while (m_iCur
< m_pFmtEtc
.GetSize() && cReturn
> 0)
364 *lpFormatEtc
++ = m_pFmtEtc
[m_iCur
++];
367 if (pceltFetched
!= NULL
)
368 *pceltFetched
= celt
- cReturn
;
370 return (cReturn
== 0) ? S_OK
: S_FALSE
;
373 STDMETHODIMP
CEnumFormatEtc::Skip(ULONG celt
)
375 if((m_iCur
+ int(celt
)) >= m_pFmtEtc
.GetSize())
381 STDMETHODIMP
CEnumFormatEtc::Reset(void)
387 STDMETHODIMP
CEnumFormatEtc::Clone(IEnumFORMATETC FAR
* FAR
*ppCloneEnumFormatEtc
)
389 if(ppCloneEnumFormatEtc
== NULL
)
392 CEnumFormatEtc
*newEnum
= new CEnumFormatEtc(m_pFmtEtc
);
394 return E_OUTOFMEMORY
;
396 newEnum
->m_iCur
= m_iCur
;
397 *ppCloneEnumFormatEtc
= newEnum
;
401 //////////////////////////////////////////////////////////////////////
402 // CIDropTarget Class
403 //////////////////////////////////////////////////////////////////////
404 CIDropTarget::CIDropTarget(HWND hTargetWnd
):
405 m_hTargetWnd(hTargetWnd
),
406 m_cRefCount(0), m_bAllowDrop(false),
407 m_pDropTargetHelper(NULL
), m_pSupportedFrmt(NULL
)
409 if(FAILED(CoCreateInstance(CLSID_DragDropHelper
,NULL
,CLSCTX_INPROC_SERVER
,
410 IID_IDropTargetHelper
,(LPVOID
*)&m_pDropTargetHelper
)))
411 m_pDropTargetHelper
= NULL
;
414 CIDropTarget::~CIDropTarget()
416 if(m_pDropTargetHelper
!= NULL
)
418 m_pDropTargetHelper
->Release();
419 m_pDropTargetHelper
= NULL
;
423 HRESULT STDMETHODCALLTYPE
CIDropTarget::QueryInterface( /* [in] */ REFIID riid
,
424 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
427 if (IID_IUnknown
==riid
|| IID_IDropTarget
==riid
)
430 if (*ppvObject
!= NULL
)
432 ((LPUNKNOWN
)*ppvObject
)->AddRef();
435 return E_NOINTERFACE
;
438 ULONG STDMETHODCALLTYPE
CIDropTarget::Release( void)
441 nTemp
= --m_cRefCount
;
442 ATLASSERT(nTemp
>= 0);
448 bool CIDropTarget::QueryDrop(DWORD grfKeyState
, LPDWORD pdwEffect
)
450 DWORD dwOKEffects
= *pdwEffect
;
454 *pdwEffect
= DROPEFFECT_NONE
;
457 //CTRL+SHIFT -- DROPEFFECT_LINK
458 //CTRL -- DROPEFFECT_COPY
459 //SHIFT -- DROPEFFECT_MOVE
460 //no modifier -- DROPEFFECT_MOVE or whatever is allowed by src
461 *pdwEffect
= (grfKeyState
& MK_CONTROL
) ?
462 ( (grfKeyState
& MK_SHIFT
) ? DROPEFFECT_LINK
: DROPEFFECT_COPY
):
463 ( (grfKeyState
& MK_SHIFT
) ? DROPEFFECT_MOVE
: 0 );
466 // No modifier keys used by user while dragging.
467 if (DROPEFFECT_MOVE
& dwOKEffects
)
468 *pdwEffect
= DROPEFFECT_MOVE
;
469 else if (DROPEFFECT_COPY
& dwOKEffects
)
470 *pdwEffect
= DROPEFFECT_COPY
;
471 else if (DROPEFFECT_LINK
& dwOKEffects
)
472 *pdwEffect
= DROPEFFECT_LINK
;
475 *pdwEffect
= DROPEFFECT_NONE
;
480 // Check if the drag source application allows the drop effect desired by user.
481 // The drag source specifies this in DoDragDrop
482 if(!(*pdwEffect
& dwOKEffects
))
483 *pdwEffect
= DROPEFFECT_NONE
;
486 return (DROPEFFECT_NONE
== *pdwEffect
)?false:true;
489 HRESULT STDMETHODCALLTYPE
CIDropTarget::DragEnter(
490 /* [unique][in] */ IDataObject __RPC_FAR
*pDataObj
,
491 /* [in] */ DWORD grfKeyState
,
492 /* [in] */ POINTL pt
,
493 /* [out][in] */ DWORD __RPC_FAR
*pdwEffect
)
498 if(m_pDropTargetHelper
)
499 m_pDropTargetHelper
->DragEnter(m_hTargetWnd
, pDataObj
, (LPPOINT
)&pt
, *pdwEffect
);
500 //IEnumFORMATETC* pEnum;
501 //pDataObj->EnumFormatEtc(DATADIR_GET,&pEnum);
504 //pEnum->Next(1,&ftm,0);
506 m_pSupportedFrmt
= NULL
;
507 for(int i
=0; i
<m_formatetc
.GetSize(); ++i
)
509 m_bAllowDrop
= (pDataObj
->QueryGetData(&m_formatetc
[i
]) == S_OK
)?true:false;
512 m_pSupportedFrmt
= &m_formatetc
[i
];
517 QueryDrop(grfKeyState
, pdwEffect
);
521 HRESULT STDMETHODCALLTYPE
CIDropTarget::DragOver(
522 /* [in] */ DWORD grfKeyState
,
523 /* [in] */ POINTL pt
,
524 /* [out][in] */ DWORD __RPC_FAR
*pdwEffect
)
526 if(m_pDropTargetHelper
)
527 m_pDropTargetHelper
->DragOver((LPPOINT
)&pt
, *pdwEffect
);
528 QueryDrop(grfKeyState
, pdwEffect
);
532 HRESULT STDMETHODCALLTYPE
CIDropTarget::DragLeave( void)
534 if(m_pDropTargetHelper
)
535 m_pDropTargetHelper
->DragLeave();
537 m_bAllowDrop
= false;
538 m_pSupportedFrmt
= NULL
;
542 HRESULT STDMETHODCALLTYPE
CIDropTarget::Drop(
543 /* [unique][in] */ IDataObject __RPC_FAR
*pDataObj
,
544 /* [in] */ DWORD grfKeyState
, /* [in] */ POINTL pt
,
545 /* [out][in] */ DWORD __RPC_FAR
*pdwEffect
)
547 if (pDataObj
== NULL
)
550 if(m_pDropTargetHelper
)
551 m_pDropTargetHelper
->Drop(pDataObj
, (LPPOINT
)&pt
, *pdwEffect
);
553 if(QueryDrop(grfKeyState
, pdwEffect
))
555 if(m_bAllowDrop
&& m_pSupportedFrmt
!= NULL
)
558 if(pDataObj
->GetData(m_pSupportedFrmt
, &medium
) == S_OK
)
560 if(OnDrop(m_pSupportedFrmt
, medium
, pdwEffect
, pt
)) //does derive class wants us to free medium?
561 ReleaseStgMedium(&medium
);
566 *pdwEffect
= DROPEFFECT_NONE
;
567 m_pSupportedFrmt
= NULL
;
571 //////////////////////////////////////////////////////////////////////
572 // CIDragSourceHelper Class
573 //////////////////////////////////////////////////////////////////////