首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ Builder 將檔案路徑放入剪貼板實現「複製檔案」效果

     編輯:關於C++

在 Windows 程式設計中,將檔案「複製到剪貼板」並非複製檔案內容,而是將檔案路徑清單以 CF_HDROP 格式 放入剪貼板。這樣使用者在總管或其他支援的應用程式中按「貼上」(Ctrl+V) 時,系統會自動執行實際的檔案複製操作。本文提供 C++ Builder 完整實作程式碼,並解析 CF_HDROP 記憶體結構原理。

核心原理:CF_HDROP 格式

CF_HDROP 是剪貼板標準格式,用於傳遞檔案路徑清單。其記憶體區塊結構為:

struct DROPFILES {
    DWORD pFiles;     // 檔案名列表相對結構體起始位置的偏移量 (通常為 20)
    POINT pt;         // 點擊位置 (通常填 0)
    BOOL  fNC;        // 非用戶區域旗標
    BOOL  fWide;      // 是否為 Unicode (TRUE=雙位元組, FALSE=ANSI)
};
// 緊接著是以雙重 NULL 結尾的檔案路徑字串陣列 (ANSI 或 Unicode)

完整實作程式碼 (C++ Builder / VCL)

bool CopyToClipboard(const AnsiString& file) {
    if (file.IsEmpty()) return false;

    // 1. 計算所需記憶體大小
    // DROPFILES 結構 20 位元組 + 檔案路徑長度 + 1 (單一 NULL) + 1 (雙重 NULL 結尾)
    int nLen = sizeof(DROPFILES) + file.Length() + 1 + 1; 

    // 2. 配置可移動、共享、零初始化的全域記憶體
    HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, nLen);
    if (!hMem) return false;

    // 3. 鎖定記憶體並填充結構
    char* pData = (char*)GlobalLock(hMem);
    if (!pData) { GlobalFree(hMem); return false; }

    DROPFILES* pDrop = (DROPFILES*)pData;
    pDrop->pFiles = sizeof(DROPFILES); // 偏移量指向結構體之後
    pDrop->pt.x = 0;
    pDrop->pt.y = 0;
    pDrop->fNC = FALSE;
    pDrop->fWide = FALSE; // 這裡使用 ANSI 版本

    // 複製檔案路徑 (包含結尾 NULL)
    strcpy(pData + sizeof(DROPFILES), file.c_str());
    // 注意:這裡只有一個檔案,所以路徑後已經是雙重 NULL (因 GMEM_ZEROINIT)

    GlobalUnlock(hMem);

    // 4. 打開剪貼板、清空、設定資料、關閉
    bool bSuccess = false;
    if (OpenClipboard(NULL)) {
        EmptyClipboard();
        if (SetClipboardData(CF_HDROP, hMem)) {
            hMem = NULL; // 所有權轉移給剪貼板,不再由我們釋放
            bSuccess = true;
        }
        CloseClipboard();
    }

    // 5. 若設定失敗,釋放記憶體
    if (hMem) GlobalFree(hMem);
    return bSuccess;
}

// 使用範例
void __fastcall TForm1::Button1Click(TObject *Sender) {
    if (CopyToClipboard("C:\\scandisk.log")) {
        ShowMessage("檔案路徑已複製到剪貼板,請在總管中按 Ctrl+V 貼上。");
    } else {
        ShowMessage("複製失敗!");
    }
}

關鍵細節解析

  1. GlobalAlloc 旗標:GMEM_MOVEABLE 允許記憶體移動 (剪貼板要求);GMEM_DDESHARE 允許跨進程共享 (DDE/剪貼板核心需求);GMEM_ZEROINIT 自動清零,確保字串以雙重 NULL 結尾。
  2. pFiles 偏移量:必須精確指向檔案名列表起始位置。對於 DROPFILES 結構 (20 位元組),值固定為 20。
  3. Unicode 支援:現代應用建議設 fWide = TRUE,並使用 wchar_t 複製路徑 (每個路徑以 L'\0' 結尾,最終雙重 L'\0\0')。Windows 總管完美支援 Unicode 路徑。
  4. 多檔案:將多個路徑依序拼接,每個以 \0 結尾,最後再加一個 \0。調整 nLen 計算即可。
  5. 所有權轉移:SetClipboardData 成功後,記憶體區塊所有權歸剪貼板,不可 呼叫 GlobalFree。失敗時則由呼叫者負責釋放。

進階應用:模擬「剪下」效果

若要實現「剪下」 (移動) 語意,需在放下時由目標應用處理。剪貼板資料本身無法區分「複製」與「剪下」。但可結合 CFSTR_PREFERREDDROPEFFECT 格式,在剪貼板同時放入 DROPEFFECT_MOVE (值為 2) 提示目標應用執行移動操作。這需要額外註冊格式並設定資料。

總結

透過構造標準 CF_HDROP 記憶體區塊,C++ Builder 應用程式即可輕松實現「複製檔案路徑到剪貼板」功能,完美融入 Windows Shell 操作流程。掌握其記憶體結構與旗標含義,是進行剪貼板進階開發的基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved