dragdropimpl.cpp

Go to the documentation of this file.
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 doxygen

ROS Explorer Homepage