进程通信专题

3、剪切板

1、课程目标

  1. 理解剪切板的工作原理
  2. 掌握剪切板数据的读写
  3. 学会剪切板监控技术
  4. 理解剪切板的安全风险

2、名词解释

术语 英文 说明
剪切板 Clipboard 系统级的数据共享机制
格式 Format 剪切板数据的类型
剪切板链 Clipboard Chain 剪切板变化的监控链

3、代码实现

3.1、示例1:写入剪切板

#include <windows.h>
#include <stdio.h>

void SetClipboardText(const char* text) {
    if (!OpenClipboard(NULL)) return;
    
    EmptyClipboard();
    
    size_t len = strlen(text) + 1;
    HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
    
    if (hMem) {
        char* pMem = (char*)GlobalLock(hMem);
        memcpy(pMem, text, len);
        GlobalUnlock(hMem);
        
        SetClipboardData(CF_TEXT, hMem);
    }
    
    CloseClipboard();
}

3.2、示例2:读取剪切板

#include <windows.h>
#include <stdio.h>

char* GetClipboardText() {
    if (!OpenClipboard(NULL)) return NULL;
    
    HANDLE hData = GetClipboardData(CF_TEXT);
    if (!hData) {
        CloseClipboard();
        return NULL;
    }
    
    char* pText = (char*)GlobalLock(hData);
    char* result = _strdup(pText);
    GlobalUnlock(hData);
    
    CloseClipboard();
    return result;
}

3.3、示例3:剪切板监控

#include <windows.h>
#include <stdio.h>

HWND g_hNextViewer = NULL;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CREATE:
        // 加入剪切板查看器链
        g_hNextViewer = SetClipboardViewer(hWnd);
        return 0;
        
    case WM_DRAWCLIPBOARD:
        // 剪切板内容变化
        printf("Clipboard changed!\n");
        
        if (IsClipboardFormatAvailable(CF_TEXT)) {
            char* text = GetClipboardText();
            if (text) {
                printf("Content: %s\n", text);
                free(text);
            }
        }
        
        // 传递给下一个查看器
        if (g_hNextViewer)
            SendMessage(g_hNextViewer, msg, wParam, lParam);
        return 0;
        
    case WM_CHANGECBCHAIN:
        // 链变化
        if ((HWND)wParam == g_hNextViewer)
            g_hNextViewer = (HWND)lParam;
        else if (g_hNextViewer)
            SendMessage(g_hNextViewer, msg, wParam, lParam);
        return 0;
        
    case WM_DESTROY:
        ChangeClipboardChain(hWnd, g_hNextViewer);
        PostQuitMessage(0);
        return 0;
    }
    
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

3.4、示例4:新式剪切板监听

#include <windows.h>
#include <stdio.h>

// Windows Vista+ 使用 AddClipboardFormatListener
LRESULT CALLBACK ModernWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CREATE:
        AddClipboardFormatListener(hWnd);
        return 0;
        
    case WM_CLIPBOARDUPDATE:
        printf("Clipboard updated!\n");
        return 0;
        
    case WM_DESTROY:
        RemoveClipboardFormatListener(hWnd);
        PostQuitMessage(0);
        return 0;
    }
    
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

4、课后作业

  1. 基础练习:实现剪切板文本的读写
  2. 格式支持:支持读写图片等其他格式
  3. 剪切板监控:实现剪切板历史记录工具
  4. 安全分析:分析剪切板窃取技术