我正在用全局钩子(Hook)编写 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);
phá vỡ;
case WM_CHANGECBCHAIN:
if((HWND) wParam == nextClipboardViewer)
nextClipboardViewer == (HWND) lParam;
else if(nextClipboardViewer != NULL)
SendMessage(nextClipboardViewer, msg, wParam, lParam);
phá vỡ;
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);
phá vỡ;
case WM_DESTROY:
ChangeClipboardChain(windowHandler, nextClipboardViewer);
PostQuitMessage(0);
phá vỡ;
mặc định:
return DefWindowProc(hwnd, msg, wParam, lParam);
phá vỡ;
}
trả về 0;
}
我只是想替换剪贴板中的信息,但这段代码不起作用。
gia hạn:现在我正在使用不可见窗口和 SetClipboardViewer 来监视更改。但剪贴板中的数据不会改变。
我怀疑在处理 WM_DRAWCLIPBOARD
消息时更改剪贴板的内容是否真的安全 - 至少我很惊讶你没有触发无限循环(因为你调用 EmptyClipboard()
Và SetClipboardData()
可能会触发另一个 WM_DRAWCLIPBOARD
消息)。可能系统对此有保护——我从来没有试图找出答案——但它仍然感觉不对:)
试试这个版本,它:
- 将剪贴板更新移动到窗口发布给自己的单独消息(将其移出剪贴板会更改通知代码)
- 使用全局标志忽略它自己所做的更改。
注意:我认为您的代码的实际错误是当您处理 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);
phá vỡ;
case WM_CHANGECBCHAIN:
if((HWND) wParam == nextClipboardViewer)
nextClipboardViewer = (HWND) lParam;
else if(nextClipboardViewer != NULL)
SendMessage(nextClipboardViewer, msg, wParam, lParam);
phá vỡ;
case WM_DRAWCLIPBOARD:
if (!g_fIgnoreClipboardChange)
PostMessage(hwnd, MSG_UPDATECLIPBOARD, 0, 0);
if(nextClipboardViewer != NULL)
SendMessage(nextClipboardViewer, msg, wParam, lParam);
phá vỡ;
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;
phá vỡ;
case WM_DESTROY:
ChangeClipboardChain(hwnd, nextClipboardViewer);
PostQuitMessage(0);
phá vỡ;
mặc định:
return DefWindowProc(hwnd, msg, wParam, lParam);
phá vỡ;
}
trả về 0;
}
Tôi là một lập trình viên xuất sắc, rất giỏi!