Windows 剪貼板操作需遵循開啟 → 清空/讀取 → 分配全域記憶體 → 鎖定/解鎖 → 設定/取得資料 → 關閉的嚴格流程。以下提供 ANSI 文字(CF_TEXT)讀寫的最小可行程式碼,適用於 MFC/ATL/WIN32 專案。
if (OpenClipboard()) {
CString str = _T("879789789"); // 要寫入的文字
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, (str.GetLength() + 1) * sizeof(TCHAR));
if (hGlobal) {
LPTSTR pBuf = static_cast<LPTSTR>(GlobalLock(hGlobal));
if (pBuf) {
_tcscpy_s(pBuf, str.GetLength() + 1, str);
GlobalUnlock(hGlobal);
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlobal); // 所有權轉移給剪貼板
}
}
CloseClipboard();
}
關鍵點:
GMEM_MOVEABLE:允許記憶體移動,剪貼板需求。GlobalLock/Unlock:取得/釋放線性位址存取。EmptyClipboard():清空舊資料並釋放先前的全域記憶體控制代碼。SetClipboardData 成功後,**不可再呼叫 GlobalFree**;失敗時需自行釋放。if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard()) {
HGLOBAL hGlobal = GetClipboardData(CF_TEXT);
if (hGlobal) {
LPTSTR pBuf = static_cast<LPTSTR>(GlobalLock(hGlobal));
if (pBuf) {
CString text(pBuf); // 複製內容
AfxMessageBox(text); // 示範用途
GlobalUnlock(hGlobal);
}
}
CloseClipboard();
}
注意:
GetClipboardData 返回的控制代碼**所有權屬於剪貼板**,不可 GlobalFree。CF_TEXT(ANSI);Unicode 專案應改用 CF_UNICODETEXT 並對應 wchar_t。| 現象 | 原因 | 修正 |
|---|---|---|
OpenClipboard 失敗 | 其他視窗持有剪貼板、非 UI 執行緒 | 重試機制、確保在主執行緒呼叫 |
| 讀取亂碼 | Unicode 專案用 CF_TEXT | 改用 CF_UNICODETEXT + wchar_t |
| 寫入後立即讀取為空 | 未 EmptyClipboard 或 SetClipboardData 失敗 | 檢查返回值、GetLastError |
| 記憶體洩漏 | SetClipboardData 失敗未釋放 hGlobal | 失敗路徑呼叫 GlobalFree |
// 寫入
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, (str.GetLength() + 1) * sizeof(wchar_t));
wchar_t* pBuf = static_cast<wchar_t*>(GlobalLock(hGlobal));
wcscpy_s(pBuf, str.GetLength() + 1, str);
SetClipboardData(CF_UNICODETEXT, hGlobal);
// 讀取
if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
HGLOBAL hGlobal = GetClipboardData(CF_UNICODETEXT);
wchar_t* pBuf = static_cast<wchar_t*>(GlobalLock(hGlobal));
CString text(pBuf);
}