我正在尝试实现一项功能,可以将Zip存档的内容从Windows资源管理器的Zip文件夹拖放到我的窗口中。我实现了IDropTarget的所有必要方法,当我从Windows资源管理器中拖放常规文件时,一切正常。
当我尝试从Zip文件夹中拖入文件时,问题出现在以下方法中:
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
}
...
}
我从QueryGetData()返回S_FALSE。
有没有人知道我错过了什么?
答案 0 :(得分:3)
我无法想象Explorer的zip文件处理程序实现CF_HDROP,因为它需要它在启动拖动之前提取文件。我打赌它使用CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS。
答案 1 :(得分:1)
我想我明白了。你能不能看一下这个伪代码,我不是很擅长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);
}
}
}