简体   繁体   中英

How to repeat key strokes with SendInput?

I'm writing a little tool in VC++ to record key strokes to replay them later, a macro recorder. It works quite nice already, using a keyboard hook function that reads each and every key press and release event. The playback works with the SendInput() function and generally also works fine - except for repeating key strokes. Pressing a key several times after releasing it every time is no problem. But pressing it and holding it down, for the input character to be repeated, can be recorded but can only be replayed in some applications. Some accept and enter the character multiple times, some do it only once. (It is reproducible which does which.) The macro recorder itself also sees the held down key pressed just a single time during playback, through its monitoring hook.

So, how can I make SendInput send multiple subsequent key strokes of a single key without adding key release events on my own in between? Sending a sequence of [press] [press] [press]... [release] doesn't always work.

You could send Multiple keys in one SendInput calls, but you will still need to set keyup flags on every char to get same results on every type of keystrokes.

if you need to send "aa", you can do like this.

INPUT input[4];

input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = 0;
input[0].ki.wScan = 'a';
input[0].ki.dwFlags = 0;

input[1].type = INPUT_KEYBOARD;
input[1].ki.wVk = 0;
input[1].ki.wScan = 'a';
input[1].ki.dwFlags = KEYEVENTF_KEYUP;

input[2].type = INPUT_KEYBOARD;
input[2].ki.wVk = 0;
input[2].ki.wScan = 'a';
input[2].ki.dwFlags = 0;

input[3].type = INPUT_KEYBOARD;
input[3].ki.wVk = 0;
input[3].ki.wScan = 'a';
input[3].ki.dwFlags = KEYEVENTF_KEYUP;

SendInput(4, input, sizeof(INPUT));

I'm not sure about your exact sequence of keystrokes, but I had a similar issue recently. I wrote a tiny Win32 tool [1] to send keys when a global shortcut key is pressed. When characters were repeated, eg, "aaabc", the repeated characters were lost. I tried many combinations of KeyDown and KeyUp, but repeated characters were always lost.

Then I found this blog post: https://batchloaf.wordpress.com/2014/10/02/using-sendinput-to-type-unicode-characters/

While the author does not specifically discuss repeating characters, it inspired me to try SendInput() with only a single INPUT structure. This technique works very well for me.

In short:

  1. Call SendInput() with only a single INPUT structure.
  2. To simulate a single typed (regular) key, eg, z , try this:
    • Send single KeyDown event: ki.dwFlags = KEYEVENTF_UNICODE
    • Send single KeyUp event: ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP

[1] https://github.com/kevinarpe/win32/tree/master/send_input

Many people experience issues with the keyup and keydown calls being "dismissed" or "dropped", and alot of people have resolved their problems by placing a small buffer amount of time between the two, to assure that all commands are transfered:

sendinput  alt keydown
sendinput  3  keydown
sleep 50
sendinput 3 keyup
sendinput alt keyup

There's also a SendInput.SendWait command....

Cheers

As far as I know, the way it works is if a key down event is received with no key up event for a certain period of time (the repeat delay), the key is considered "repeating" until a key up occurs.

Since sending press, press, press, release doesn't work always, have you tried recording the time between the key down and key up, then repeating the commands in that same time? It becomes real time, but it should trigger the same repeat actions that way.

I can't think of any other way to end up with the same amount of "key repeats" as the original since those aren't recorded as individual key presses.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM