【问题标题】:Accept CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR int DoDrop in MFC Application在 MFC 应用程序中接受 CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR int DoDrop
【发布时间】:2014-08-19 19:36:08
【问题描述】:

我有一个 MFC 应用程序 (VS2010),其中包含一个 CScrollView,它使用 COleDropTarget 将自己注册为放置目标。

这行得通,我可以在 OnDrop 方法中检查拖放数据的类型:

BOOL CMyClass::DoDrop(COleDataObject *pDataObject,  DROPEFFECT dropEffect, CPoint point)
{
    if (pDataObject->IsDataAvailable(CF_DIB))
    {
        // Do something with DIB
    }
    else if (pDataObject->IsDataAvailable(CF_ENHMETAFILE) || pDataObject->IsDataAvailable(CF_METAFILEPICT))
    {
       // Do something with Metafiles
    }
    else if (pDataObject->IsDataAvailable(CF_HDROP))
    {
        // Do something with files
    }
    return FALSE;
}

这很好用。现在,我想将“虚拟文件”放入这个 CScrollView(来自另一个应用程序),但我不知道如何。对于虚拟文件,我的意思是使用 CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR clipbord 格式并在需要时提供实际的数据流。

为剪贴板提供虚拟文件很容易(那里有教程,例如herethere), 但在接收端(我的 DoDrop 方法)我不知道如何检索数据。

提供虚拟文件的应用程序似乎可以工作(这意味着我可以将它们放到桌面上)。

那么,谁能告诉我如何在我的 MFC DoDrop 方法中从虚拟文件中获取数据?

编辑:好的,以下代码对我有用:

FORMATETC fetc;
// m_cfstrFileContents is CLIPFORMAT retrieved with RegisterClipboardFormat(_T("FileContents"))
fetc.cfFormat=m_cfstrFileContents; 
fetc.dwAspect=DVASPECT_CONTENT;
fetc.lindex=0;
fetc.ptd=NULL;
fetc.tymed=TYMED_ISTREAM;

// Get file contents.
STGMEDIUM stgm;
if (!pDataObject->GetData(m_cfstrFileContents, &stgm, &fetc))
{
    // We don't have virtual file contents in the clipbord.
    return FALSE;
}
COleStreamFile file(stgm.pstm);
DWORD dwLength=file.GetLength();
LPSTR pszString=(LPSTR)_alloca(dwLength+1);
file.Seek(0, CFile::begin);
file.Read(pszString, dwLength);
pszString[dwLength]='\0';
// Either close the stream or release the storage medium, not both!
//file.Close(); 

ReleaseStgMedium(&stgm);

所以,pszString 真正指向了传输文件的数据,任务完成。

【问题讨论】:

    标签: c++ mfc drag-and-drop


    【解决方案1】:

    要接收数据,您应该能够使用CFSTR_FILEDESCRIPTORCFSTR_FILECONTENTS 的ID 调用pDataObject->GetData()(您需要调用RegisterClipboardFormat() 来获取ID)。

    这将使用获取虚拟数据所需的值填充您的 STGMEDIUM 结构,这些值可以作为 IStream 提供,但也可以像 HGLOBAL 等一样轻松提供。

    处理完数据后,调用ReleaseStgMedium()函数释放STGMEDIUM数据。

    这在 MSDN 上有记录:

    Handling Shell Data Transfer Scenarios

    Using the CFSTR_FILECONTENTS Format to Extract Data from a File

    【讨论】:

    • 感谢@snowdude,我几乎可以正常工作了,只有在发布 STGMEDIUM 时出现无法解释的异常,你明白我为什么会得到它吗? (如果没有,我可以提出另一个问题,专门询问这个问题的解决方案)。
    • 找到了解决办法,不能先关闭COleStream再释放存储介质,一个就够了。
    • @Daniel 是的,如果您查看 COleStreamFile::Close() 的代码,它会释放 IStream 指针。调用 ReleaseStgMedium 应该是首选方式。
    • @remy-lebeau 感谢您整理我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    • 2023-03-12
    • 2018-05-19
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    相关资源
    最近更新 更多