所以我尝试用 C 语言运行一个简单的代码,在每次移动鼠标时打印鼠标的位置。为了让程序运行一段时间然后退出,我使用了如下所示的 for 循环。我希望挂钩仅与当前线程关联。 这是代码:
#include <stdio.h>
#include <windows.h>
// Global hook handle
HHOOK hHook = NULL;
// Mouse hook callback
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
printf("Entered\n");
if (nCode >= 0) {
if ((nCode == HC_ACTION) && (wParam == WM_MOUSEMOVE)) {
MOUSEHOOKSTRUCT* pMouseStruct = (MOUSEHOOKSTRUCT*)lParam;
printf("Mouse X: %ld, Mouse Y: %ld\n", pMouseStruct->pt.x, pMouseStruct->pt.y);
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
int main() {
// Install the mouse hook
hHook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC) &MouseHookProc, NULL, GetCurrentThreadId());
if (hHook == NULL) {
printf("Hook installation failed\n");
return 1;
}
// Keep program running
for (unsigned long long i = 0; i < 4e9; ++i) {}
// Unhook and exit
UnhookWindowsHookEx(hHook);
return 0;
}
printf 语句永远不会被执行。为什么hook设置成功了,proc却没有被调用?
正如评论中所指出的,您确实需要一个 Win32 消息循环才能接收 挂钩事件。
示例(main.cpp):
#include <Windows.h>
#include <iostream>
static HHOOK p_hook = nullptr;
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType);
LRESULT CALLBACK LowLevelMouseProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam);
int main()
{
if (SetConsoleCtrlHandler(HandlerRoutine, TRUE) == 0)
return ~0;
p_hook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, nullptr, 0);
if (p_hook == nullptr)
return ~0;
MSG msg = { 0 };
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (p_hook != nullptr)
UnhookWindowsHookEx(p_hook);
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK LowLevelMouseProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
if (nCode == HC_ACTION)
{
auto m_struct = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
std::cout << "x: " << m_struct->pt.x << " y: " << m_struct->pt.y << std::endl;
}
return CallNextHookEx(p_hook, nCode, wParam, lParam);
}
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_CLOSE_EVENT || dwCtrlType == CTRL_SHUTDOWN_EVENT)
{
if (UnhookWindowsHookEx(p_hook) == TRUE)
p_hook = nullptr;
}
return TRUE;
}