Reputation: 17313
I'm trying to implement a feature when contents of a Zip archive could be dragged-and-dropped from a Windows Explorer's Zip folder into my window. I implemented all necessary methods of IDropTarget and everything works fine when I drag-n-drop regular files from the Windows Explorer.
The issue happens in the following method when I attempt to drag in a file from a Zip folder:
HRESULT DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
static FORMATETC fmtetc_file = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hr = pDataObject->QueryGetData(&fmtetc_file);
if(hr == S_OK)
{
//Format supported
}
...
}
I get S_FALSE returned from QueryGetData().
Does anyone have any idea what am I missing?
Upvotes: 5
Views: 3238
Reputation: 17313
I think I got it. Could you review this pseudo-code, I'm not really good at COM:
Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
FORMATETC fmtetc_file_desc = {RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if(pDataObject->QueryGetData(&fmtetc_file_desc) == S_OK)
{
STGMEDIUM stgmed;
if(pDataObject->GetData(&fmtetc_file_desc, &stgmed) == S_OK)
{
if(stgmed.tymed & TYMED_HGLOBAL)
{
FILEGROUPDESCRIPTOR* pFGD = (FILEGROUPDESCRIPTOR*)::GlobalLock(stgmed.hGlobal);
for(int f = 0; f < pFGD->cItems; f++)
{
STGMEDIUM stgmedFile = {0};
//You may want to move out the RegisterClipboardFormat() API into some global variable
FORMATETC fmtetc_file_desc = {RegisterClipboardFormat(CFSTR_FILECONTENTS), 0, DVASPECT_CONTENT, f, TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ISTORAGE};
if(pDataObject->GetData(&fmtetc_file_desc, &stgmedFile) == S_OK)
{
BOOL bReadOK = FALSE;
if(!bReadOK && (stgmedFile & TYMED_ISTREAM))
{
//Now read data from a stream & process it
//(If need be, it can be saved in a file)
IStream *pstm = pStgmed->pstm;
//Size of data in a steam & archived file name
STATSTG stg = {0};
SUCCEEDED(pstm->Stat(&stg, STATFLAG_DEFAULT) == S_OK);
//Then to read data from a stream
//Call repeatedly until all or required data is read)
SUCCEEDED(pstm->Read(pStorage, ncbBytesRead, &ucbBytesRead));
//If read and processed successfully
bReadOK = TRUE;
//Release mem
CoTaskMemFree(stg.pwcsName);
}
//Probably need to implement these as well?
if(!bReadOK && (stgmedFile & TYMED_ISTORAGE))
{
}
if(!bReadOK && (stgmedFile & TYMED_HGLOBAL))
{
}
ReleaseStgMedium(&stgmedFile);;
}
}
::GlobalUnlock(stgmed.hGlobal);
}
ReleaseStgMedium(&stgmed);
}
}
}
Upvotes: 1
Reputation: 11431
I can't imagine Explorer's zip file handler implements CF_HDROP as that would require it to extract the files before initiating the drag. I am betting it uses CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS.
Upvotes: 3