#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