C语言 The Difference between to usages of SetWindowsHookEx



首先:我在Windows XP-32位上使用Visual Studio 2010。

现在我正在尝试编写一个DLL,它将使另一个应用程序能够使用低级键盘挂钩。

尽管我已经开始工作了,但我现在想明白为什么。

非工作代码:

#include <Windows.h>
#include <stdio.h>
static HINSTANCE hinst;
static HHOOK kbdHook = NULL;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf(":"); fflush(stdout);
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            hinst = hinstDLL;
            CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
            kbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hinst, 0);
            break;
        case DLL_PROCESS_DETACH:
            UnhookWindowsHookEx(kbdHook);
            break;
        default:
            break;
    }
    return TRUE;
}

工作代码:

#include <Windows.h>
#include <stdio.h>
static HINSTANCE hinst;
static HHOOK kbdHook = NULL;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf(":"); fflush(stdout);
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    MSG msg;
    kbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            hinst = hinstDLL;
            CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
            break;
        case DLL_PROCESS_DETACH:
            UnhookWindowsHookEx(kbdHook);
            break;
        default:
            break;
    }
    return TRUE;
}

唯一的区别是我将SetWindowsHookEx-调用从DllMain移动到了ThreadProc

问题是:为什么这个会带来所有的不同?

LowLevelKeyboardProc回调函数的文档中对此进行了解释:

这个钩子是在安装它的线程的上下文中调用的。通过向安装钩子的线程发送消息来进行调用因此,安装钩子的线程必须有一个消息循环

您的非工作代码将钩子安装在一个线程上,该线程不会运行消息循环。

最新更新