2011-05-13 74 views
3

我试图在Zip存档的内容可以从Windows资源管理器的Zip文件夹拖放到我的窗口时实现该功能。我实现了IDropTarget的所有必要的方法,并且当我从Windows资源管理器拖放常规文件时,一切正常。将Zip文件夹中的文件拖放到我的窗口

问题发生在下面的方法,当我试图从一个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()返回。

有没有人有任何想法我错过了什么?

回答

3

我无法想象Explorer的zip文件处理程序实现了CF_HDROP,因为它需要它在启动拖动之前提取文件。我打赌它使用CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS

+0

非常感谢,使用下面的代码线的dragenter()工作: 'FORMATETC fmtetc_file = {的RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR) ,0,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; 如果(pDataObject->的QueryGetData(fmtetc_file)== S_OK){ } ' 但现在我有点进退两难是如何获得的通道连接到一个zip压缩文件(其文件被拖进我的窗口)或临时路径到文件本身,如果壳牌恰好为我解压缩? – ahmd0 2011-05-13 23:58:46

+0

拖放的重点是抽象出zip文件等实现细节;如果你能弄明白的话,我会有点惊讶。 – Luke 2011-05-14 02:33:23

+0

对不起,卢克,但我仍然无法弄清楚。那么我该如何获得拖到我窗口中的文件呢? – ahmd0 2011-05-14 08:29:16

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); 

     } 
    } 

} 
+0

对我来说没关系。在我的测试中,我只见过IStream;不确定是否实际使用了其他存储方法。此外,Stat()返回E_NOTIMPL,所以你可能只需要Read(),直到cbBytesRead == 0. – Luke 2011-05-14 22:04:06

+0

嗯,真的。你在测试什么版本的Windows? – ahmd0 2011-05-14 22:06:53

+0

我正在测试XP SP3 – Luke 2011-05-15 00:59:22

相关问题