//
---------------------------------------------------------------------------
// DragSource Lib.
// Copyright (c) 2006, 2007 by Mao yongjun
// All rights reserved
// Add "WINOLEAPI OleInitialize (LPVOID pvReserved)" before use DragDropLib on each thread
// Don't forget "WINOLEAPI OleUninitialize ()" on exit the thread
// ---------------------------------------------------------------------------
#pragma hdrstop
#include " DragDrop.h "
#pragma package(smart_init)
void * THDROP_Files::Create_HDROP() const
... {
struct TMyDropFiles...{
DWORD pFiles;
POINT pt;
BOOL fNC;
BOOL fWide;
char szFiles[1];
};
size_t MemSize=0;
for(const_iterator i=begin();i!=end();i++)
...{
MemSize+=i->length();
MemSize++;
}
void* ptr=GlobalAlloc(GMEM_FIXED,sizeof(TMyDropFiles)+MemSize);
ZeroMemory(ptr,sizeof(TMyDropFiles)+MemSize);
TMyDropFiles *FileNames=new (ptr)TMyDropFiles;
FileNames->pFiles=(unsigned)FileNames->szFiles - (unsigned)(&FileNames->pFiles);
char *p=FileNames->szFiles;
for(const_iterator i=begin();i!=end();i++)
...{
size_t len=i->length();
CopyMemory(p,i->c_str(),len);
p+=len;
*(p++)=0;
}
*p=0;
return ptr;
}
// ------------------------------TDropSource---------------------------------------------
HANDLE MemToHandle ( void * pMem, int nSize)
... {
void* ptr=GlobalAlloc(GMEM_FIXED, nSize);
CopyMemory(ptr, pMem, nSize);
return ptr;
}
HRESULT __stdcall TDropSource::QueryInterface(REFIID iid, void ** ppv)
... {
if((iid==IID_IUnknown)||(iid==IID_IDropSource))
...{
*ppv=this;
AddRef();
}
else
...{
*ppv=NULL;
return E_NOINTERFACE;
}
return S_OK;
}
HRESULT __stdcall TDropSource::QueryContinueDrag(BOOL fEscapePressed,DWORD grfKeyState)
... {
return fEscapePressed?DRAGDROP_S_CANCEL:((grfKeyState&MK_LBUTTON)?S_OK:DRAGDROP_S_DROP);
}
HRESULT __stdcall TDropSource::GiveFeedback(DWORD dwEffect)
... {
return DRAGDROP_S_USEDEFAULTCURSORS;
}
// -------------------------------TDataObject--------------------------------------------
HGLOBAL DupGlobalMem (HGLOBAL hMem)
... {
DWORD len = GlobalSize (hMem);
PVOID source = GlobalLock (hMem);
PVOID dest = GlobalAlloc (GMEM_FIXED, len);
memcpy (dest, source, len);
GlobalUnlock (hMem);
return dest;
}
HRESULT CreateDataObject (FORMATETC * fmtetc, STGMEDIUM * stgmeds, UINT count, IDataObject ** ppDataObject)
... {
if(ppDataObject == 0)
return E_INVALIDARG;
*ppDataObject = new TDataObject;
((TDataObject *)(*ppDataObject))->Add(fmtetc, stgmeds, count);
return (*ppDataObject) ? S_OK : E_OUTOFMEMORY;
}
HRESULT __stdcall TDataObject::QueryInterface(REFIID iid, void ** ppv)
... {
if((iid==IID_IUnknown)||(iid==IID_IDataObject))
...{
*ppv=this;
AddRef();
return S_OK;
}
else
...{
*ppv=NULL;
return E_NOINTERFACE;
}
}
HRESULT __stdcall TDataObject::QueryGetData(FORMATETC * pFormatEtc)
... {
return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
}
HRESULT __stdcall TDataObject::GetData (FORMATETC * pFormatEtc, STGMEDIUM * pStgMedium)
... {
int idx;
if((idx = LookupFormatEtc(pFormatEtc)) == -1)
return DV_E_FORMATETC;
pStgMedium->tymed = _pFormatEtc[idx].tymed;
pStgMedium->pUnkForRelease = 0;
switch(_pFormatEtc[idx].tymed)
...{
case TYMED_HGLOBAL:
pStgMedium->hGlobal = DupGlobalMem(_pStgMedium[idx].hGlobal);
break;
case TYMED_GDI:
pStgMedium->hBitmap = CopyImage(_pStgMedium[idx].hBitmap,IMAGE_BITMAP,0,0,0);
break;
default:
return DV_E_FORMATETC;
}
return S_OK;
}
int TDataObject::LookupFormatEtc(FORMATETC * pFormatEtc)
... {
// 轮流检查格式看是否能找到匹配的格式
for(size_t i = 0; i < _pFormatEtc.size(); i++)
...{
if((_pFormatEtc[i].tymed & pFormatEtc->tymed) &&
_pFormatEtc[i].cfFormat == pFormatEtc->cfFormat &&
_pFormatEtc[i].dwAspect == pFormatEtc->dwAspect)
...{
return i;
}
}
return -1;
}
HRESULT __stdcall TDataObject::EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC ** ppEnumFormatEtc)
... {
// OLE仅仅支持得到方向成员
if(dwDirection == DATADIR_GET)
...{
// 在WIN2K下,你可以调用API函数SHCreateStdEnumFmtEtc来完成,但为了支持//所有的window平台,我们需要实现IEnumFormatEtc。
return CreateEnumFormatEtc(_pFormatEtc.size(), &_pFormatEtc[0], ppEnumFormatEtc);
}
else
...{
// the direction specified is not supported for drag+drop
return E_NOTIMPL;
}
}
void TDataObject::Add(CLIPFORMAT ctFormat,DWORD tymed, void * hStorage)
... {
FORMATETC fmtetc = ...{
ctFormat, // we will be dropping some text
0,
DVASPECT_CONTENT,
-1,
tymed // stored as a HGLOBAL
};
STGMEDIUM stgmed = ...{
tymed,
...{hStorage},
0
};
_pFormatEtc.push_back(fmtetc);
_pStgMedium.push_back(stgmed);
}
void TDataObject::Add(FORMATETC * fmtetc, STGMEDIUM * stgmeds, UINT count = 1 )
... {
for(UINT i=0;i<count;i++)
...{
_pFormatEtc.push_back(fmtetc[i]);
_pStgMedium.push_back(stgmeds[i]);
}
}
void TDataObject::Clear()
... {
_pFormatEtc.clear();
_pStgMedium.clear();
}
void TDataObject::ClearAndRelease()
... {
for(size_t i=0;i<_pFormatEtc.size();i++)
ReleaseStgMedium(&_pStgMedium[i]);
Clear();
}
// -------------------------------TEnumFormatEtc--------------------------------------------
HRESULT CreateEnumFormatEtc (UINT cfmt, FORMATETC * afmt, IEnumFORMATETC ** ppEnumFormatEtc)
... {
if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
return E_INVALIDARG;
*ppEnumFormatEtc = new TEnumFormatEtc (afmt, cfmt);
if(*ppEnumFormatEtc)
...{
return S_OK;
}
else
...{
return E_OUTOFMEMORY;
}
}
void DeepCopyFormatEtc(FORMATETC * dest, FORMATETC * source)
... {
// copy the source FORMATETC into dest
*dest = *source;
if(source->ptd)
...{
// allocate memory for the DVTARGETDEVICE if necessary
dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
// copy the contents of the source DVTARGETDEVICE into dest->ptd
*(dest->ptd) = *(source->ptd);
}
}
TEnumFormatEtc::TEnumFormatEtc(FORMATETC * pFormatEtc, ULONG nNumFormats)
:_iRefCount( 1 ),_nIndex( 0 ),_nNumFormats(nNumFormats)
... {
_pFormatEtc = new FORMATETC[nNumFormats];
// make a new copy of each FORMATETC structure
for(ULONG i = 0; i < nNumFormats; i++)
...{
DeepCopyFormatEtc (&_pFormatEtc[i], &pFormatEtc[i]);
}
}
TEnumFormatEtc:: ~ TEnumFormatEtc()
... {
// first free any DVTARGETDEVICE structures
for(ULONG i = 0; i < _nNumFormats; i++)
...{
if(_pFormatEtc[i].ptd)
CoTaskMemFree(_pFormatEtc[i].ptd);
}
// now free the main array
delete[] _pFormatEtc;
}
HRESULT __stdcall TEnumFormatEtc::Next(ULONG celt, FORMATETC * pFormatEtc, ULONG * pceltFetched)
... {
ULONG copied = 0;
// copy the FORMATETC structures into the caller's buffer
while (_nIndex < _nNumFormats && copied < celt)
...{
DeepCopyFormatEtc (&pFormatEtc [copied], &_pFormatEtc [_nIndex]);
copied++;
_nIndex++;
}
// store result
if(pceltFetched != 0)
*pceltFetched = copied;
// did we copy all that was requested?
return (copied == celt) ? S_OK : S_FALSE;
}
TDropResult DoDragDrop(FORMATETC * fmtetc, STGMEDIUM * stgmeds,UINT count,DWORD dwOKEffect)
... {
IDropSource *pDropSource=new TDropSource;
TDataObject *pDataObject=new TDataObject();
pDataObject->Add(fmtetc, stgmeds, count);
DWORD dwEffect;
DWORD dwResult = DoDragDrop(pDataObject, pDropSource, dwOKEffect, &dwEffect);
pDropSource->Release();
pDataObject->Release();
TDropResult Result=...{dwResult,dwEffect};
return Result;
}
TDropResult DoDragDrop(CLIPFORMAT ctFormat,DWORD tymed, void * hStorage,DWORD dwOKEffect)
... {
FORMATETC fmtetc = ...{
ctFormat,
0,
DVASPECT_CONTENT,
-1,
tymed
};
STGMEDIUM stgmed = ...{
tymed,
...{hStorage},
0
};
TDropResult Result= DoDragDrop(&fmtetc,&stgmed,1,dwOKEffect);
ReleaseStgMedium(&stgmed);
return Result;
}
TDropResult DoDragDrop( char * szText,DWORD dwOKEffect)
... {
return DoDragDrop(
CF_TEXT,
TYMED_HGLOBAL,
MemToHandle(szText, strlen(szText)+1), //Freed
dwOKEffect
);
}
TDropResult DoDragDropURL( char * URL,DWORD dwOKEffect)
... {
return DoDragDrop(
RegisterClipboardFormat("UniformResourceLocator"),
TYMED_HGLOBAL,
MemToHandle(URL, strlen(URL)+1), //Freed
dwOKEffect
);
}
TDropResult DoDragDrop(wchar_t * wszText,DWORD dwOKEffect)
... {
return DoDragDrop(
CF_UNICODETEXT,
TYMED_HGLOBAL,
MemToHandle (wszText, wcslen(wszText)*2+2), //Freed
dwOKEffect
);
}
TDropResult DoDragDrop(HBITMAP hBitmap,DWORD dwOKEffect)
... {
FORMATETC fmtetc = ...{
CF_BITMAP,
0,
DVASPECT_CONTENT,
-1,
TYMED_GDI
};
STGMEDIUM stgmed = ...{
TYMED_GDI,
...{hBitmap},
0
};
TDropResult Result = DoDragDrop(&fmtetc,&stgmed,1,dwOKEffect);
return Result;
}
TDropResult DoDragDrop( const THDROP_Files & files,
DWORD dwOKEffect)
... {
return DoDragDrop(
CF_HDROP,
TYMED_HGLOBAL,
files.Create_HDROP(),
dwOKEffect
);
}
// DragSource Lib.
// Copyright (c) 2006, 2007 by Mao yongjun
// All rights reserved
// Add "WINOLEAPI OleInitialize (LPVOID pvReserved)" before use DragDropLib on each thread
// Don't forget "WINOLEAPI OleUninitialize ()" on exit the thread
// ---------------------------------------------------------------------------
#pragma hdrstop
#include " DragDrop.h "
#pragma package(smart_init)
void * THDROP_Files::Create_HDROP() const
... {
struct TMyDropFiles...{
DWORD pFiles;
POINT pt;
BOOL fNC;
BOOL fWide;
char szFiles[1];
};
size_t MemSize=0;
for(const_iterator i=begin();i!=end();i++)
...{
MemSize+=i->length();
MemSize++;
}
void* ptr=GlobalAlloc(GMEM_FIXED,sizeof(TMyDropFiles)+MemSize);
ZeroMemory(ptr,sizeof(TMyDropFiles)+MemSize);
TMyDropFiles *FileNames=new (ptr)TMyDropFiles;
FileNames->pFiles=(unsigned)FileNames->szFiles - (unsigned)(&FileNames->pFiles);
char *p=FileNames->szFiles;
for(const_iterator i=begin();i!=end();i++)
...{
size_t len=i->length();
CopyMemory(p,i->c_str(),len);
p+=len;
*(p++)=0;
}
*p=0;
return ptr;
}
// ------------------------------TDropSource---------------------------------------------
HANDLE MemToHandle ( void * pMem, int nSize)
... {
void* ptr=GlobalAlloc(GMEM_FIXED, nSize);
CopyMemory(ptr, pMem, nSize);
return ptr;
}
HRESULT __stdcall TDropSource::QueryInterface(REFIID iid, void ** ppv)
... {
if((iid==IID_IUnknown)||(iid==IID_IDropSource))
...{
*ppv=this;
AddRef();
}
else
...{
*ppv=NULL;
return E_NOINTERFACE;
}
return S_OK;
}
HRESULT __stdcall TDropSource::QueryContinueDrag(BOOL fEscapePressed,DWORD grfKeyState)
... {
return fEscapePressed?DRAGDROP_S_CANCEL:((grfKeyState&MK_LBUTTON)?S_OK:DRAGDROP_S_DROP);
}
HRESULT __stdcall TDropSource::GiveFeedback(DWORD dwEffect)
... {
return DRAGDROP_S_USEDEFAULTCURSORS;
}
// -------------------------------TDataObject--------------------------------------------
HGLOBAL DupGlobalMem (HGLOBAL hMem)
... {
DWORD len = GlobalSize (hMem);
PVOID source = GlobalLock (hMem);
PVOID dest = GlobalAlloc (GMEM_FIXED, len);
memcpy (dest, source, len);
GlobalUnlock (hMem);
return dest;
}
HRESULT CreateDataObject (FORMATETC * fmtetc, STGMEDIUM * stgmeds, UINT count, IDataObject ** ppDataObject)
... {
if(ppDataObject == 0)
return E_INVALIDARG;
*ppDataObject = new TDataObject;
((TDataObject *)(*ppDataObject))->Add(fmtetc, stgmeds, count);
return (*ppDataObject) ? S_OK : E_OUTOFMEMORY;
}
HRESULT __stdcall TDataObject::QueryInterface(REFIID iid, void ** ppv)
... {
if((iid==IID_IUnknown)||(iid==IID_IDataObject))
...{
*ppv=this;
AddRef();
return S_OK;
}
else
...{
*ppv=NULL;
return E_NOINTERFACE;
}
}
HRESULT __stdcall TDataObject::QueryGetData(FORMATETC * pFormatEtc)
... {
return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
}
HRESULT __stdcall TDataObject::GetData (FORMATETC * pFormatEtc, STGMEDIUM * pStgMedium)
... {
int idx;
if((idx = LookupFormatEtc(pFormatEtc)) == -1)
return DV_E_FORMATETC;
pStgMedium->tymed = _pFormatEtc[idx].tymed;
pStgMedium->pUnkForRelease = 0;
switch(_pFormatEtc[idx].tymed)
...{
case TYMED_HGLOBAL:
pStgMedium->hGlobal = DupGlobalMem(_pStgMedium[idx].hGlobal);
break;
case TYMED_GDI:
pStgMedium->hBitmap = CopyImage(_pStgMedium[idx].hBitmap,IMAGE_BITMAP,0,0,0);
break;
default:
return DV_E_FORMATETC;
}
return S_OK;
}
int TDataObject::LookupFormatEtc(FORMATETC * pFormatEtc)
... {
// 轮流检查格式看是否能找到匹配的格式
for(size_t i = 0; i < _pFormatEtc.size(); i++)
...{
if((_pFormatEtc[i].tymed & pFormatEtc->tymed) &&
_pFormatEtc[i].cfFormat == pFormatEtc->cfFormat &&
_pFormatEtc[i].dwAspect == pFormatEtc->dwAspect)
...{
return i;
}
}
return -1;
}
HRESULT __stdcall TDataObject::EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC ** ppEnumFormatEtc)
... {
// OLE仅仅支持得到方向成员
if(dwDirection == DATADIR_GET)
...{
// 在WIN2K下,你可以调用API函数SHCreateStdEnumFmtEtc来完成,但为了支持//所有的window平台,我们需要实现IEnumFormatEtc。
return CreateEnumFormatEtc(_pFormatEtc.size(), &_pFormatEtc[0], ppEnumFormatEtc);
}
else
...{
// the direction specified is not supported for drag+drop
return E_NOTIMPL;
}
}
void TDataObject::Add(CLIPFORMAT ctFormat,DWORD tymed, void * hStorage)
... {
FORMATETC fmtetc = ...{
ctFormat, // we will be dropping some text
0,
DVASPECT_CONTENT,
-1,
tymed // stored as a HGLOBAL
};
STGMEDIUM stgmed = ...{
tymed,
...{hStorage},
0
};
_pFormatEtc.push_back(fmtetc);
_pStgMedium.push_back(stgmed);
}
void TDataObject::Add(FORMATETC * fmtetc, STGMEDIUM * stgmeds, UINT count = 1 )
... {
for(UINT i=0;i<count;i++)
...{
_pFormatEtc.push_back(fmtetc[i]);
_pStgMedium.push_back(stgmeds[i]);
}
}
void TDataObject::Clear()
... {
_pFormatEtc.clear();
_pStgMedium.clear();
}
void TDataObject::ClearAndRelease()
... {
for(size_t i=0;i<_pFormatEtc.size();i++)
ReleaseStgMedium(&_pStgMedium[i]);
Clear();
}
// -------------------------------TEnumFormatEtc--------------------------------------------
HRESULT CreateEnumFormatEtc (UINT cfmt, FORMATETC * afmt, IEnumFORMATETC ** ppEnumFormatEtc)
... {
if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
return E_INVALIDARG;
*ppEnumFormatEtc = new TEnumFormatEtc (afmt, cfmt);
if(*ppEnumFormatEtc)
...{
return S_OK;
}
else
...{
return E_OUTOFMEMORY;
}
}
void DeepCopyFormatEtc(FORMATETC * dest, FORMATETC * source)
... {
// copy the source FORMATETC into dest
*dest = *source;
if(source->ptd)
...{
// allocate memory for the DVTARGETDEVICE if necessary
dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
// copy the contents of the source DVTARGETDEVICE into dest->ptd
*(dest->ptd) = *(source->ptd);
}
}
TEnumFormatEtc::TEnumFormatEtc(FORMATETC * pFormatEtc, ULONG nNumFormats)
:_iRefCount( 1 ),_nIndex( 0 ),_nNumFormats(nNumFormats)
... {
_pFormatEtc = new FORMATETC[nNumFormats];
// make a new copy of each FORMATETC structure
for(ULONG i = 0; i < nNumFormats; i++)
...{
DeepCopyFormatEtc (&_pFormatEtc[i], &pFormatEtc[i]);
}
}
TEnumFormatEtc:: ~ TEnumFormatEtc()
... {
// first free any DVTARGETDEVICE structures
for(ULONG i = 0; i < _nNumFormats; i++)
...{
if(_pFormatEtc[i].ptd)
CoTaskMemFree(_pFormatEtc[i].ptd);
}
// now free the main array
delete[] _pFormatEtc;
}
HRESULT __stdcall TEnumFormatEtc::Next(ULONG celt, FORMATETC * pFormatEtc, ULONG * pceltFetched)
... {
ULONG copied = 0;
// copy the FORMATETC structures into the caller's buffer
while (_nIndex < _nNumFormats && copied < celt)
...{
DeepCopyFormatEtc (&pFormatEtc [copied], &_pFormatEtc [_nIndex]);
copied++;
_nIndex++;
}
// store result
if(pceltFetched != 0)
*pceltFetched = copied;
// did we copy all that was requested?
return (copied == celt) ? S_OK : S_FALSE;
}
TDropResult DoDragDrop(FORMATETC * fmtetc, STGMEDIUM * stgmeds,UINT count,DWORD dwOKEffect)
... {
IDropSource *pDropSource=new TDropSource;
TDataObject *pDataObject=new TDataObject();
pDataObject->Add(fmtetc, stgmeds, count);
DWORD dwEffect;
DWORD dwResult = DoDragDrop(pDataObject, pDropSource, dwOKEffect, &dwEffect);
pDropSource->Release();
pDataObject->Release();
TDropResult Result=...{dwResult,dwEffect};
return Result;
}
TDropResult DoDragDrop(CLIPFORMAT ctFormat,DWORD tymed, void * hStorage,DWORD dwOKEffect)
... {
FORMATETC fmtetc = ...{
ctFormat,
0,
DVASPECT_CONTENT,
-1,
tymed
};
STGMEDIUM stgmed = ...{
tymed,
...{hStorage},
0
};
TDropResult Result= DoDragDrop(&fmtetc,&stgmed,1,dwOKEffect);
ReleaseStgMedium(&stgmed);
return Result;
}
TDropResult DoDragDrop( char * szText,DWORD dwOKEffect)
... {
return DoDragDrop(
CF_TEXT,
TYMED_HGLOBAL,
MemToHandle(szText, strlen(szText)+1), //Freed
dwOKEffect
);
}
TDropResult DoDragDropURL( char * URL,DWORD dwOKEffect)
... {
return DoDragDrop(
RegisterClipboardFormat("UniformResourceLocator"),
TYMED_HGLOBAL,
MemToHandle(URL, strlen(URL)+1), //Freed
dwOKEffect
);
}
TDropResult DoDragDrop(wchar_t * wszText,DWORD dwOKEffect)
... {
return DoDragDrop(
CF_UNICODETEXT,
TYMED_HGLOBAL,
MemToHandle (wszText, wcslen(wszText)*2+2), //Freed
dwOKEffect
);
}
TDropResult DoDragDrop(HBITMAP hBitmap,DWORD dwOKEffect)
... {
FORMATETC fmtetc = ...{
CF_BITMAP,
0,
DVASPECT_CONTENT,
-1,
TYMED_GDI
};
STGMEDIUM stgmed = ...{
TYMED_GDI,
...{hBitmap},
0
};
TDropResult Result = DoDragDrop(&fmtetc,&stgmed,1,dwOKEffect);
return Result;
}
TDropResult DoDragDrop( const THDROP_Files & files,
DWORD dwOKEffect)
... {
return DoDragDrop(
CF_HDROP,
TYMED_HGLOBAL,
files.Create_HDROP(),
dwOKEffect
);
}