Keyboard class + a shitty hook.
This isn't really "CA specific" as it'll work in any application that uses the Windows Message Queue. Basically it's a way to introduce "callback-oriented" keyboard commands; a nice alternative from everyone's spammed calls to "GetAsyncKeyState". I've included my basic Hook class too so I'll add a bit of explanation about that in case someone wants to rip it out and use it somewhere.
For people that haven't ever done any Win32 Windows programming, essentially all Windows applications (GUI-subsystem, not console applications) implement a "message queue" at some level (yes even in the .NET framework, although you never really see this unless you're overriding the famous "WndProc" event). To read more about the Message Queue, check here.
The Keyboard Class
The way a window behaves depends on the messages it receives in its message queue (is the mouse down, it it in a draggable area..etc etc). A typical message loop is implemented something like this:
That's it! In DirectX games you may see a message loop that doesn't block so much, like the following:
Source: DirectXTutorial.com | Lesson 4: The Real-Time Message Loop
Either way, we see some common API calls here. Why is this relevant? Your keyboard messages also go through this message loop before being processed by the game. By hooking into one of these public API calls, you can intercept keyboard messages and do your own processing to respond to the user's input. This is what I've done.
The hook is very simple:
1) Call the real API to translate the message properly.
2) Check if the MSG we received is relevant to us (a keyboard message)
3) If yes to 2) construct the KBDLLHOOKSTRUCT and run the callbacks. If no to 2), skip this step and go to 4
4) Reset the hook and return the real value of the TranslateMessage call.
Easy peasy. There are only 3 methods you need to concern yourself with in the Keyboard class:
That's it. I've written the class so you can even specify member functions as a callback (i.e class methods)
Your callback must have the following signature:
An example of using the class is demonstrated below:
Super simple stuff.
The Hook Class
Alright to support this I needed to be able to hook into the API. I wrote a very simple Hook class to do this and it's included in the source code in the attachment. Unlike most hooks this is more OO, some people might not like this and deem it "inefficient" or whatever; I don't really give a fuck, replace my hook with your own, it's not very difficult.
Basically I've implemented 3 "types" of hook into this. You can configure a bunch of shit in the header file to change the way that the Hook is implemented at runtime.
The first 3 defines need to remain exactly as they are. Touch them and any ensuing assfuckery is your own stupid fault.
DEFAULT_HOOK specifies, you guessed it, the default hooking method to use. If you have VARIABLE_HOOKS #defined, this value is ignored.
If you uncomment VARIABLE_HOOKS the Hook class will compile into a dynamic hooking beast, using 1 of the 3 available hooks each time the hook is reset.
I've commented the source code for all the included files so I won't spend too much time going over how it all works and how to use it. Read the code comments, then see how I've hooked the TranslateMessage API in keyboard.cc to see how to properly use the Hook class.

Hopefully someone pulls their head out of their ass and uses this, but I doubt it.
Cheers,
Jason
For people that haven't ever done any Win32 Windows programming, essentially all Windows applications (GUI-subsystem, not console applications) implement a "message queue" at some level (yes even in the .NET framework, although you never really see this unless you're overriding the famous "WndProc" event). To read more about the Message Queue, check here.
The Keyboard Class
The way a window behaves depends on the messages it receives in its message queue (is the mouse down, it it in a draggable area..etc etc). A typical message loop is implemented something like this:
Code:
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg); // dispatches the message to the window handler, typically WndProc
}
Code:
// Enter the infinite message loop
while(TRUE)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message == WM_QUIT)
break;
// Run game code here
// ...
// ...
}
Either way, we see some common API calls here. Why is this relevant? Your keyboard messages also go through this message loop before being processed by the game. By hooking into one of these public API calls, you can intercept keyboard messages and do your own processing to respond to the user's input. This is what I've done.
The hook is very simple:
1) Call the real API to translate the message properly.
2) Check if the MSG we received is relevant to us (a keyboard message)
3) If yes to 2) construct the KBDLLHOOKSTRUCT and run the callbacks. If no to 2), skip this step and go to 4
4) Reset the hook and return the real value of the TranslateMessage call.
Easy peasy. There are only 3 methods you need to concern yourself with in the Keyboard class:
Code:
Keyboard::set(); Keyboard:unset(); Keyboard::add_callback();
Your callback must have the following signature:
Code:
void __cdecl KeyboardProc(key_message msg, const KBDLLHOOKSTRUCT *pKeyData);
Code:
#include "keyboard.h"
HANDLE hMainThread = NULL;
BOOL bExiting = FALSE;
void __cdecl KeyboardCallback(key_message msg, const KBDLLHOOKSTRUCT *pKbData) {
if (msg == KEYDOWN) {
char szKey[2];
sprintf(szKey, "%c", (char)pKbData->vkCode);
MessageBoxA(NULL, szKey, "key pressed", MB_OK);
// ZOMG DO H4X HERE
}
}
DWORD WINAPI EntryProc(LPVOID) {
// add the custom callback, then set the hook
Keyboard::add_callback(&KeyboardCallback);
Keyboard::set();
while (!bExiting)
Sleep(150);
// module is being unloaded now, unset the hook to be as unintrusive as possible
Keyboard::unset();
return TRUE;
}
BOOL APIENTRY DllMain(HMODULE hThis, DWORD dwReason, LPVOID lpReserved) {
// typical entry point code blah blah.
if (dwReason == DLL_PROCESS_ATTACH) {
hMainThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&EntryProc, NULL, 0, NULL);
}
else if (dwReason == DLL_PROCESS_DETACH) {
// flag the module as closing to exit the infinite loop
bExiting = TRUE;
WaitForSingleObject(hMainThread, 150);
CloseHandle(hMainThread);
}
return TRUE;
}
The Hook Class
Alright to support this I needed to be able to hook into the API. I wrote a very simple Hook class to do this and it's included in the source code in the attachment. Unlike most hooks this is more OO, some people might not like this and deem it "inefficient" or whatever; I don't really give a fuck, replace my hook with your own, it's not very difficult.
Basically I've implemented 3 "types" of hook into this. You can configure a bunch of shit in the header file to change the way that the Hook is implemented at runtime.
Code:
# define JMP_HOOK 0 # define PUSHRET_HOOK 1 # define MOVJMP_HOOK 2 # define DEFAULT_HOOK MOVJMP_HOOK //# define VARIABLE_HOOKS // comment this #define out to get a single lean and mean default hook
DEFAULT_HOOK specifies, you guessed it, the default hooking method to use. If you have VARIABLE_HOOKS #defined, this value is ignored.
If you uncomment VARIABLE_HOOKS the Hook class will compile into a dynamic hooking beast, using 1 of the 3 available hooks each time the hook is reset.
I've commented the source code for all the included files so I won't spend too much time going over how it all works and how to use it. Read the code comments, then see how I've hooked the TranslateMessage API in keyboard.cc to see how to properly use the Hook class.
Hopefully someone pulls their head out of their ass and uses this, but I doubt it.
Cheers,
Jason


