Разница между использованиями 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:
Этот хук вызывается в контексте потока, который его установил. Вызов осуществляется путем отправки сообщения в поток, который установил хук. Поэтому поток, который установил ловушку, должен иметь цикл сообщений.
Ваш нерабочий код устанавливает ловушку в потоке, который не запускает цикл сообщений.