#include <Windows.h>
#include <shlobj.h>
IDataObject *pDataObj = NULL;
OleGetClipboard(&pDataObj);
if (pDataObj)
{
FORMATETC etc;
STGMEDIUM stgMedium;
// 这两步操作才会触发文件的下载操作(不调用这两个,不会触发文件下载)
etc = setCf(RegisterClipboardFormat(CFSTR_FILENAMEMAPW));
pDataObj->GetData(&etc, &stgMedium);
etc = setCf(RegisterClipboardFormat(CFSTR_TARGETCLSID));
pDataObj->SetData(&etc, &stgMedium, FALSE);
// 第一次获取到的路径可能是虚假的(触发下载操作),第二次才是真正的
for (int i = 0; i < 2; ++i)
{
QStringList filepaths;
IEnumFORMATETC *etcs = NULL;
pDataObj->EnumFormatEtc(DATADIR_GET, &etcs);
if (etcs)
{
etcs->Reset();
while (etcs->Next(1, &etc, NULL) != S_FALSE)
{
if (etc.cfFormat == CF_HDROP)
{
if (pDataObj->GetData(&etc, &stgMedium) == S_OK)
{
TCHAR lpszFileName[MAX_PATH];
int fileCount = ::DragQueryFile((HDROP)stgMedium.hGlobal, 0xFFFFFFFF, NULL, 0);
for (int i = 0; i < fileCount; ++i)
{
int filenameLength = DragQueryFile((HDROP)stgMedium.hGlobal, i, 0, 0);
DragQueryFile((HDROP)stgMedium.hGlobal, i, lpszFileName, filenameLength + 1);
QString path = QString::fromUtf16((unsigned short *)lpszFileName);
filepaths.append(path);
ui->textEdit->append(path);
}
}
}
}
}
}
pDataObj->Release();
}
如果想要实现文件的跨进程复制粘贴(那种一开始文件根本不存在于当前操作系统的情况),在windows上是设置
CF_HDROP字段的值,参考代码:
inline bool setHdrop(STGMEDIUM *pmedium)
{
TCHAR szFiles[128] = L"C:\\Users\\xxxxxx\\Desktop\\xxxxxxx.log\0C:\\Users\\xxxxxx\\Desktop\\xxxxxx.txt";
int nSize = sizeof(DROPFILES) + sizeof(szFiles);
HANDLE hData = ::GlobalAlloc (GHND, nSize);
LPDROPFILES pDropFiles = (LPDROPFILES) ::GlobalLock(hData);
pDropFiles->pFiles = sizeof(DROPFILES);
#ifdef UNICODE
pDropFiles->fWide = TRUE;
#else
pDropFiles->fWide = FALSE;
#endif
::CopyMemory((void *)pDropFiles + sizeof(DROPFILES), szFiles, sizeof(szFiles));
::GlobalUnlock(hData);
pmedium->tymed = TYMED_HGLOBAL;
pmedium->hGlobal = hData;
pmedium->pUnkForRelease = 0;
return true;
}
OLE需要自己实现一个IDataObject接口,可以参考Qt的源码qtbase\src\plugins\platforms\windows\qwindowsole.cpp