Перетащите файлы из папки Zip в мое окно.
Я пытаюсь реализовать функцию, когда содержимое Zip-архива может быть перетащено из папки Zip Проводника Windows в мое окно. Я реализовал все необходимые методы 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
}
...
}
Я получаю s_false, возвращенный из QueryGetData ().
Есть ли у кого-нибудь идеи чего мне не хватает?
2 ответа:
Я не могу себе представить, что обработчик zip-файлов проводника реализует CF_HDROP, поскольку это потребует от него извлечения файлов перед началом перетаскивания. Я держу пари, что он использует CFSTR_FILEDESCRIPTOR и CFSTR_FILECONTENTS .
Кажется, я понял. Не могли бы вы просмотреть этот псевдокод, я не очень хорошо разбираюсь в 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); } } }