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

C++Builder TClipboard 完全指南:剪貼板數據傳輸、格式協商、異常安全與跨進程互操作

     編輯:關於C++

C++Builder TClipboard 完全指南:剪貼板數據傳輸、格式協商、異常安全與跨進程互操作

TClipboard 封裝 Windows 剪貼板 API,提供格式協商、引用計數管理、多格式並存、組件/流/文本/圖像統一介面的高層抽象。全域單例 Clipboard(需 #include <Clipbrd.hpp>)即開箱即用。本文系統講解核心屬性、數據讀寫模式、自定義格式註冊、異常安全 RAII 封裝、跨進程大數據傳輸與常見陷阱。

類結構與單例

TObject
  └── TPersistent
        └── TClipboard  // 無公共構造函數,僅全域單例

// 訪問
#include <Clipbrd.hpp>
TClipboard* Clipboard();  // 進程單例,引用計數管理

核心屬性

屬性類型說明
AsTextAnsiString純文本讀寫(CF_TEXT/CF_UNICODETEXT 自動轉換)
FormatCountint當前剪貼板格式數量(只讀)
Formats[int Index]Word格式 ID 陣列(0 基),含系統預定義與自定義格式

核心方法

方法簽名用途
Open/Closevoid __fastcall Open/Close()鎖定/釋放剪貼板,支援嵌套計數
Clearvoid __fastcall Clear()清空剪貼板(寫入前自動調用)
HasFormatbool __fastcall HasFormat(Word fmt)檢查指定格式是否可用
GetAsHandleint __fastcall GetAsHandle(Word fmt)返回格式數據的 HGLOBAL(需 Open 狀態有效)
SetAsHandlevoid __fastcall SetAsHandle(Word fmt, int h)以 HGLOBAL 寫入數據(所有權轉移給剪貼板)
GetTextBuf/SetTextBufint GetTextBuf(char*,int) / void SetTextBuf(char*)緩衝區文本讀寫(低層)
Assignvirtual void Assign(TPersistent* src)通用讀寫:
Clipboard->Assign(bitmap) 寫入
bitmap->Assign(Clipboard) 讀出
GetComponent/SetComponentTComponent* GetComponent(Owner,Parent) / void SetComponent(Comp)組件樹序列化(需 RegisterClasses)

標準格式常數

CF_TEXT            = 1;      // ANSI 文本
CF_BITMAP          = 2;      // HBITMAP
CF_METAFILEPICT    = 3;      // HANDLE to METAFILEPICT
CF_SYLK            = 4;      // Symbolic Link
CF_DIF             = 5;      // Data Interchange Format
CF_TIFF            = 6;      // TIFF 圖像
CF_OEMTEXT         = 7;      // OEM 文本
CF_DIB             = 8;      // 設備無關位圖
CF_PALETTE         = 9;      // 調色盤
CF_PENDATA         = 10;     // 筆跡數據
CF_RIFF            = 11;     // RIFF 音頻
CF_WAVE            = 12;     // WAVE 音頻
CF_UNICODETEXT     = 13;     // Unicode 文本 (WinNT+)
CF_ENHMETAFILE     = 14;     // 增強圖元檔
CF_HDROP           = 15;     // 檔案拖放列表
CF_LOCALE          = 16;     // 語言環境
CF_MAX             = 17;     // 系統保留上限
// 自定義格式:RegisterClipboardFormat("MyApp/CustomData") → 返回 > CF_MAX 的 ID

異常安全 RAII 封裝

class ScopedClipboard {
    bool opened;
public:
    ScopedClipboard() : opened(false) {
        Clipboard()->Open();
        opened = true;
    }
    ~ScopedClipboard() {
        if (opened) Clipboard()->Close();
    }
    // 禁止拷貝
    ScopedClipboard(const ScopedClipboard&) = delete;
    ScopedClipboard& operator=(const ScopedClipboard&) = delete;
};

// 使用範例:寫入多格式
{
    ScopedClipboard cb;
    Clipboard()->Clear();
    Clipboard()->AsText = "Plain text";
    Clipboard()->Assign(myBitmap);  // 同時寫入 CF_BITMAP + CF_DIB
    // 離開作用域自動 Close
}

自定義格式註冊與大數據傳輸

// 註冊(進程全域唯一)
static UINT MY_FORMAT = 0;
if (MY_FORMAT == 0)
    MY_FORMAT = RegisterClipboardFormat(L"MyApp/ObjectData_v1");

// 寫入大數據(> 幾 MB 建議用 HGLOBAL + 共享內存)
{
    ScopedClipboard cb;
    Clipboard()->Clear();
    HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, dataSize);
    void* ptr = GlobalLock(hMem);
    memcpy(ptr, data, dataSize);
    GlobalUnlock(hMem);
    Clipboard()->SetAsHandle(MY_FORMAT, (int)hMem);  // 所有權轉移
    // 若需同時提供文本預覽
    Clipboard()->AsText = "[MyApp Object Data]";
}

// 讀取
{
    ScopedClipboard cb;
    if (Clipboard()->HasFormat(MY_FORMAT)) {
        HGLOBAL hMem = (HGLOBAL)Clipboard()->GetAsHandle(MY_FORMAT);
        void* ptr = GlobalLock(hMem);
        // 處理數據...
        GlobalUnlock(hMem);
        // 注意:不要 GlobalFree,剪貼板關閉時系統自動釋放
    }
}

跨進程大數據最佳實踐

  1. 共享內存 + 格式協商:寫入方 GlobalAlloc(GMEM_DDESHARE),讀取方 GetAsHandle 獲取同一 HGLOBAL,零拷貝。
  2. 檔案落地備援:超大數據(> 100MB)寫入臨時檔,剪貼板僅放 CF_HDROP 或自定義路徑字串。
  3. 版本化格式名:MyApp/Type_v2,讀取端按版本解析,實現向前相容。
  4. 異步通知:AddClipboardFormatListener 監聽變更,避免輪詢。

常見陷阱

現象原因對策
Open 失敗/超時其他進程長期持有剪貼板重試機制;UI 執行緒勿長時間 Open
GetAsHandle 返回句柄無效在 Close 後使用句柄必須在 ScopedClipboard 作用域內使用
SetAsHandle 後數據損壞寫入方過早 GlobalFree所有權轉移給剪貼板,切勿自行釋放
組件讀取 EClassNotFound未 RegisterClasses啟動時 RegisterClasses([__classid(TMyComp)])
Unicode 文本亂碼舊版 ANSI 應用讀 CF_UNICODETEXT優先用 AsText(內部自動轉碼)

TClipboard 以 Assign 多態介面統一了「文本/圖像/組件/自定義二進制」的讀寫模式,配合 Open/Close 引用計數鎖定與 HGLOBAL 共享內存,構建了高效、安全的跨進程數據交換通道。

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