#ifndef UNICODE
#define UNICODE
#define _UNICODE
#endif
#include <windows.h>
#include <stdio.h>
static HHOOK hHook;
static LRESULT CALLBACK LowLevelKeyboradProc(int code, WPARAM wParam, LPARAM lParam)
{
// Итак, у нас какое-то клавиатурное событие, и нам нужно БЫСТРО его
// обработать.
// Во-первых, тупо передаем события с отрицательным кодом дальше, как того
// требует MSDN. Не обрабатываем. Передали дальше и вернули, что вернулось.
// Но так как нас интересует только HC_ACTION, то мы поступаем так же со
// всеми остальными событиями.
if (code != HC_ACTION) // if (code < 0 && code != HC_ACTION)
{
return CallNextHookEx(hHook, code, wParam, lParam);
}
// Во-вторых, нам нужна инфа о событии. В wParam у нас тип события, а
// lParam указывает на все остальное.
UINT msg = (UINT) wParam;
KBDLLHOOKSTRUCT *info = (KBDLLHOOKSTRUCT *) lParam;
// Для примера ломаем клавишу Q. Независимо от раскладки. Так как мы
// возвращаем не 0 на сообщения о ее нажатии/отжатии, эти сообщения не
// будут обрабатываться дальше.
if (info->vkCode == VK_Q)
{
const char *action = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) ? "pressed" : "released";
printf("Q key was %s!\n", action
);
return 1;
}
// Все остальное передаем дальше, другим хукам, и возвращаем то, что
// вернулось от них.
return CallNextHookEx(hHook, code, wParam, lParam);
}
int main(void)
{
// Устанавливаем хук. При нажатии и отпускании клавиш в любом потоке будет
// переключение контекста на наш поток и вызов LowLevelKeyboradProc.
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, &LowLevelKeyboradProc, GetModuleHandle(NULL), 0);
if (hHook)
{
// Обрабатываем сообщения своего потока. Это крайне желательно делать.
MSG msg;
// Получаем очередное сообщения для потока. Если это WM_QUIT (= 0), то
// завершаем работу, если это какое-то другое - отдаем на обработку
// обратно системе, пусть сама разбирается.
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
// Убираем за собой хук и выходим.
UnhookWindowsHookEx(hHook);
return 0;
}
else
{
// SetWindowsHookEx вернула NULL.
MessageBoxW(NULL, L"Unable to install hook.", L"Error", MB_ICONERROR);
return 1;
}
}
I2lmbmRlZiBVTklDT0RFCiAgICAjZGVmaW5lIFVOSUNPREUKICAgICNkZWZpbmUgX1VOSUNPREUKI2VuZGlmCiNpbmNsdWRlIDx3aW5kb3dzLmg+CiNpbmNsdWRlIDxzdGRpby5oPgoKc3RhdGljIEhIT09LIGhIb29rOwoKc3RhdGljIExSRVNVTFQgQ0FMTEJBQ0sgTG93TGV2ZWxLZXlib3JhZFByb2MoaW50IGNvZGUsIFdQQVJBTSB3UGFyYW0sIExQQVJBTSBsUGFyYW0pCnsKICAgIC8vINCY0YLQsNC6LCDRgyDQvdCw0YEg0LrQsNC60L7QtS3RgtC+INC60LvQsNCy0LjQsNGC0YPRgNC90L7QtSDRgdC+0LHRi9GC0LjQtSwg0Lgg0L3QsNC8INC90YPQttC90L4g0JHQq9Ch0KLQoNCeINC10LPQvgogICAgLy8g0L7QsdGA0LDQsdC+0YLQsNGC0YwuCgogICAgLy8g0JLQvi3Qv9C10YDQstGL0YUsINGC0YPQv9C+INC/0LXRgNC10LTQsNC10Lwg0YHQvtCx0YvRgtC40Y8g0YEg0L7RgtGA0LjRhtCw0YLQtdC70YzQvdGL0Lwg0LrQvtC00L7QvCDQtNCw0LvRjNGI0LUsINC60LDQuiDRgtC+0LPQvgogICAgLy8g0YLRgNC10LHRg9C10YIgTVNETi4g0J3QtSDQvtCx0YDQsNCx0LDRgtGL0LLQsNC10LwuINCf0LXRgNC10LTQsNC70Lgg0LTQsNC70YzRiNC1INC4INCy0LXRgNC90YPQu9C4LCDRh9GC0L4g0LLQtdGA0L3Rg9C70L7RgdGMLgogICAgLy8g0J3QviDRgtCw0Log0LrQsNC6INC90LDRgSDQuNC90YLQtdGA0LXRgdGD0LXRgiDRgtC+0LvRjNC60L4gSENfQUNUSU9OLCDRgtC+INC80Ysg0L/QvtGB0YLRg9C/0LDQtdC8INGC0LDQuiDQttC1INGB0L4KICAgIC8vINCy0YHQtdC80Lgg0L7RgdGC0LDQu9GM0L3Ri9C80Lgg0YHQvtCx0YvRgtC40Y/QvNC4LgogICAgaWYgKGNvZGUgIT0gSENfQUNUSU9OKSAvLyBpZiAoY29kZSA8IDAgJiYgY29kZSAhPSBIQ19BQ1RJT04pCiAgICB7CiAgICAgICAgcmV0dXJuIENhbGxOZXh0SG9va0V4KGhIb29rLCBjb2RlLCB3UGFyYW0sIGxQYXJhbSk7CiAgICB9CgogICAgLy8g0JLQvi3QstGC0L7RgNGL0YUsINC90LDQvCDQvdGD0LbQvdCwINC40L3RhNCwINC+INGB0L7QsdGL0YLQuNC4LiDQkiB3UGFyYW0g0YMg0L3QsNGBINGC0LjQvyDRgdC+0LHRi9GC0LjRjywg0LAKICAgIC8vIGxQYXJhbSDRg9C60LDQt9GL0LLQsNC10YIg0L3QsCDQstGB0LUg0L7RgdGC0LDQu9GM0L3QvtC1LgogICAgVUlOVCBtc2cgPSAoVUlOVCkgd1BhcmFtOwogICAgS0JETExIT09LU1RSVUNUICppbmZvID0gKEtCRExMSE9PS1NUUlVDVCAqKSBsUGFyYW07CgogICAgLy8g0JTQu9GPINC/0YDQuNC80LXRgNCwINC70L7QvNCw0LXQvCDQutC70LDQstC40YjRgyBRLiDQndC10LfQsNCy0LjRgdC40LzQviDQvtGCINGA0LDRgdC60LvQsNC00LrQuC4g0KLQsNC6INC60LDQuiDQvNGLCiAgICAvLyDQstC+0LfQstGA0LDRidCw0LXQvCDQvdC1IDAg0L3QsCDRgdC+0L7QsdGJ0LXQvdC40Y8g0L4g0LXQtSDQvdCw0LbQsNGC0LjQuC/QvtGC0LbQsNGC0LjQuCwg0Y3RgtC4INGB0L7QvtCx0YnQtdC90LjRjyDQvdC1CiAgICAvLyDQsdGD0LTRg9GCINC+0LHRgNCw0LHQsNGC0YvQstCw0YLRjNGB0Y8g0LTQsNC70YzRiNC1LgogICAgaWYgKGluZm8tPnZrQ29kZSA9PSBWS19RKQogICAgewogICAgICAgIGNvbnN0IGNoYXIgKmFjdGlvbiA9IChtc2cgPT0gV01fS0VZRE9XTiB8fCBtc2cgPT0gV01fU1lTS0VZRE9XTikgPyAicHJlc3NlZCIgOiAicmVsZWFzZWQiOwogICAgICAgIHByaW50ZigiUSBrZXkgd2FzICVzIVxuIiwgYWN0aW9uKTsKCiAgICAgICAgcmV0dXJuIDE7CiAgICB9CgogICAgLy8g0JLRgdC1INC+0YHRgtCw0LvRjNC90L7QtSDQv9C10YDQtdC00LDQtdC8INC00LDQu9GM0YjQtSwg0LTRgNGD0LPQuNC8INGF0YPQutCw0LwsINC4INCy0L7Qt9Cy0YDQsNGJ0LDQtdC8INGC0L4sINGH0YLQvgogICAgLy8g0LLQtdGA0L3Rg9C70L7RgdGMINC+0YIg0L3QuNGFLgogICAgcmV0dXJuIENhbGxOZXh0SG9va0V4KGhIb29rLCBjb2RlLCB3UGFyYW0sIGxQYXJhbSk7Cn0KCmludCBtYWluKHZvaWQpCnsKICAgIC8vINCj0YHRgtCw0L3QsNCy0LvQuNCy0LDQtdC8INGF0YPQui4g0J/RgNC4INC90LDQttCw0YLQuNC4INC4INC+0YLQv9GD0YHQutCw0L3QuNC4INC60LvQsNCy0LjRiCDQsiDQu9GO0LHQvtC8INC/0L7RgtC+0LrQtSDQsdGD0LTQtdGCCiAgICAvLyDQv9C10YDQtdC60LvRjtGH0LXQvdC40LUg0LrQvtC90YLQtdC60YHRgtCwINC90LAg0L3QsNGIINC/0L7RgtC+0Log0Lgg0LLRi9C30L7QsiBMb3dMZXZlbEtleWJvcmFkUHJvYy4KICAgIGhIb29rID0gU2V0V2luZG93c0hvb2tFeChXSF9LRVlCT0FSRF9MTCwgJkxvd0xldmVsS2V5Ym9yYWRQcm9jLCBHZXRNb2R1bGVIYW5kbGUoTlVMTCksIDApOwoKICAgIGlmIChoSG9vaykKICAgIHsKICAgICAgICAvLyDQntCx0YDQsNCx0LDRgtGL0LLQsNC10Lwg0YHQvtC+0LHRidC10L3QuNGPINGB0LLQvtC10LPQviDQv9C+0YLQvtC60LAuINCt0YLQviDQutGA0LDQudC90LUg0LbQtdC70LDRgtC10LvRjNC90L4g0LTQtdC70LDRgtGMLgogICAgICAgIE1TRyBtc2c7CgogICAgICAgIC8vINCf0L7Qu9GD0YfQsNC10Lwg0L7Rh9C10YDQtdC00L3QvtC1INGB0L7QvtCx0YnQtdC90LjRjyDQtNC70Y8g0L/QvtGC0L7QutCwLiDQldGB0LvQuCDRjdGC0L4gV01fUVVJVCAoPSAwKSwg0YLQvgogICAgICAgIC8vINC30LDQstC10YDRiNCw0LXQvCDRgNCw0LHQvtGC0YMsINC10YHQu9C4INGN0YLQviDQutCw0LrQvtC1LdGC0L4g0LTRgNGD0LPQvtC1IC0g0L7RgtC00LDQtdC8INC90LAg0L7QsdGA0LDQsdC+0YLQutGDCiAgICAgICAgLy8g0L7QsdGA0LDRgtC90L4g0YHQuNGB0YLQtdC80LUsINC/0YPRgdGC0Ywg0YHQsNC80LAg0YDQsNC30LHQuNGA0LDQtdGC0YHRjy4KICAgICAgICB3aGlsZSAoR2V0TWVzc2FnZSgmbXNnLCBOVUxMLCAwLCAwKSkKICAgICAgICB7CiAgICAgICAgICAgIERpc3BhdGNoTWVzc2FnZSgmbXNnKTsKICAgICAgICB9CgogICAgICAgIC8vINCj0LHQuNGA0LDQtdC8INC30LAg0YHQvtCx0L7QuSDRhdGD0Log0Lgg0LLRi9GF0L7QtNC40LwuCiAgICAgICAgVW5ob29rV2luZG93c0hvb2tFeChoSG9vayk7CiAgICAgICAgcmV0dXJuIDA7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgLy8gU2V0V2luZG93c0hvb2tFeCDQstC10YDQvdGD0LvQsCBOVUxMLgogICAgICAgIE1lc3NhZ2VCb3hXKE5VTEwsIEwiVW5hYmxlIHRvIGluc3RhbGwgaG9vay4iLCBMIkVycm9yIiwgTUJfSUNPTkVSUk9SKTsKICAgICAgICByZXR1cm4gMTsKICAgIH0KfQo=