一、文字內容操作
複製到剪貼板
CString strText = _T("要複製的文字");
if (OpenClipboard()) {
EmptyClipboard();
HGLOBAL hGlob = GlobalAlloc(GMEM_DDESHARE, (strText.GetLength()+1)*sizeof(TCHAR));
LPTSTR pBuf = (LPTSTR)GlobalLock(hGlob);
_tcscpy(pBuf, strText);
GlobalUnlock(hGlob);
SetClipboardData(CF_UNICODETEXT, hGlob); // Unicode 版本
CloseClipboard();
}
從剪貼板取得文字
CString strResult;
if (OpenClipboard()) {
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData) {
LPTSTR pBuf = (LPTSTR)GlobalLock(hData);
strResult = pBuf;
GlobalUnlock(hData);
}
CloseClipboard();
}
二、增強圖元檔操作
複製 EMF 到剪貼板
if (OpenClipboard()) {
EmptyClipboard();
CMetaFileDC mfDC;
mfDC.CreateEnhanced(NULL, NULL, NULL, _T("EMF Description"));
// 繪圖操作...
HENHMETAFILE hEMF = mfDC.CloseEnhanced();
SetClipboardData(CF_ENHMETAFILE, hEMF);
CloseClipboard();
DeleteEnhMetaFile(hEMF); // 釋放
}
從剪貼板繪製 EMF
if (OpenClipboard()) {
HENHMETAFILE hEMF = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);
if (hEMF) {
CClientDC dc(this);
CRect rect(0,0,200,200);
dc.PlayMetaFile(hEMF, rect);
}
CloseClipboard();
}
三、位圖操作
複製位圖到剪貼板
if (OpenClipboard()) {
EmptyClipboard();
CClientDC dc(this);
CDC memDC; memDC.CreateCompatibleDC(&dc);
CBitmap bmp; bmp.CreateCompatibleBitmap(&dc, 200, 200);
CBitmap* pOld = memDC.SelectObject(&bmp);
// 繪圖...
memDC.SelectObject(pOld);
SetClipboardData(CF_BITMAP, bmp.Detach()); // 脫離 CBitmap 管理
CloseClipboard();
}
從剪貼板取得位圖並顯示
if (OpenClipboard()) {
HBITMAP hBmp = (HBITMAP)GetClipboardData(CF_BITMAP);
if (hBmp) {
CClientDC dc(this);
CDC memDC; memDC.CreateCompatibleDC(&dc);
CBitmap bmp; bmp.Attach(hBmp); // 接管控制權
BITMAP bm; bmp.GetBitmap(&bm);
CBitmap* pOld = memDC.SelectObject(&bmp);
dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight, &memDC, 0,0, SRCCOPY);
memDC.SelectObject(pOld);
bmp.Detach(); // 不刪除 GDI 物件
}
CloseClipboard();
}
四、自訂格式資料
struct MyData { long val1; int val2; };
// 註冊格式
UINT uFormat = RegisterClipboardFormat(_T("MY_CUSTOM_FORMAT"));
// 複製
if (OpenClipboard()) {
EmptyClipboard();
MyData data = {100, 200};
HGLOBAL hGlob = GlobalAlloc(GMEM_DDESHARE, sizeof(MyData));
MyData* p = (MyData*)GlobalLock(hGlob);
*p = data;
GlobalUnlock(hGlob);
SetClipboardData(uFormat, hGlob);
CloseClipboard();
}
// 讀取
MyData data;
if (OpenClipboard()) {
HANDLE hData = GetClipboardData(uFormat);
if (hData) {
MyData* p = (MyData*)GlobalLock(hData);
data = *p;
GlobalUnlock(hData);
}
CloseClipboard();
}
五、監聽剪貼板內容變更
// 初始化時
SetClipboardViewer(); // 加入觀察者鏈
// 訊息映射
ON_WM_DRAWCLIPBOARD()
ON_WM_CHANGECBCHAIN()
// 處理 WM_DRAWCLIPBOARD
void CMyDlg::OnDrawClipboard() {
CWnd::OnDrawClipboard();
// 內容已變更,更新 UI 或處理資料
DisplayClipboardText();
// 傳遞給下一個觀察者
SendMessage(WM_DRAWCLIPBOARD, 0, 0);
}
// 處理 WM_CHANGECBCHAIN
void CMyDlg::OnChangeCbChain(HWND hWndRemove, HWND hWndAfter) {
if (m_hNextViewer == hWndRemove)
m_hNextViewer = hWndAfter;
else if (m_hNextViewer)
SendMessage(m_hNextViewer, WM_CHANGECBCHAIN, (WPARAM)hWndRemove, (LPARAM)hWndAfter);
}
六、自動貼上到其他應用程式視窗
HWND hTarget = FindWindow(_T("Notepad"), NULL); // 尋找目標視窗
if (hTarget) {
// 確保剪貼板有資料
SendMessage(hTarget, WM_PASTE, 0, 0);
}
最佳實務總結
- 剪貼板操作必須成對呼叫
OpenClipboard/CloseClipboard,且盡量縮短佔用時間。
- 使用
CF_UNICODETEXT、CF_ENHMETAFILE、CF_BITMAP 標準格式確保跨應用相容。
- 自訂格式用
RegisterClipboardFormat 取得唯一識別碼。
- 監聽變更需維護觀察者鏈,正確處理
WM_CHANGECBCHAIN。
- GDI 物件(位圖、圖元檔)所有權移轉需小心:
Detach/Attach 配合 SetClipboardData/GetClipboardData。