How to simulate a hardware key press by using SendMessage() intead of SendInput()?

236 views Asked by At

I have been trying to screen capture a game that blocks the Windows GDI API (possibly via API hooking) and hence I cannot use the good old BitBlt() for capturing the screen, unfortunately. Whenever I call BitBlt , it fails with an error code: 126 (ERROR_MOD_NOT_FOUND), which is very weird!

I tried simulating the print screen key on the keyboard using the preferred API SendInput() to send VK_SNAPSHOT key events to Windows, and it can capture the screen to the clipboard successfully, but only when the game is not running.

INPUT inputs[2];
memset(inputs, 0x00, sizeof(INPUT) * 2);
// Key Press
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_SNAPSHOT;
inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;

// Key release
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = VK_SNAPSHOT;
inputs[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
SendInput(2, inputs, sizeof(INPUT));

I understand the reason for this behaviour might be because the game (closed source software) has installed a low level keyboard hook via SetWindowHookEx() and is trapping the VK_SNAPSHOT and is able to distinguish the injected keystroke via checking the flags for LLKHF_INJECTED, and is trapping such injected VK_SNAPSHOT keys by making it skip the chain and it doesn't get passed on to Windows.

But, the game application generously allows the hardware presses to be interpreted by Windows, and I can take a screenshot by pressing the hardware PrntSc (print screen) key on the physical keyboard!

Now, I am assuming that there is a window inside Windows (possibly the desktop window?) that can directly accept the print screen keystroke whether virtual or hardware. I could be wrong, please do correct me.

So, I was thinking of using the Windows API SendMessage() to send VK_SNAPSHOT events to the desktop window, but unfortunately it is not working, neither when the game is running, nor in normal circumstances in which VK_SNAPSHOT sent by SendInput() works fine.

This is how I am using SendMessage():

/* Key Press */
SendMessage(GetDesktopWindow(), WM_KEYDOWN, VK_SNAPSHOT, 0) // Is lParam = 0, a problem here?
/* Key Release */ 
SendMessage(GetDesktopWindow()), WM_KEYUP, VK_SNAPSHOT, 0) 

Coding language: C , Environment: Microsoft Visual Studio 2022, Windows 10 or Windows 11.

Please do consider all this and help me out! Every help, comment and answer will be appreciated! Please understand that everything is for fair use, and the game manufacturer has no problem in taking screen captures, and I don't know why they are blocking this.

Other methods that show me the way in taking screen captures will help me a lot!

0

There are 0 answers