C++ 监视剪贴板

C++ 监视剪贴板,c++,winapi,visual-c++,C++,Winapi,Visual C++,我正在用全局钩子编写dll。其中一项任务是在有人执行复制操作时查看剪贴板并从中删除所有数据。这是我的窗口回调函数: string test("my data"); LRESULT CALLBACK WndHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: nextClipboardViewer = SetClipboa

我正在用全局钩子编写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\u(剪贴板
消息)。可能系统对此有保护措施——我从未尝试过去发现——但它仍然感觉不对:)

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

(注意:我认为您的代码的实际错误在于,当您处理
WM_CREATE
时,
windowHandler
尚未分配。您可能正在将其设置为
CreateWindowEx
返回值,但当
WM_CREATE
正在处理
CreateWindowEx
时,实际上尚未返回。这意味着ns剪贴板查看器从未真正正确建立。我已将引用更改为使用
hwnd
来修复此问题。)


即使这可以实现,您也会遇到这样的情况:使用
WM_COPY
消息将数据放在剪贴板上,但这并不能保证一定会成功。创建一个窗口并使用
SetClipboardViewer
AddClipboardFormatListener
是一个更好的解决方案。清空剪贴板没有意义在应用程序将数据复制到其中之前,请先创建一个HWD。错误的钩子,请使用WH_CALLWNDPROCRET。而且您确实希望使用SetClipboardViewer。如果您没有HWD,则只需创建一个HWD,它就不必可见。请确保您的卸载程序也完美无缺,它会得到很好的锻炼。是的,您是对的。我的头痛是SetClipb中错误的窗口处理程序我现在正在学习C++,并且有一个非常简单的问题:我试图用这个代码在我的控制台Win32应用程序中创建一个新线程。是未定义的。我应该包含什么库来解决这个问题?我在谷歌上搜索了它,但在这个特定函数和库导入中没有找到任何内容;我假设这是我的问题。该代码来自OP,只是一个片段,它不是一个完整的程序。如果您在函数外部添加
HWND nextClipboardViewer=0;
(使其成为全局)它应该让你克服这个错误,但是我不确定你会遇到什么其他错误,只使用别人的代码片段。谢谢。我发现在C++中,当有一个错误时,由于缺少的库或完全不同的东西,很难判断。(VS 2015)
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;
}