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

VC++ 剪貼板操作完全攻略:文字、圖元檔、位圖、自訂格式與變更監聽

     編輯:VC 教學

一、文字內容操作

複製到剪貼板

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。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved