[Win32] No WM_KEYDOWN for screenshot-key

Started by
10 comments, last by Erik Rufelt 8 years, 9 months ago

So I was going for Erik Rufelts appoach with SetWindowsHookEx, by pretty much copying his code, and it worked so far. Unfortunately, this means that keyboard input now is becoming unresponsive when the application ie. is stalling in a (single threaded) loading routine. For example, while I'm loading the project, I cannot ALT+TAB out of the window, and when a breakpoint is hit, I can't really use any key commands for the debugger. From what I've been able to gather this is due to that once you inject the WH_KEYBOARD_LL, processing of key events require a running message loop. Though it solves problems with the hotkey approach (no clipboard data, print not working in different windows while the application is running), this is way to annoying to keep it actually going. Is there anything I can do about those problems with the WH_KEYBOARD_LL solution? Otherwise, I might as well switch to the (kinda hackish) solution of using WM_KEYUP for print instead...

Advertisement

Not entirely sure it's the best way but this should work:


LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
	if(nCode < 0 || nCode != HC_ACTION || !appIsActive)
		return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);

	if(wParam == WM_KEYDOWN || wParam == WM_KEYUP) {
		KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
		if(p->vkCode == VK_SNAPSHOT) {
			bool down = (wParam == WM_KEYDOWN);

			return 1;
		}
	}

	return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}

DWORD WINAPI HookThreadProc(LPVOID lpParam) {
	HINSTANCE hModule = (HINSTANCE)lpParam;
	HHOOK hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hModule, NULL);
	MSG msg;
	while(GetMessage(&msg, NULL, 0, 0) > 0) {
	}
	UnhookWindowsHookEx(hKeyboardHook);
	return 0;
}

...

CreateThread(NULL, 0, HookThreadProc, GetModuleHandle(NULL), 0, NULL);

And if you want to wait for the thread to exit cleanly PostThreadMessage(WM_QUIT) and WaitForSingleObject on exit.

One thing about the method is that it if returning 1 instead of CallNextHookEx, it also disables standard print screen handling.. which may or may not be desired. If you want your messages to WndProc you can also simply post them with PostThreadMessage when detecting that key to get WM_KEYDOWN for VK_SNAPSHOT. This method can also be used to separate left/right Win/Shift/Ctrl keys.

This topic is closed to new replies.

Advertisement