我用全局钩子写dll。任务之一是查看剪贴板并在有人执行复制操作时从剪贴板中删除所有数据。这是我的窗口回调函数:

string test("my data");

LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
        case WM_CREATE:
            nextClipboardViewer = SetClipboardViewer(windowHandler);
            MessageBeep(MB_ICONINFORMATION);
            break;
        case WM_CHANGECBCHAIN:
            if((HWND) wParam == nextClipboardViewer)
                nextClipboardViewer == (HWND) lParam;
            else if(nextClipboardViewer != NULL)
                SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case WM_DRAWCLIPBOARD:
            if(OpenClipboard(windowHandler)) {
                EmptyClipboard();
                HGLOBAL hClipboardData;
                hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1);
                char * pchData;
                pchData = (char*)GlobalLock(hClipboardData);
                memcpy(pchData, test.c_str(), test.size() + 1);
                GlobalUnlock(hClipboardData);
                SetClipboardData(CF_TEXT, hClipboardData);
                CloseClipboard();
            }
            SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case WM_DESTROY:
            ChangeClipboardChain(windowHandler, nextClipboardViewer);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
            break;
    }
    return 0;
}


我只是尝试替换剪贴板中的信息,但是此代码不起作用。

更新:现在我正在使用不可见窗口和SetClipboardViewer监视更改。但是剪贴板中的数据不会改变。

最佳答案

我怀疑在处理WM_DRAWCLIPBOARD消息时更改剪贴板的内容是否真的安全-至少让我感到惊讶的是,您不会触发无限循环(因为您对EmptyClipboard()SetClipboardData()的调用可能触发另一个WM_DRAWCLIPBOARD消息)。可能该系统对此有所保护-我从未尝试找出答案-但它仍然感觉不对:)

尝试使用此版本,其中a)将剪贴板更新移动到窗口发布到其自身的单独消息中(将其移动到剪贴板更改通知代码之外),b)使用全局标志来忽略其所做的更改。

(请注意:我认为您代码的实际错误是,当您处理WM_CREATE时,尚未分配windowHandler。您大概是将其设置为返回值CreateWindowEx,但是当WM_CREATE被处理过的CreateWindowEx尚未真正返回。这意味着剪贴板查看器实际上并未正确建立。我已更改了引用,以使用hwnd来解决此问题。)

string test("my data");

#define MSG_UPDATECLIPBOARD     (WM_APP + 1)
static bool g_fIgnoreClipboardChange = false;

LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
        case WM_CREATE:
            nextClipboardViewer = SetClipboardViewer(hwnd);
            MessageBeep(MB_ICONINFORMATION);
            break;
        case WM_CHANGECBCHAIN:
            if((HWND) wParam == nextClipboardViewer)
                nextClipboardViewer == (HWND) lParam;
            else if(nextClipboardViewer != NULL)
                SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case WM_DRAWCLIPBOARD:
            if (!g_fIgnoreClipboardChange)
                PostMessage(hwnd, MSG_UPDATECLIPBOARD, 0, 0);
            if(nextClipboardViewer != NULL)
                SendMessage(nextClipboardViewer, msg, wParam, lParam);
            break;
        case MSG_UPDATECLIPBOARD:
            g_fIgnoreClipboardChange = true;
            if(OpenClipboard(hwnd)) {
                HGLOBAL hClipboardData;
                hClipboardData = GlobalAlloc(GMEM_MOVEABLE, test.size() + 1);
                char * pchData;
                pchData = (char*)GlobalLock(hClipboardData);
                memcpy(pchData, test.c_str(), test.size() + 1);
                GlobalUnlock(hClipboardData);
                SetClipboardData(CF_TEXT, hClipboardData);
                CloseClipboard();
            }
            g_fIgnoreClipboardChange = false;
            break;
        case WM_DESTROY:
            ChangeClipboardChain(hwnd, nextClipboardViewer);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
            break;
    }
    return 0;
}

关于c++ - 监控剪贴板,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18311274/

10-16 10:16