00001 #include <precomp.h> 00002 00003 /************************************************************************** 00004 THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF 00005 ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 00006 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 00007 PARTICULAR PURPOSE. 00008 Author: Leon Finker 11/2000 00009 Modifications: replaced ATL by STL, Martin Fuchs 7/2003 00010 **************************************************************************/ 00011 00012 // dragdropimp.cpp: implementation of the IDataObjectImpl class. 00013 ////////////////////////////////////////////////////////////////////// 00014 00015 //#include <shlobj.h> 00016 //#include <assert.h> 00017 00018 //#include "dragdropimpl.h" 00019 00020 ////////////////////////////////////////////////////////////////////// 00021 // IDataObjectImpl Class 00022 ////////////////////////////////////////////////////////////////////// 00023 00024 IDataObjectImpl::IDataObjectImpl(IDropSourceImpl* pDropSource) 00025 : super(IID_IDataObject), 00026 m_pDropSource(pDropSource), 00027 m_cRefCount(0) 00028 { 00029 } 00030 00031 IDataObjectImpl::~IDataObjectImpl() 00032 { 00033 for(StorageArray::iterator it=_storage.begin(); it!=_storage.end(); ++it) 00034 ReleaseStgMedium(it->_medium); 00035 } 00036 00037 STDMETHODIMP IDataObjectImpl::GetData( 00038 /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn, 00039 /* [out] */ STGMEDIUM __RPC_FAR *pmedium) 00040 { 00041 if (pformatetcIn == NULL || pmedium == NULL) 00042 return E_INVALIDARG; 00043 00044 pmedium->hGlobal = NULL; 00045 00046 for(StorageArray::iterator it=_storage.begin(); it!=_storage.end(); ++it) 00047 { 00048 if (pformatetcIn->tymed & it->_format->tymed && 00049 pformatetcIn->dwAspect == it->_format->dwAspect && 00050 pformatetcIn->cfFormat == it->_format->cfFormat) 00051 { 00052 CopyMedium(pmedium, it->_medium, it->_format); 00053 return S_OK; 00054 } 00055 } 00056 00057 return DV_E_FORMATETC; 00058 } 00059 00060 STDMETHODIMP IDataObjectImpl::GetDataHere( 00061 /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc, 00062 /* [out][in] */ STGMEDIUM __RPC_FAR *pmedium) 00063 { 00064 return E_NOTIMPL; 00065 } 00066 00067 STDMETHODIMP IDataObjectImpl::QueryGetData( 00068 /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc) 00069 { 00070 if (pformatetc == NULL) 00071 return E_INVALIDARG; 00072 00073 //support others if needed DVASPECT_THUMBNAIL //DVASPECT_ICON //DVASPECT_DOCPRINT 00074 if (!(DVASPECT_CONTENT & pformatetc->dwAspect)) 00075 return (DV_E_DVASPECT); 00076 00077 HRESULT hr = DV_E_TYMED; 00078 00079 for(StorageArray::iterator it=_storage.begin(); it!=_storage.end(); ++it) 00080 { 00081 if (pformatetc->tymed & it->_format->tymed) 00082 { 00083 if (pformatetc->cfFormat == it->_format->cfFormat) 00084 return S_OK; 00085 else 00086 hr = DV_E_CLIPFORMAT; 00087 } 00088 else 00089 hr = DV_E_TYMED; 00090 } 00091 00092 return hr; 00093 } 00094 00095 STDMETHODIMP IDataObjectImpl::GetCanonicalFormatEtc( 00096 /* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn, 00097 /* [out] */ FORMATETC __RPC_FAR *pformatetcOut) 00098 { 00099 if (pformatetcOut == NULL) 00100 return E_INVALIDARG; 00101 00102 return DATA_S_SAMEFORMATETC; 00103 } 00104 00105 STDMETHODIMP IDataObjectImpl::SetData( 00106 /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc, 00107 /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium, 00108 /* [in] */ BOOL fRelease) 00109 { 00110 if (pformatetc == NULL || pmedium == NULL) 00111 return E_INVALIDARG; 00112 00113 assert(pformatetc->tymed == pmedium->tymed); 00114 FORMATETC* fetc=new FORMATETC; 00115 STGMEDIUM* pStgMed = new STGMEDIUM; 00116 00117 if (fetc == NULL || pStgMed == NULL) 00118 return E_OUTOFMEMORY; 00119 00120 ZeroMemory(fetc, sizeof(FORMATETC)); 00121 ZeroMemory(pStgMed, sizeof(STGMEDIUM)); 00122 00123 *fetc = *pformatetc; 00124 00125 if (fRelease) 00126 *pStgMed = *pmedium; 00127 else 00128 CopyMedium(pStgMed, pmedium, pformatetc); 00129 00130 DataStorage storage; 00131 00132 storage._format = fetc; 00133 storage._medium = pStgMed; 00134 00135 _storage.push_back(storage); 00136 00137 return S_OK; 00138 } 00139 00140 void IDataObjectImpl::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc) 00141 { 00142 switch(pMedSrc->tymed) 00143 { 00144 case TYMED_HGLOBAL: 00145 pMedDest->hGlobal = (HGLOBAL)OleDuplicateData(pMedSrc->hGlobal, pFmtSrc->cfFormat, 0); 00146 break; 00147 case TYMED_GDI: 00148 pMedDest->hBitmap = (HBITMAP)OleDuplicateData(pMedSrc->hBitmap, pFmtSrc->cfFormat, 0); 00149 break; 00150 case TYMED_MFPICT: 00151 pMedDest->hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(pMedSrc->hMetaFilePict, pFmtSrc->cfFormat, 0); 00152 break; 00153 case TYMED_ENHMF: 00154 pMedDest->hEnhMetaFile = (HENHMETAFILE)OleDuplicateData(pMedSrc->hEnhMetaFile, pFmtSrc->cfFormat, 0); 00155 break; 00156 case TYMED_FILE: 00157 pMedDest->lpszFileName = (LPOLESTR)OleDuplicateData(pMedSrc->lpszFileName, pFmtSrc->cfFormat, 0); 00158 break; 00159 case TYMED_ISTREAM: 00160 pMedDest->pstm = pMedSrc->pstm; 00161 pMedSrc->pstm->AddRef(); 00162 break; 00163 case TYMED_ISTORAGE: 00164 pMedDest->pstg = pMedSrc->pstg; 00165 pMedSrc->pstg->AddRef(); 00166 break; 00167 case TYMED_NULL: 00168 default: 00169 break; 00170 } 00171 pMedDest->tymed = pMedSrc->tymed; 00172 pMedDest->pUnkForRelease = pMedSrc->pUnkForRelease; 00173 } 00174 00175 STDMETHODIMP IDataObjectImpl::EnumFormatEtc( 00176 /* [in] */ DWORD dwDirection, 00177 /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc) 00178 { 00179 if (ppenumFormatEtc == NULL) 00180 return E_POINTER; 00181 00182 *ppenumFormatEtc=NULL; 00183 switch (dwDirection) 00184 { 00185 case DATADIR_GET: 00186 *ppenumFormatEtc = new EnumFormatEtcImpl(_storage); 00187 00188 if (!*ppenumFormatEtc) 00189 return E_OUTOFMEMORY; 00190 00191 (*ppenumFormatEtc)->AddRef(); 00192 break; 00193 00194 case DATADIR_SET: 00195 default: 00196 return E_NOTIMPL; 00197 break; 00198 } 00199 00200 return S_OK; 00201 } 00202 00203 STDMETHODIMP IDataObjectImpl::DAdvise( 00204 /* [in] */ FORMATETC __RPC_FAR *pformatetc, 00205 /* [in] */ DWORD advf, 00206 /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink, 00207 /* [out] */ DWORD __RPC_FAR *pdwConnection) 00208 { 00209 return OLE_E_ADVISENOTSUPPORTED; 00210 } 00211 00212 STDMETHODIMP IDataObjectImpl::DUnadvise( 00213 /* [in] */ DWORD dwConnection) 00214 { 00215 return E_NOTIMPL; 00216 } 00217 00218 HRESULT STDMETHODCALLTYPE IDataObjectImpl::EnumDAdvise( 00219 /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) 00220 { 00221 return OLE_E_ADVISENOTSUPPORTED; 00222 } 00223 00224 ////////////////////////////////////////////////////////////////////// 00225 // IDropSourceImpl Class 00226 ////////////////////////////////////////////////////////////////////// 00227 00228 STDMETHODIMP IDropSourceImpl::QueryContinueDrag( 00229 /* [in] */ BOOL fEscapePressed, 00230 /* [in] */ DWORD grfKeyState) 00231 { 00232 if (fEscapePressed) 00233 return DRAGDROP_S_CANCEL; 00234 if (!(grfKeyState & (MK_LBUTTON|MK_RBUTTON))) 00235 { 00236 m_bDropped = true; 00237 return DRAGDROP_S_DROP; 00238 } 00239 00240 return S_OK; 00241 00242 } 00243 00244 STDMETHODIMP IDropSourceImpl::GiveFeedback( 00245 /* [in] */ DWORD dwEffect) 00246 { 00247 return DRAGDROP_S_USEDEFAULTCURSORS; 00248 } 00249 00250 ////////////////////////////////////////////////////////////////////// 00251 // EnumFormatEtcImpl Class 00252 ////////////////////////////////////////////////////////////////////// 00253 00254 EnumFormatEtcImpl::EnumFormatEtcImpl(const FormatArray& ArrFE) 00255 : super(IID_IEnumFORMATETC), 00256 m_cRefCount(0), 00257 m_iCur(0) 00258 { 00259 for(FormatArray::const_iterator it=ArrFE.begin(); it!=ArrFE.end(); ++it) 00260 m_pFmtEtc.push_back(*it); 00261 } 00262 00263 EnumFormatEtcImpl::EnumFormatEtcImpl(const StorageArray& ArrFE) 00264 : super(IID_IEnumFORMATETC), 00265 m_cRefCount(0), 00266 m_iCur(0) 00267 { 00268 for(StorageArray::const_iterator it=ArrFE.begin(); it!=ArrFE.end(); ++it) 00269 m_pFmtEtc.push_back(*it->_format); 00270 } 00271 00272 STDMETHODIMP EnumFormatEtcImpl::Next(ULONG celt,LPFORMATETC lpFormatEtc, ULONG* pceltFetched) 00273 { 00274 if (pceltFetched != NULL) 00275 *pceltFetched=0; 00276 00277 ULONG cReturn = celt; 00278 00279 if (celt <= 0 || lpFormatEtc == NULL || m_iCur >= m_pFmtEtc.size()) 00280 return S_FALSE; 00281 00282 if (pceltFetched == NULL && celt != 1) // pceltFetched can be NULL only for 1 item request 00283 return S_FALSE; 00284 00285 while (m_iCur < m_pFmtEtc.size() && cReturn > 0) 00286 { 00287 *lpFormatEtc++ = m_pFmtEtc[m_iCur++]; 00288 --cReturn; 00289 } 00290 if (pceltFetched != NULL) 00291 *pceltFetched = celt - cReturn; 00292 00293 return (cReturn == 0) ? S_OK : S_FALSE; 00294 } 00295 00296 STDMETHODIMP EnumFormatEtcImpl::Skip(ULONG celt) 00297 { 00298 if ((m_iCur + int(celt)) >= m_pFmtEtc.size()) 00299 return S_FALSE; 00300 00301 m_iCur += celt; 00302 return S_OK; 00303 } 00304 00305 STDMETHODIMP EnumFormatEtcImpl::Reset(void) 00306 { 00307 m_iCur = 0; 00308 return S_OK; 00309 } 00310 00311 STDMETHODIMP EnumFormatEtcImpl::Clone(IEnumFORMATETC** ppCloneEnumFormatEtc) 00312 { 00313 if (ppCloneEnumFormatEtc == NULL) 00314 return E_POINTER; 00315 00316 EnumFormatEtcImpl* newEnum = new EnumFormatEtcImpl(m_pFmtEtc); 00317 00318 if (!newEnum) 00319 return E_OUTOFMEMORY; 00320 00321 newEnum->AddRef(); 00322 newEnum->m_iCur = m_iCur; 00323 *ppCloneEnumFormatEtc = newEnum; 00324 00325 return S_OK; 00326 } 00327 00328 ////////////////////////////////////////////////////////////////////// 00329 // IDropTargetImpl Class 00330 ////////////////////////////////////////////////////////////////////// 00331 IDropTargetImpl::IDropTargetImpl(HWND hTargetWnd) 00332 : m_cRefCount(0), 00333 m_bAllowDrop(false), 00334 m_pDropTargetHelper(NULL), 00335 m_pSupportedFrmt(NULL), 00336 m_hTargetWnd(hTargetWnd) 00337 { 00338 assert(m_hTargetWnd != NULL); 00339 00340 if (FAILED(CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER, 00341 IID_IDropTargetHelper,(LPVOID*)&m_pDropTargetHelper))) 00342 m_pDropTargetHelper = NULL; 00343 } 00344 00345 IDropTargetImpl::~IDropTargetImpl() 00346 { 00347 if (m_pDropTargetHelper != NULL) 00348 { 00349 m_pDropTargetHelper->Release(); 00350 m_pDropTargetHelper = NULL; 00351 } 00352 } 00353 00354 HRESULT STDMETHODCALLTYPE IDropTargetImpl::QueryInterface( /* [in] */ REFIID riid, 00355 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) 00356 { 00357 *ppvObject = NULL; 00358 if (IID_IUnknown==riid || IID_IDropTarget==riid) 00359 *ppvObject=this; 00360 00361 if (*ppvObject != NULL) 00362 { 00363 ((LPUNKNOWN)*ppvObject)->AddRef(); 00364 return S_OK; 00365 } 00366 00367 return E_NOINTERFACE; 00368 } 00369 00370 ULONG STDMETHODCALLTYPE IDropTargetImpl::Release() 00371 { 00372 long nTemp = --m_cRefCount; 00373 00374 assert(nTemp >= 0); 00375 00376 if (nTemp == 0) 00377 delete this; 00378 00379 return nTemp; 00380 } 00381 00382 bool IDropTargetImpl::QueryDrop(DWORD grfKeyState, LPDWORD pdwEffect) 00383 { 00384 DWORD dwOKEffects = *pdwEffect; 00385 00386 if (!m_bAllowDrop) 00387 { 00388 *pdwEffect = DROPEFFECT_NONE; 00389 return false; 00390 } 00391 00392 //CTRL+SHIFT -- DROPEFFECT_LINK 00393 //CTRL -- DROPEFFECT_COPY 00394 //SHIFT -- DROPEFFECT_MOVE 00395 //no modifier -- DROPEFFECT_MOVE or whatever is allowed by src 00396 *pdwEffect = (grfKeyState & MK_CONTROL) ? 00397 ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY ): 00398 ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_MOVE : DROPEFFECT_NONE ); 00399 if (*pdwEffect == 0) 00400 { 00401 // No modifier keys used by user while dragging. 00402 if (DROPEFFECT_COPY & dwOKEffects) 00403 *pdwEffect = DROPEFFECT_COPY; 00404 else if (DROPEFFECT_MOVE & dwOKEffects) 00405 *pdwEffect = DROPEFFECT_MOVE; 00406 else if (DROPEFFECT_LINK & dwOKEffects) 00407 *pdwEffect = DROPEFFECT_LINK; 00408 else 00409 { 00410 *pdwEffect = DROPEFFECT_NONE; 00411 } 00412 } 00413 else 00414 { 00415 // Check if the drag source application allows the drop effect desired by user. 00416 // The drag source specifies this in DoDragDrop 00417 if (!(*pdwEffect & dwOKEffects)) 00418 *pdwEffect = DROPEFFECT_NONE; 00419 } 00420 00421 return (DROPEFFECT_NONE == *pdwEffect)?false:true; 00422 } 00423 00424 HRESULT STDMETHODCALLTYPE IDropTargetImpl::DragEnter( 00425 /* [unique][in] */ IDataObject __RPC_FAR *pDataObj, 00426 /* [in] */ DWORD grfKeyState, 00427 /* [in] */ POINTL pt, 00428 /* [out][in] */ DWORD __RPC_FAR *pdwEffect) 00429 { 00430 if (pDataObj == NULL) 00431 return E_INVALIDARG; 00432 00433 if (m_pDropTargetHelper) 00434 m_pDropTargetHelper->DragEnter(m_hTargetWnd, pDataObj, (LPPOINT)&pt, *pdwEffect); 00435 00436 //IEnumFORMATETC* pEnum; 00437 //pDataObj->EnumFormatEtc(DATADIR_GET,&pEnum); 00438 //FORMATETC ftm; 00439 //for() 00440 //pEnum->Next(1,&ftm,0); 00441 //pEnum->Release(); 00442 m_pSupportedFrmt = NULL; 00443 00444 for(FormatArray::iterator it=m_formatetc.begin(); it!=m_formatetc.end(); ++it) 00445 { 00446 m_bAllowDrop = (pDataObj->QueryGetData(&*it) == S_OK)? true: false; 00447 00448 if (m_bAllowDrop) 00449 { 00450 m_pSupportedFrmt = &*it; 00451 break; 00452 } 00453 } 00454 00455 QueryDrop(grfKeyState, pdwEffect); 00456 00457 return S_OK; 00458 } 00459 00460 HRESULT STDMETHODCALLTYPE IDropTargetImpl::DragOver( 00461 /* [in] */ DWORD grfKeyState, 00462 /* [in] */ POINTL pt, 00463 /* [out][in] */ DWORD __RPC_FAR *pdwEffect) 00464 { 00465 if (m_pDropTargetHelper) 00466 m_pDropTargetHelper->DragOver((LPPOINT)&pt, *pdwEffect); 00467 00468 QueryDrop(grfKeyState, pdwEffect); 00469 00470 return S_OK; 00471 } 00472 00473 HRESULT STDMETHODCALLTYPE IDropTargetImpl::DragLeave() 00474 { 00475 if (m_pDropTargetHelper) 00476 m_pDropTargetHelper->DragLeave(); 00477 00478 m_bAllowDrop = false; 00479 m_pSupportedFrmt = NULL; 00480 00481 return S_OK; 00482 } 00483 00484 HRESULT STDMETHODCALLTYPE IDropTargetImpl::Drop( 00485 /* [unique][in] */ IDataObject __RPC_FAR *pDataObj, 00486 /* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt, 00487 /* [out][in] */ DWORD __RPC_FAR *pdwEffect) 00488 { 00489 if (pDataObj == NULL) 00490 return E_INVALIDARG; 00491 00492 if (m_pDropTargetHelper) 00493 m_pDropTargetHelper->Drop(pDataObj, (LPPOINT)&pt, *pdwEffect); 00494 00495 if (QueryDrop(grfKeyState, pdwEffect)) 00496 { 00497 if (m_bAllowDrop && m_pSupportedFrmt != NULL) 00498 { 00499 STGMEDIUM medium; 00500 00501 if (pDataObj->GetData(m_pSupportedFrmt, &medium) == S_OK) 00502 { 00503 if (OnDrop(m_pSupportedFrmt, medium, pdwEffect)) //does derive class wants us to free medium? 00504 ReleaseStgMedium(&medium); 00505 } 00506 } 00507 } 00508 00509 m_bAllowDrop = false; 00510 *pdwEffect = DROPEFFECT_NONE; 00511 m_pSupportedFrmt = NULL; 00512 00513 return S_OK; 00514 }
ROS Explorer Source Code Documentation
generated on 02.01.2013 by ![]() |