Daniel
Daniel

Reputation: 411

Accept CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR int DoDrop in MFC Application

I've got a MFC application (VS2010) containing a CScrollView which uses a COleDropTarget to register itself as a drop target.

This works, and I can check the type of the dropped data in the OnDrop method:

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

This works nicely. Now, I would like to drop "virtual files" into this CScrollView (from another application) and I don't know how. With virtual files I mean using the CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR clipbord format and provide the actual stream of data when needed.

Providing the clipboard with virtual files is easy enough (there are tutorials out there, e.g. here or there), but on the receiving end (my DoDrop method) I don't know how to retrieve the data.

The application providing the virtual files seems to work (meaning that I can drop them to the desktop).

So, can somebody tell me how I can get the data from the virtual files in my MFC DoDrop method?

Edit: Ok, following code works for me:

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

So, pszString really points to the data of the transferred file, mission accomplished.

Upvotes: 1

Views: 2430

Answers (1)

snowdude
snowdude

Reputation: 3874

To receive the data you should just be able to call pDataObject->GetData() with the IDs for CFSTR_FILEDESCRIPTOR and CFSTR_FILECONTENTS (you need to call RegisterClipboardFormat() to get the IDs).

That will fill out your STGMEDIUM structure with the values required to get the virtual data, which might be provided as an IStream but could just as easily be provided as an HGLOBAL etc.

After you have finished with the data, call ReleaseStgMedium() function to release the STGMEDIUM data.

This is documented on MSDN:

Handling Shell Data Transfer Scenarios

Using the CFSTR_FILECONTENTS Format to Extract Data from a File

Upvotes: 2

Related Questions