Разница между использованиями SetWindowsHookEx

Во-первых: я использую Visual Studio 2010 в Windows XP - 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 ответ

Решение

Это все объясняется в документации для функции обратного вызова LowLevelKeyboardProc:

Этот хук вызывается в контексте потока, который его установил. Вызов осуществляется путем отправки сообщения в поток, который установил хук. Поэтому поток, который установил ловушку, должен иметь цикл сообщений.

Ваш нерабочий код устанавливает ловушку в потоке, который не запускает цикл сообщений.

Другие вопросы по тегам