VMware windows系統上文件拷貝原理(linux應該類似,拖拽應該也類似)

    #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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章