SetWindowsHookEx的用法之间的区别

时间:2016-04-12 08:36:09

标签: c winapi setwindowshookex createthread

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

现在我正在尝试编写一个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

问题:为什么这个会有所不同?

1 个答案:

答案 0 :(得分:4)

LowLevelKeyboardProc callback function的文档中解释了这一点:

  

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

你的非工作代码会在一个没有运行消息循环的线程上安装钩子。