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

C++ Builder 實作:列舉剪貼板所有可用資料格式

     編輯:關於C++

前言:為什麼需要檢查剪貼板格式?

剪貼板不只是純文字或圖片的暫存區。現代應用程式 (Word、Excel、瀏覽器、設計軟體) 會將資料以多種格式同時放入剪貼板:標準格式 (CF_TEXT, CF_BITMAP, CF_HDROP 等) 與自訂格式 (如 Excel 的 XML Spreadsheet、RTF 的 Rich Text Format)。開發「貼上」功能時,必須先偵測剪貼板內容,才能決定啟用哪些貼上選項、或進行格式轉換。

核心 API:EnumClipboardFormats

Windows 提供 EnumClipboardFormats 迭代剪貼板所有格式:

UINT EnumClipboardFormats(UINT format);
  • 首次呼叫傳入 0,取得第一個格式 ID。
  • 後續呼叫傳入上一個取得的 ID,取得下一個。
  • 回傳 0 表示列舉結束或錯誤 (需配合 GetLastError 判斷)。

完整實作範例 (C++ Builder / VCL)

標準格式 ID 對照表

系統預定義格式值範圍通常在 1..17 (視 OS 版本),常見者:

常數值說明
CF_TEXT1ANSI 文字
CF_BITMAP2位圖控制代碼
CF_METAFILEPICT3中繼檔圖片
CF_DIB8裝置無關位圖 (DIB)
CF_UNICODETEXT13Unicode 文字 (WinNT+)
CF_HDROP15拖放檔案清單
CF_LOCALE16地區設定識別碼

取得自訂格式名稱:GetClipboardFormatName

格式 ID > CF_MAX (通常 17) 即為應用程式向系統註冊的自訂格式 (RegisterClipboardFormat)。需呼叫 GetClipboardFormatName 取得其字串名稱。

按鈕點擊事件完整程式碼

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  ListBox1->Clear();
  if (!OpenClipboard(Handle)) return; // 開啟剪貼板,傳入視窗句柄建立擁有權

  try
  {
    UINT fmt = EnumClipboardFormats(0);
    while (fmt != 0)
    {
      AnsiString name;
      if (fmt < 18) // 標準格式範圍 (視實際 CF_MAX 調整)
        name = StandardFormatName(fmt); // 查表函式
      else
        name = GetCustomFormatName(fmt); // 呼叫 GetClipboardFormatName

      ListBox1->Items->Add(Format("%u: %s", ARRAYOFCONST((fmt, name))));
      fmt = EnumClipboardFormats(fmt); // 取下一個
    }
  }
  __finally
  {
    CloseClipboard(); // 必須在 finally 區塊釋放,避免例外導致剪貼板鎖死
  }
}

// 查表標準格式名稱
AnsiString StandardFormatName(UINT fmt) {
  static const char* names[] = {
    "CF_TEXT", "CF_BITMAP", "CF_METAFILEPICT", "CF_SYLK", "CF_DIF",
    "CF_TIFF", "CF_OEMTEXT", "CF_DIB", "CF_PALETTE", "CF_PENDATA",
    "CF_RIFF", "CF_WAVE", "CF_UNICODETEXT", "CF_ENHMETAFILE",
    "CF_HDROP", "CF_LOCALE", "CF_MAX"
  };
  if (fmt >= 1 && fmt <= 17) return names[fmt - 1];
  return "UNKNOWN_STD";
}

// 取得自訂格式名稱
AnsiString GetCustomFormatName(UINT fmt) {
  char buf[256];
  if (GetClipboardFormatName(fmt, buf, sizeof(buf)))
    return buf;
  return "-----None------";
}

執行效果與測試建議

  1. 編譯執行程式,點擊按鈕,ListBox 顯示當前剪貼板所有格式 ID 與名稱。
  2. 先在 Word 複製一段富文本,再點擊按鈕,觀察是否出現 Rich Text Format、HTML Format 等自訂格式。
  3. 在總管複製檔案,觀察 CF_HDROP (15) 及 Shell IDList Array 等格式。
  4. 在 Excel 複製儲存格,觀察 XML Spreadsheet、CSV 等專屬格式。

常見坑點與最佳實務

  • 剪貼板鎖定: OpenClipboard 失敗時 (回傳 FALSE) 通常是其他程式正在存取,應重試或放棄,切勿強制等待導致 UI 凍結。
  • 例外安全: 一定要用 try/__finally 確保 CloseClipboard 被呼叫,否則系統剪貼板會被永久鎖定,需重啟 explorer.exe 或登出才能恢復。
  • 格式 ID 不固定: 自訂格式 ID 每次開機/登入後由系統動態分配,**不可硬編碼 ID**,必須每次透過 RegisterClipboardFormat 或列舉時取得名稱比對。
  • 大資料量: 列舉格式本身極快,但若後續呼叫 GetClipboardData 取得大量資料 (如高解析度圖片),需考慮非同步處理或進度提示。

延伸應用:智慧型貼上選單

結合本技術,可打造類似 Office 的「選擇性貼上」對話框:

if (HasFormat(CF_HDROP))       EnableMenuItem(pasteFiles);
if (HasFormat(CF_UNICODETEXT)) EnableMenuItem(pasteText);
if (HasFormat("HTML Format"))  EnableMenuItem(pasteHtml);
if (HasFormat("Rich Text Format")) EnableMenuItem(pasteRtf);
// ...

甚至可依優先順序自動選擇最佳格式貼上 (如優先 HTML > RTF > Unicode Text > ANSI Text)。

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