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

Win32 開發入門(21):剪貼板操作 - 文字複製貼上與 GlobalAlloc 記憶體管理

     編輯:關於C++

Win32 剪貼板操作遵循「開啟→清空/讀取→關閉」流程,資料透過 HGLOBAL 可移動記憶體區塊傳遞。本文詳細實作 Unicode 文字複製與貼上,解析記憶體鎖定/解鎖機制。

核心流程


// 複製到剪貼板
OpenClipboard(hWnd);
EmptyClipboard();
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
LPVOID pData = GlobalLock(hGlobal);
memcpy(pData, source, size);
GlobalUnlock(hGlobal);
SetClipboardData(CF_UNICODETEXT, hGlobal);  // 所有權轉移給系統
CloseClipboard();

// 從剪貼板貼上
OpenClipboard(hWnd);
if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
    HGLOBAL hGlobal = GetClipboardData(CF_UNICODETEXT);
    LPVOID pData = GlobalLock(hGlobal);
    // 使用 pData...
    GlobalUnlock(hGlobal);
}
CloseClipboard();

關鍵細節解析

1. GMEM_MOVEABLE 必要性

  • 系統需在剪貼板內部重新定位記憶體區塊(碎片整理、序列化)。
  • GlobalLock 返回當前實際位址,使用前必須鎖定,用畢解鎖。
  • 若用 GMEM_FIXED,GlobalLock 直接返回固定位址,但系統無法移動,SetClipboardData 會失敗。

2. 所有權轉移

  • SetClipboardData 成功後,**記憶體所有權歸系統**,呼叫端不得釋放或寫入。
  • CloseClipboard 前必須 GlobalUnlock,否則系統無法存取。
  • 系統會在適當時機(如下一次 EmptyClipboard、進程結束)釋放記憶體。

3. 格式選擇

格式常數資料類型編碼優先序
CF_UNICODETEXTUnicode 文字UTF-16LE最高(現代首選)
CF_TEXTANSI 文字系統代碼頁相容舊版
CF_HTMLHTML 片段UTF-8/UTF-16富文本
CF_RTFRTF 文件ASCII富文本
CF_HDROP檔案路徑清單-拖放檔案

完整對話方塊範例


case IDC_BTN_COPY: {
    HWND hEditSrc = GetDlgItem(hDlg, IDC_EDIT_SRC);
    int len = GetWindowTextLength(hEditSrc);
    std::wstring text(len + 1, L'\0');
    GetWindowText(hEditSrc, &text[0], len + 1);

    OpenClipboard(hDlg);
    EmptyClipboard();
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, (text.size()) * sizeof(wchar_t));
    wchar_t* pDst = (wchar_t*)GlobalLock(hGlobal);
    wcscpy(pDst, text.c_str());
    GlobalUnlock(hGlobal);
    SetClipboardData(CF_UNICODETEXT, hGlobal);
    CloseClipboard();
    break;
}

case IDC_BTN_PASTE: {
    HWND hEditDst = GetDlgItem(hDlg, IDC_EDIT_DST);
    OpenClipboard(hDlg);
    if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
        HGLOBAL hGlobal = GetClipboardData(CF_UNICODETEXT);
        wchar_t* pSrc = (wchar_t*)GlobalLock(hGlobal);
        if (pSrc) SetWindowText(hEditDst, pSrc);
        GlobalUnlock(hGlobal);
    }
    CloseClipboard();
    break;
}

執行結果

現代替代方案

  • C++/WinRT:Windows::ApplicationModel::DataTransfer::Clipboard 非同步、支援多格式。
  • .NET:System.Windows.Forms.Clipboard / System.Windows.Clipboard 封裝完整。
  • OLE 剪貼板:OleSetClipboard/OleGetClipboard 支援 COM 物件、資料物件、延遲渲染。

常見錯誤避坑

  1. 忘記 GlobalUnlock → 系統無法讀取、資源洩漏。
  2. SetClipboardData 後又 GlobalFree → 雙重釋放崩潰。
  3. 未檢查 IsClipboardFormatAvailable 直接 GetClipboardData → 返回 NULL 導致崩潰。
  4. 混用 CF_TEXT (ANSI) 與 Unicode 字串 → 亂碼。
  5. 剪貼板被其他進程鎖定時 OpenClipboard 失敗 → 需重試機制。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved