Automate Game Screenshot Capture: Windows API SendInput Function with C++

I am trying to write video game reviews after I have finished a game and I like to add some impressions in the form of screenshots to the reviews. There is one problem though: sometimes it is impossible to press the keyboard shortcut to capture a screenshot because the game requires my full attention – and all my fingers. Therefore, I miss out on a lot of action sequences. What does a programmer do in such a situation? Write a tool that scratches the itch.

I decided to not write a tool that takes the screenshot itself, which is way more complex and time consuming, but rather initiates the hotkey that triggers the capture tool. I may or may not polish the tool and put it up on Github once it is worthy of being shown. The key component is the use of the Windows API, and more specific, the SendInput function. Through that you can emulate button press events and thus trigger any hotkey. Here is a quick guide on how to use it.

If you are familiar with the Windows API then this is straight forward. There is one catch though, which is why it is worth a separate blog post. First, let me show you some code on how to use it. This snippet will emulate "Win + Alt + PrintScreen" to make use of Windows’ built-in screenshot capture that can be enabled with the Xbox Game Bar.

// (1) Emulate the hotkey by pressing all keys.
auto input1 = INPUT{};
input1.type = INPUT_KEYBOARD;
input1.ki.wVk = VK_LWIN;

auto input2 = INPUT{};
input2.type = INPUT_KEYBOARD;
input2.ki.wVk = VK_MENU;

auto input3 = INPUT{};
input3.type = INPUT_KEYBOARD;
input3.ki.wVk = VK_SNAPSHOT;

// (2) Emulate releasing all keys.
auto input4 = INPUT{};
input4.type = INPUT_KEYBOARD;
input4.ki.wVk = VK_LWIN;
input4.ki.dwFlags = KEYEVENTF_KEYUP;

auto input5 = INPUT{};
input5.type = INPUT_KEYBOARD;
input5.ki.wVk = VK_MENU;
input5.ki.dwFlags = KEYEVENTF_KEYUP;

auto input6 = INPUT{};
input6.type = INPUT_KEYBOARD;
input6.ki.wVk = VK_SNAPSHOT;
input6.ki.dwFlags = KEYEVENTF_KEYUP;

// (3)
INPUT inputs[] = {input1, input2, input3, input4, input5, input6};

// (4) “Press” the hotkeys.
auto result = SendInput(6, inputs, sizeof(INPUT));

Let us quickly go through it:

  1. Create three INPUT structures for all the keys that need to be pressed and set the minimum required values:
    • type: INPUT_KEYBOARD (there is also mouse input, among other things)

    • ki.wVk: VK_LWIN, VK_MENU and VK_SNAPSHOT

      Since keyboard actions are emulated the KEYBDINPUT structure ki needs to be set. Here you only need to specify the virtual key code wVk of the button.

  2. It is not enough to just “push” the buttons. This will trigger the shortcut alright, but the buttons will remain pressed. It is therefore important to create three new INPUT structures with the same settings as in 1) and an additional ki.dwFlags = KEYEVENTF_KEYUP. Otherwise, further invocations will not work, and Windows will also behave weird until you have managed to depress the individual buttons (e.g. by pressing them on the keyboard).
  3. Create an array that contains all the key input emulations.
  4. Call the Windows SendInput function. If all goes well, it returns the number of key events it has sent – six in this example.

That is all there is to it. The important part is 2), so keep that in mind. Whenever you want to emulate a regular button press like a human would do it, you also must depress it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.