关于C#:SetWindowsHookEx用法的区别

The Difference between to usages of SetWindowsHookEx

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

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

即使我可以使用它-现在我想了解原因。

非工作代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#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;
}

工作代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#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回调函数的文档中对此进行了全部解释:

This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.

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