nim_duilib/examples/multi_browser/dragdrop/drag_drop.cpp

405 lines
9.1 KiB
C++
Raw Normal View History

2019-04-19 17:19:57 +08:00
#include "drag_drop.h"
#include <shlobj.h>
#include <shlobj.h>
#include <shlwapi.h>
SdkDataObject::SdkDataObject(/*SdkDropSource *pDropSource*/)
{
m_lRefCount = 1;
}
SdkDataObject::~SdkDataObject(void)
{
m_lRefCount = 0;
int nSize = (int)m_dataStorageCL.size();
for (int i = 0; i < nSize; ++i)
{
DATASTORAGE_t dataEntry = m_dataStorageCL.at(i);
ReleaseStgMedium(dataEntry.m_stgMedium);
if (dataEntry.m_stgMedium)
{
delete dataEntry.m_stgMedium;
}
if (dataEntry.m_formatEtc)
{
delete dataEntry.m_formatEtc;
}
}
}
STDMETHODIMP SdkDataObject::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(SdkDataObject, IDataObject),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
//return E_NOTIMPL;
}
STDMETHODIMP_(ULONG) SdkDataObject::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
STDMETHODIMP_(ULONG) SdkDataObject::Release()
{
ULONG lRef = InterlockedDecrement(&m_lRefCount);
if (0 == lRef)
{
delete this;
return 0;
}
return m_lRefCount;
}
STDMETHODIMP SdkDataObject::GetData(FORMATETC *pformatetcIn,
STGMEDIUM *pmedium)
{
if ((NULL == pformatetcIn) || (NULL == pmedium))
{
return E_INVALIDARG;
}
pmedium->hGlobal = NULL;
int nSize = (int)m_dataStorageCL.size();
for (int i = 0; i < nSize; ++i)
{
DATASTORAGE_t dataEntry = m_dataStorageCL.at(i);
if ((pformatetcIn->tymed & dataEntry.m_formatEtc->tymed) &&
(pformatetcIn->dwAspect == dataEntry.m_formatEtc->dwAspect) &&
(pformatetcIn->cfFormat == dataEntry.m_formatEtc->cfFormat))
{
return CopyMedium(pmedium,
dataEntry.m_stgMedium, dataEntry.m_formatEtc);
}
}
return DV_E_FORMATETC;
}
STDMETHODIMP SdkDataObject::SetData(FORMATETC *pformatetc,
STGMEDIUM *pmedium, BOOL fRelease)
{
if ((NULL == pformatetc) || (NULL == pmedium))
{
return E_INVALIDARG;
}
if (pformatetc->tymed != pmedium->tymed)
{
return E_FAIL;
}
FORMATETC* fetc = new FORMATETC;
STGMEDIUM* pStgMed = new STGMEDIUM;
ZeroMemory(fetc, sizeof(FORMATETC));
ZeroMemory(pStgMed, sizeof(STGMEDIUM));
*fetc = *pformatetc;
if (TRUE == fRelease)
{
*pStgMed = *pmedium;
}
else
{
CopyMedium(pStgMed, pmedium, pformatetc);
}
DATASTORAGE_t dataEntry = { fetc, pStgMed };
m_dataStorageCL.push_back(dataEntry);
return S_OK;
}
STDMETHODIMP SdkDataObject::GetDataHere(
FORMATETC *pformatetc, STGMEDIUM *pmedium)
{
UNREFERENCED_PARAMETER(pformatetc);
UNREFERENCED_PARAMETER(pmedium);
return E_NOTIMPL;
}
STDMETHODIMP SdkDataObject::QueryGetData(FORMATETC *pformatetc)
{
if (NULL == pformatetc)
{
return E_INVALIDARG;
}
if (!(DVASPECT_CONTENT & pformatetc->dwAspect))
{
return DV_E_DVASPECT;
}
HRESULT hr = DV_E_TYMED;
int nSize = m_dataStorageCL.size();
for (int i = 0; i < nSize; ++i)
{
DATASTORAGE_t dataEnrty = m_dataStorageCL.at(i);
if (dataEnrty.m_formatEtc->tymed & pformatetc->tymed)
{
if (dataEnrty.m_formatEtc->cfFormat == pformatetc->cfFormat)
{
return S_OK;
}
else
{
hr = DV_E_CLIPFORMAT;
}
}
else
{
hr = DV_E_TYMED;
}
}
return hr;
}
STDMETHODIMP SdkDataObject::GetCanonicalFormatEtc(FORMATETC *pformatetcIn, FORMATETC *pformatetcOut)
{
return E_NOTIMPL;
}
STDMETHODIMP SdkDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
{
if (NULL == ppenumFormatEtc)
{
return E_INVALIDARG;
}
*ppenumFormatEtc = NULL;
HRESULT hr = E_NOTIMPL;
if (DATADIR_GET == dwDirection)
{
int nSize = m_dataStorageCL.size();
FORMATETC* rgfmtetc = new FORMATETC[nSize];
for (int i = 0; i < nSize; ++i)
{
DATASTORAGE_t dataEnrty = m_dataStorageCL.at(i);
rgfmtetc[i] = *dataEnrty.m_formatEtc;
}
hr = SHCreateStdEnumFmtEtc(nSize, rgfmtetc, ppenumFormatEtc);
}
return hr;
}
STDMETHODIMP SdkDataObject::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSnk, DWORD *pdwConnection)
{
UNREFERENCED_PARAMETER(pformatetc);
UNREFERENCED_PARAMETER(advf);
UNREFERENCED_PARAMETER(pAdvSnk);
UNREFERENCED_PARAMETER(pdwConnection);
return E_NOTIMPL;
}
STDMETHODIMP SdkDataObject::DUnadvise(DWORD dwConnection)
{
UNREFERENCED_PARAMETER(dwConnection);
return E_NOTIMPL;
}
STDMETHODIMP SdkDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
{
UNREFERENCED_PARAMETER(ppenumAdvise);
return E_NOTIMPL;
}
HRESULT SdkDataObject::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc)
{
if ((NULL == pMedDest) || (NULL == pMedSrc) || (NULL == pFmtSrc))
{
return E_INVALIDARG;
}
switch (pMedSrc->tymed)
{
case TYMED_HGLOBAL:
pMedDest->hGlobal = (HGLOBAL)OleDuplicateData(pMedSrc->hGlobal, pFmtSrc->cfFormat, NULL);
break;
case TYMED_GDI:
pMedDest->hBitmap = (HBITMAP)OleDuplicateData(pMedSrc->hBitmap, pFmtSrc->cfFormat, NULL);
break;
case TYMED_MFPICT:
pMedDest->hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(pMedSrc->hMetaFilePict, pFmtSrc->cfFormat, NULL);
break;
case TYMED_ENHMF:
pMedDest->hEnhMetaFile = (HENHMETAFILE)OleDuplicateData(pMedSrc->hEnhMetaFile, pFmtSrc->cfFormat, NULL);
break;
case TYMED_FILE:
pMedDest->lpszFileName = (LPOLESTR)OleDuplicateData(pMedSrc->lpszFileName, pFmtSrc->cfFormat, NULL);
break;
case TYMED_ISTREAM:
pMedDest->pstm = pMedSrc->pstm;
pMedSrc->pstm->AddRef();
break;
case TYMED_ISTORAGE:
pMedDest->pstg = pMedSrc->pstg;
pMedSrc->pstg->AddRef();
break;
case TYMED_NULL:
default:
break;
}
pMedDest->tymed = pMedSrc->tymed;
pMedDest->pUnkForRelease = NULL;
if (pMedSrc->pUnkForRelease != NULL)
{
pMedDest->pUnkForRelease = pMedSrc->pUnkForRelease;
pMedSrc->pUnkForRelease->AddRef();
}
return S_OK;
}
HRESULT SdkDataObject::SetBlob(CLIPFORMAT cf, const void *pvBlob, UINT cbBlob)
{
void *pv = GlobalAlloc(GPTR, cbBlob);
HRESULT hr = pv ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
CopyMemory(pv, pvBlob, cbBlob);
FORMATETC fmte = { cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
// The STGMEDIUM structure is used to define how to handle a global memory transfer.
// This structure includes a flag, tymed, which indicates the medium
// to be used, and a union comprising pointers and a handle for getting whichever
// medium is specified in tymed.
STGMEDIUM medium = {};
medium.tymed = TYMED_HGLOBAL;
medium.hGlobal = pv;
hr = this->SetData(&fmte, &medium, TRUE);
if (FAILED(hr))
{
GlobalFree(pv);
}
}
return hr;
}
HGLOBAL CreateGlobalHandle(IN void* ptr, int size)
{
HGLOBAL hGlobal = NULL;
hGlobal = GlobalAlloc(GMEM_FIXED, size);
if (NULL != hGlobal)
{
LPVOID pdest = GlobalLock(hGlobal);
if (NULL != pdest)
{
memcpy_s(pdest, size, ptr, size);
}
GlobalUnlock(hGlobal);
}
return hGlobal;
}
//////////////////////////////////////////////////////////////////////
// SdkDropSource Class
//////////////////////////////////////////////////////////////////////
SdkDropSource::SdkDropSource()
{
m_cRefCount = 1;
m_bDropped = false;
m_feedbackCursor = NULL;
}
STDMETHODIMP SdkDropSource::QueryInterface(/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
*ppvObject = NULL;
if (IID_IUnknown==riid || IID_IDropSource==riid)
*ppvObject=this;
if (*ppvObject != NULL)
{
((LPUNKNOWN)*ppvObject)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) SdkDropSource::AddRef( void)
{
return ++m_cRefCount;
}
STDMETHODIMP_(ULONG) SdkDropSource::Release( void)
{
long nTemp;
nTemp = --m_cRefCount;
ASSERT(nTemp >= 0);
2019-04-19 17:19:57 +08:00
if(nTemp==0)
delete this;
return nTemp;
}
STDMETHODIMP SdkDropSource::QueryContinueDrag(/* [in] */ BOOL fEscapePressed, /* [in] */ DWORD grfKeyState)
{
if(fEscapePressed)
return DRAGDROP_S_CANCEL;
if(!(grfKeyState & (MK_LBUTTON|MK_RBUTTON)))
{
m_bDropped = true;
return DRAGDROP_S_DROP;
}
return S_OK;
}
STDMETHODIMP SdkDropSource::GiveFeedback( /* [in] */ DWORD dwEffect)
{
if (NULL != m_feedbackCursor)
{
::SetCursor(m_feedbackCursor);
return S_OK;
}
else
{
return DRAGDROP_S_USEDEFAULTCURSORS;
}
}
void SdkDropSource::SetFeedbackCursor(HCURSOR cursor)
{
ASSERT(NULL != cursor);
m_feedbackCursor = cursor;
}
//////////////////////////////////////////////////////////////////////
// SdkDragSourceHelper Class
//////////////////////////////////////////////////////////////////////
SdkDragSourceHelper::SdkDragSourceHelper()
{
if (FAILED(CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER, IID_IDragSourceHelper, (void**)&m_pDragSourceHelper)))
m_pDragSourceHelper = NULL;
}
SdkDragSourceHelper::~SdkDragSourceHelper()
{
if (m_pDragSourceHelper != NULL)
{
m_pDragSourceHelper->Release();
m_pDragSourceHelper = NULL;
}
}
HRESULT SdkDragSourceHelper::InitializeFromBitmap(HBITMAP hBitmap, POINT& pt_offset, SIZE& bitmap_size, IDataObject* pDataObject, COLORREF crColorKey)
{
if (m_pDragSourceHelper == NULL)
return E_FAIL;
SHDRAGIMAGE di;
di.sizeDragImage = bitmap_size;
di.hbmpDragImage = hBitmap;
di.crColorKey = crColorKey;
di.ptOffset = pt_offset;
return m_pDragSourceHelper->InitializeFromBitmap(&di, pDataObject);
}
HRESULT SdkDragSourceHelper::InitializeFromWindow(HWND hwnd, POINT& pt, IDataObject* pDataObject)
{
if (m_pDragSourceHelper == NULL)
return E_FAIL;
return m_pDragSourceHelper->InitializeFromWindow(hwnd, &pt, pDataObject);
}