在GUI自动化服务的开发中,我们的团队面临着无法正确处理WM_LBUTTONUP消息的问题。
目标是拦截 WM_LBUTTONUP,禁用活动窗口,完成我们的工作并显示带有 YES 和 NO 按钮的 MessageBox:
- 如果点击是,我们手动做我们的事情;
- 否则,如果单击 NO,则不执行任何操作,但在这两种情况下,我们都必须阻止单击的窗口接收此消息,然后启用冻结窗口。
尝试使用 WH_MOUSE_LL 钩子,但点击的窗口在我们可以做任何事情之前收到点击。尝试使用 WH_GETMESSAGE 钩子,我们做所有事情,但在启用接收 WM_LBUTTONUP 后,用户独立回答禁用的窗口。
消息循环的代码(在 Service.exe 中):
int Loop()
{
do
{
if (PeekMessage(&MessagesQueue, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&MessagesQueue);
DispatchMessage(&MessagesQueue);
}
} while (true);
ResetHook();
return (int)MessagesQueue.wParam;
}
与 WH_MOUSE_LL 一起使用的代码(在 Service.dll 中):
LRESULT __stdcall HookProc(int code, WPARAM wParam, LPARAM lParam)
{
if (wParam == WM_LBUTTONUP && GetAsyncKeyState(VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1))
{
HWND w = GetForegroundWindow();
EnableWindow(w, FALSE);
// Do things right.
EnableWindow(w, TRUE);
SetForegroundWindow(w);
}
return CallNextHookEx(MouseHook, code, wParam, lParam);
}
HRESULT SetHook()
{
MouseHook = SetWindowsHookExW(WH_MOUSE_LL, HookProc, hDllModule, 0);
if (MouseHook == NULL)
{
wcout << L"MouseHook = NULL" << endl;
}
else
{
wcout << L"MouseHook is" << endl;
}
return (MouseHook == NULL) ? ::GetLastError() : NO_ERROR;
}
void ResetHook()
{
UnhookWindowsHookEx(MouseHook);
}
以及与 WH_GETMESSAGE 一起使用的代码(在 Service.dll 中):
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MSG* msg = (MSG*)lParam;
if (msg->message == WM_LBUTTONUP && GetAsyncKeyState(VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1))
{
HWND w = GetForegroundWindow();
EnableWindow(w, FALSE);
// Do things right.
EnableWindow(w, TRUE);
SetForegroundWindow(w);
}
}
所以我的问题是如何拦截 WM_LBUTTONUP 消息并阻止目标窗口接收到该消息?