I've implemented a hook procedure that catches some Alt+letter
key combinations and injects predefined strings. An example of a hook procedure is shown below. It detects the hotkeys LeftAlt+Q
and LeftAlt+A
and injects the string ABCD1234
in both cases, using the WinAPI function SendInput()
.
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void DisplayString()
{
INPUT in[24] = { 0 };
int i;
for (i = 0; i < ARRAYSIZE(in); i++) in[i].type = INPUT_KEYBOARD;
i = 0;
in[i++].ki.wVk = VK_CONTROL; // CTRL
in[i].ki.wVk = VK_CONTROL; // CTRL Up
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i].ki.wVk = VK_LMENU; // LeftAlt Up
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = VK_LSHIFT; // LeftShift down
in[i++].ki.wVk = 'A';
in[i].ki.wVk = 'A';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = 'B';
in[i].ki.wVk = 'B';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = 'C';
in[i].ki.wVk = 'C';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = 'D';
in[i].ki.wVk = 'D';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i].ki.wVk = VK_LSHIFT; // LeftShift Up
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = '1';
in[i].ki.wVk = '1';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = '2';
in[i].ki.wVk = '2';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = '3';
in[i].ki.wVk = '3';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = '4';
in[i].ki.wVk = '4';
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
in[i++].ki.wVk = VK_CONTROL; // CTRL
in[i++].ki.wVk = VK_LMENU; // LeftAlt Down
in[i].ki.wVk = VK_CONTROL; // CTRL Up
in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(ARRAYSIZE(in), in, sizeof(INPUT));
}
HHOOK hHook{ NULL };
#define VK_HOT_1 0x51
#define VK_HOT_2 0x41
extern "C" __declspec(dllexport)
LRESULT CALLBACK KeyboardHookProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code < 0) return CallNextHookEx(hHook, code, wParam, lParam);
// If LeftAlt pressed
if (wParam == WM_SYSKEYDOWN && (GetAsyncKeyState(VK_LMENU) & 0x80000000))
{
DWORD vkCode = ((KBDLLHOOKSTRUCT*)lParam)->vkCode; // virtual-key code
if (vkCode == VK_HOT_1 || vkCode == VK_HOT_2)
{
DisplayString();
return 1;
}
}
return CallNextHookEx(hHook, code, wParam, lParam);
}
The hook procedure is installed using the function SetWindowsHookExW()
.
The program works as expected in a broad range of applications. I've tested it with WordPad, Notepad++, Chrome, Edge, Command Prompt, PowerShell, and Visual Studio. However, the program exhibits unexplained behavior when the string is injected into Notepad. Only 2-4 characters come up, and the rest appear when additional keys are pressed on the keyboard, with a couple of characters following each key down.
This behavior is new. I used Notepad to test this program during development some weeks ago, and Notepad worked fine. I'm using this program on several PCs, and some work problem-free. All the PCs use Windows 11.
EDIT: AutoHotkey
is an advanced Windows app for implementing user-defined hotkeys. The user configures the key combinations to use, and the action to perform when a hotkey is pressed. I've configured AutoHotkey
for the same hotkeys and actions as in my application and tested it on a Windows 11 PC. AutoHotkey's
behavior is the same as that of my application: injecting text works fine in all tested apps but Notepad
.
Moreover, the behavior I observe now is different. The whole string comes out intermittently, two characters at a time, seemingly at the rate of cursor blinks.