监控剪贴板
我正在用全局钩子写入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()
可以触发另一消息)。可能系统有保护反对 - 我从来没有试图找出 - 但它仍然感觉错误:)
试试这个版本,其中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;
}
是的,你是对的。我的头痛是SetClipboardViewer()函数中错误的窗口句柄。现在它完美地工作。 –
我只是在学习C++,并且对你有一个非常简单的问题:我正尝试使用此代码在我的控制台win32应用程序中创建一个新线程。我收到“nextClipboardViewer”未定义的错误。我包含哪些库来解决这个问题?我GOOGLE了它,但没有发现这个特定的功能和库进口;我假设这是我的问题。 – user1017063
该代码来自OP,只是一个片段,并不是一个完整的程序。如果你添加'HWND nextClipboardViewer = 0; ** **外部函数(使其成为一个全局函数),它应该让你通过那个错误,但我不知道你会遇到什么其他错误只使用片段别人的代码。 –
即使这可以作出的工作,你会是陷阱“WM_COPY”消息用于在剪贴板上放置数据的实例 - 无法保证。创建一个窗口并使用'SetClipboardViewer'或'AddClipboardFormatListener'是一个更好的解决方案。 –
在应用程序复制数据之前,清空剪贴板是毫无意义的。错误的钩子,使用WH_CALLWNDPROCRET。你真的*想要使用SetClipboardViewer。如果你没有HWND,那么只需创建一个HWND,它不一定是可见的。确保你的卸载程序是完美无瑕的,它会得到很好的锻炼。 –