Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SendInput doesn't work with Print Screen key

I'm making a front end for various emulators and triggering their various functionality such as save/load state, save screenshot, but with a unified interface. FS-UAE annoyingly uses "Print Screen" as its screenshot key, and I'd like to avoid the user having to change emulators from their default hotkey settings.

I've managed to simulate any key press I want with SendInput, except for the "Print Screen" key.

I haven't had any luck with using virtual key codes, I think that doesn't work with full screen applications. Hence that part of the code is commented out. (EDIT: better explanation - Virtual Key codes are ignored by DirectInput software)

Using scan codes, I can get any key to press - almost. Print Screen seems to be the odd one out.

Here's the reference I'm using for the scan codes; https://msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx

Below is the minimum viable code to reproduce the problem. If you run it, press a key then quickly switch to notepad and wait 2 seconds, it should press the letter "q" into notepad, then quit.

Change the scan code from 0x10 (q) to 0x37 (Print Screen), be sure to do it in both places - KEY DOWN, and KEY UP.

Now run it again, press a key and wait. To see if Print Screen worked, open MS Paint or whatever and press CTRL+V, see if you get a screenshot of your desktop. It doesn't work! But if you manually press Print Screen, and CTRL+V into MS Paint, it will work.

Why doesn't the Print Screen key work?

#include "stdafx.h"

//For create process & keyboard codes
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

int main()
{
    INPUT ip = {};

    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0;
    ip.ki.wVk = 0;
    ip.ki.dwExtraInfo = 0;
    ip.ki.dwFlags = 0;

    printf("Press a key, then taskswitch.\n");
    system("pause");
    Sleep(2000);

    //KEY DOWN
    ip.ki.wScan = 0x10; //0x37 PrintScreen, 0x10 Q
    ip.ki.dwFlags = KEYEVENTF_SCANCODE;
    //ip.ki.wVk = VK_SNAPSHOT;
    //ip.ki.dwFlags = 0;
    SendInput(1, &ip, sizeof(INPUT));

    //KEY UP
    ip.ki.wScan = 0x10;
    ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; 
    //ip.ki.wVk = VK_SNAPSHOT;
    //ip.ki.dwFlags = KEYEVENTF_KEYUP; 
    SendInput(1, &ip, sizeof(INPUT));

    printf("Done.\n");
    system("pause");
    return 0;
}
like image 638
Domarius Avatar asked Jan 24 '18 12:01

Domarius


2 Answers

Use wVk instead of wScan, and make sure KEYEVENTF_SCANCODE is not set because that ignores wVk. You have to use VK_SNAPSHOT

INPUT ip[2] = { 0 };

ip[0].type = INPUT_KEYBOARD;
ip[0].ki.wVk = VK_SNAPSHOT;

ip[1] = ip[0];
ip[1].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2, ip, sizeof(INPUT));
like image 199
Barmak Shemirani Avatar answered Oct 23 '22 18:10

Barmak Shemirani


Okay I'm answering my own question here;

So I've done some more research, found this amazing post by someone who's nutted out the details of scan codes, and it seems that Print Screen is a weird one, requiring a special sequence to be triggered properly; https://handmade.network/forums/t/2011-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names (And for additional reading, there is this article on the history of the 3 different scan code sets, which gives some insight as to why some keys might be weird, as new keys were added to the standard) http://www.quadibloc.com/comp/scan.htm

However, I still couldn't get it to work trying the variety of code sequences in that article - in the end, I managed to work around my original problem by learning that FS-UAE supports an ALTERNATE key sequence for saving a screenshot: F12-S, which I am using instead and it's working great.

So I may have avoided the issue this time, but woe be the person who needs to legitimately simulate a Print Screen key press at the scan code level WITHOUT using "Virtual Key codes"... it is a mysterious arcane task that I have still not achieved.

like image 35
Domarius Avatar answered Oct 23 '22 18:10

Domarius