#include <Windows.h>
// variable to store the HANDLE to the hook. Don't declare it anywhere else then globally
// or you will get problems since every function uses this variable.
HHOOK _hook;
// This struct contains the data received by the hook callback. As you see in the callback function
// it contains the thing you will need: vkCode = virtual key code. (described later)
KBDLLHOOKSTRUCT kbdStruct;
void SetHook();
void ReleaseHook();
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam);
void SetHook()
{
// Set the hook and set it to use the callback function above.
// WH_KEYBOARD_LL means it will set a low level keyboard hook. More information can be found on MSDN.
// The last 2 parameters are NULL, 0 because the callback function is in the same thread and window as the
// function that sets and releases the hook. If you create a hack you will not need the callback function
// in another place then your own code file anyway. Read more about it at MSDN.
if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0)))
{
// Display a messagebox that notifies the user of an error. At this point, the hook is NOT installed!
MessageBoxA(NULL, "Failed to install hook!", "Error", MB_ICONERROR);
}
}
void ReleaseHook()
{
// Uninstall the hook you have set. If the hook wasn't yet installed then this function will fail ofcourse.
UnhookWindowsHookEx(_hook);
}
// This is the callback function. Consider it the event that is raised when, in this case,
// a key is pressed.
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
if (wParam == WM_KEYDOWN)
{
// lParam is the pointer to the struct containing the data needed, so cast and assign it to kdbStruct.
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
// a key (non-system) is pressed.
if (kbdStruct.vkCode == VK_F1)
{
// F1 is pressed!
MessageBoxA(NULL, "F1 is pressed!", "key pressed", MB_ICONINFORMATION);
}
}
}
// call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void main()
{
// Set the hook
SetHook();
// Don't mind this, it is a meaningless loop to keep a console application running.
// I used this to test the keyboard hook functionality. If you want to test it, keep it in ;)
MSG msg;
while (true)
{
}
//while (GetMessage(&msg, NULL, 0, 0)) { }
}
I2luY2x1ZGUgPFdpbmRvd3MuaD4KIAovLyB2YXJpYWJsZSB0byBzdG9yZSB0aGUgSEFORExFIHRvIHRoZSBob29rLiBEb24ndCBkZWNsYXJlIGl0IGFueXdoZXJlIGVsc2UgdGhlbiBnbG9iYWxseQovLyBvciB5b3Ugd2lsbCBnZXQgcHJvYmxlbXMgc2luY2UgZXZlcnkgZnVuY3Rpb24gdXNlcyB0aGlzIHZhcmlhYmxlLgpISE9PSyBfaG9vazsKIAovLyBUaGlzIHN0cnVjdCBjb250YWlucyB0aGUgZGF0YSByZWNlaXZlZCBieSB0aGUgaG9vayBjYWxsYmFjay4gQXMgeW91IHNlZSBpbiB0aGUgY2FsbGJhY2sgZnVuY3Rpb24KLy8gaXQgY29udGFpbnMgdGhlIHRoaW5nIHlvdSB3aWxsIG5lZWQ6IHZrQ29kZSA9IHZpcnR1YWwga2V5IGNvZGUuIChkZXNjcmliZWQgbGF0ZXIpCktCRExMSE9PS1NUUlVDVCBrYmRTdHJ1Y3Q7CiAKdm9pZCBTZXRIb29rKCk7CnZvaWQgUmVsZWFzZUhvb2soKTsKTFJFU1VMVCBfX3N0ZGNhbGwgSG9va0NhbGxiYWNrKGludCBuQ29kZSwgV1BBUkFNIHdQYXJhbSwgTFBBUkFNIGxQYXJhbSk7Cgp2b2lkIFNldEhvb2soKQp7CiAgICAvLyBTZXQgdGhlIGhvb2sgYW5kIHNldCBpdCB0byB1c2UgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGFib3ZlLgogICAgLy8gV0hfS0VZQk9BUkRfTEwgbWVhbnMgaXQgd2lsbCBzZXQgYSBsb3cgbGV2ZWwga2V5Ym9hcmQgaG9vay4gTW9yZSBpbmZvcm1hdGlvbiBjYW4gYmUgZm91bmQgb24gTVNETi4KICAgIC8vIFRoZSBsYXN0IDIgcGFyYW1ldGVycyBhcmUgTlVMTCwgMCBiZWNhdXNlIHRoZSBjYWxsYmFjayBmdW5jdGlvbiBpcyBpbiB0aGUgc2FtZSB0aHJlYWQgYW5kIHdpbmRvdyBhcyB0aGUKICAgIC8vIGZ1bmN0aW9uIHRoYXQgc2V0cyBhbmQgcmVsZWFzZXMgdGhlIGhvb2suIElmIHlvdSBjcmVhdGUgYSBoYWNrIHlvdSB3aWxsIG5vdCBuZWVkIHRoZSBjYWxsYmFjayBmdW5jdGlvbiAKICAgIC8vIGluIGFub3RoZXIgcGxhY2UgdGhlbiB5b3VyIG93biBjb2RlIGZpbGUgYW55d2F5LiBSZWFkIG1vcmUgYWJvdXQgaXQgYXQgTVNETi4KICAgIGlmICghKF9ob29rID0gU2V0V2luZG93c0hvb2tFeChXSF9LRVlCT0FSRF9MTCwgSG9va0NhbGxiYWNrLCBOVUxMLCAwKSkpCiAgICB7CgkvLyBEaXNwbGF5IGEgbWVzc2FnZWJveCB0aGF0IG5vdGlmaWVzIHRoZSB1c2VyIG9mIGFuIGVycm9yLiBBdCB0aGlzIHBvaW50LCB0aGUgaG9vayBpcyBOT1QgaW5zdGFsbGVkIQogICAgICAgIE1lc3NhZ2VCb3hBKE5VTEwsICJGYWlsZWQgdG8gaW5zdGFsbCBob29rISIsICJFcnJvciIsIE1CX0lDT05FUlJPUik7CiAgICB9Cn0KCnZvaWQgUmVsZWFzZUhvb2soKQp7CiAgICAvLyBVbmluc3RhbGwgdGhlIGhvb2sgeW91IGhhdmUgc2V0LiBJZiB0aGUgaG9vayB3YXNuJ3QgeWV0IGluc3RhbGxlZCB0aGVuIHRoaXMgZnVuY3Rpb24gd2lsbCBmYWlsIG9mY291cnNlLgogICAgVW5ob29rV2luZG93c0hvb2tFeChfaG9vayk7Cn0KCi8vIFRoaXMgaXMgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uLiBDb25zaWRlciBpdCB0aGUgZXZlbnQgdGhhdCBpcyByYWlzZWQgd2hlbiwgaW4gdGhpcyBjYXNlLCAKLy8gYSBrZXkgaXMgcHJlc3NlZC4KTFJFU1VMVCBfX3N0ZGNhbGwgSG9va0NhbGxiYWNrKGludCBuQ29kZSwgV1BBUkFNIHdQYXJhbSwgTFBBUkFNIGxQYXJhbSkKewogICAgaWYgKG5Db2RlID49IDApCiAgICB7CiAgICAgICAgLy8gdGhlIGFjdGlvbiBpcyB2YWxpZDogSENfQUNUSU9OLgogICAgICAgIGlmICh3UGFyYW0gPT0gV01fS0VZRE9XTikKICAgICAgICB7CiAgICAgICAgICAgIC8vIGxQYXJhbSBpcyB0aGUgcG9pbnRlciB0byB0aGUgc3RydWN0IGNvbnRhaW5pbmcgdGhlIGRhdGEgbmVlZGVkLCBzbyBjYXN0IGFuZCBhc3NpZ24gaXQgdG8ga2RiU3RydWN0LgogICAgICAgICAgICBrYmRTdHJ1Y3QgPSAqKChLQkRMTEhPT0tTVFJVQ1QqKWxQYXJhbSk7CiAgICAgICAgICAgIC8vIGEga2V5IChub24tc3lzdGVtKSBpcyBwcmVzc2VkLgogICAgICAgICAgICBpZiAoa2JkU3RydWN0LnZrQ29kZSA9PSBWS19GMSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgLy8gRjEgaXMgcHJlc3NlZCEKICAgICAgICAgICAgICAgIE1lc3NhZ2VCb3hBKE5VTEwsICJGMSBpcyBwcmVzc2VkISIsICJrZXkgcHJlc3NlZCIsIE1CX0lDT05JTkZPUk1BVElPTik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAKICAgIC8vIGNhbGwgdGhlIG5leHQgaG9vayBpbiB0aGUgaG9vayBjaGFpbi4gVGhpcyBpcyBuZXNzZWNhcnkgb3IgeW91ciBob29rIGNoYWluIHdpbGwgYnJlYWsgYW5kIHRoZSBob29rIHN0b3BzCiAgICByZXR1cm4gQ2FsbE5leHRIb29rRXgoX2hvb2ssIG5Db2RlLCB3UGFyYW0sIGxQYXJhbSk7Cn0KCnZvaWQgbWFpbigpCnsKICAgIC8vIFNldCB0aGUgaG9vawogICAgU2V0SG9vaygpOwogCiAgICAvLyBEb24ndCBtaW5kIHRoaXMsIGl0IGlzIGEgbWVhbmluZ2xlc3MgbG9vcCB0byBrZWVwIGEgY29uc29sZSBhcHBsaWNhdGlvbiBydW5uaW5nLgogICAgLy8gSSB1c2VkIHRoaXMgdG8gdGVzdCB0aGUga2V5Ym9hcmQgaG9vayBmdW5jdGlvbmFsaXR5LiBJZiB5b3Ugd2FudCB0byB0ZXN0IGl0LCBrZWVwIGl0IGluIDspCiAgICBNU0cgbXNnOwoJd2hpbGUgKHRydWUpCgl7CgoJfQoKICAgIC8vd2hpbGUgKEdldE1lc3NhZ2UoJm1zZywgTlVMTCwgMCwgMCkpIHsgfQp9