WINAPI的消息循环让我发疯

WINAPI's message loops drives me crazy

本文关键字:发疯 循环 消息 WINAPI      更新时间:2023-10-16

我一直在尝试使用 JNI 实现简单的低级键钩,一切都很顺利,直到我认为当 DLL 处于无限循环(消息循环)时我无法调用这些方法。 所以我决定创建新线程,但不知何故,在我使消息循环在自己的循环上运行之后,低级键钩停止响应,这意味着它不再调用 keyproc, 我不知道这是为什么?还有其他解决方法吗?我需要能够在键盘挂钩仍在工作时调用 DLL 的方法。

我当前的代码就像

注册键盘挂钩:

keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardProc, hInstance, 0);

启动线程

HANDLE threadHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &threadId);

我的键盘程序和线程程序如下:

DWORD WINAPI ThreadProc(LPVOID lpVoid) {
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
LRESULT CALLBACK keyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    KBDLLHOOKSTRUCT keyEvent = *((KBDLLHOOKSTRUCT*)lParam);
    jint vkCode = keyEvent.vkCode;
    jint flags = keyEvent.flags;
    jint action = wParam;
    (*globalEnv).CallVoidMethod(globalObj, keyboardMethodId, vkCode, flags, action);
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

我哪里出错了?我确定它不是 java,因为即使我为它从未调用的键程序添加简单的日志记录。但是,如果我停止使用线程并在主线程上运行消息循环,它可以正常工作,但 DLL 不会响应它之后的方法调用。

您需要在

名为 SetWindowsHookEx() 的同一线程上泵送消息循环。 因此,只需将调用移动到您的 ThreadProc() 中即可。 当然,请注意您的 CallVoidMethod() 回调也在同一线程上运行,因此请注意您在该函数中执行的操作。 您访问的任何共享状态都需要使用锁进行保护。

您正在尝试安装桌面范围的挂钩,该挂钩跨越桌面的所有进程。也就是说,DLL 映射到具有特定于进程的全局变量集的多个进程中。您在其他进程中没有有效的globalEnv,并且可能会遇到访问冲突或类似错误(可以使用共享数据细分受众群创建全局变量,有关详细信息,请参阅此文章)。

要安装特定于线程的钩子,您将需要不同类型的钩子(WH_KEYBOARD_LL仅是全局的!)和 SetWindowsHookEx 中的非零最后一个参数。