简体   繁体   English

如何使用 SendInput 重复击键?

[英]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.我正在用 VC++ 编写一个小工具来记录击键以便稍后重播,这是一个宏记录器。 It works quite nice already, using a keyboard hook function that reads each and every key press and release event.它已经工作得很好,使用键盘钩子 function 读取每个按键和释放事件。 The playback works with the SendInput() function and generally also works fine - except for repeating key strokes.回放与 SendInput() function 一起工作并且通常也可以正常工作 - 除了重复击键。 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?那么,如何让 SendInput 发送单个键的多个后续击键,而无需在其间自行添加键释放事件? Sending a sequence of [press] [press] [press]... [release] doesn't always work.发送一系列 [press] [press] [press]... [release] 并不总是有效。

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.您可以在一个 SendInput 调用中发送多个键,但您仍然需要在每个字符上设置 keyup 标志,以便在每种类型的击键上获得相同的结果。

if you need to send "aa", you can do like this.如果你需要发送“aa”,你可以这样做。

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.我编写了一个小型 Win32 工具 [1] 来在按下全局快捷键时发送键。 When characters were repeated, eg, "aaabc", the repeated characters were lost.当字符重复时,例如“aaabc”,重复的字符将丢失。 I tried many combinations of KeyDown and KeyUp, but repeated characters were always lost.我尝试了很多 KeyDown 和 KeyUp 的组合,但是重复的字符总是丢失。

Then I found this blog post: https://batchloaf.wordpress.com/2014/10/02/using-sendinput-to-type-unicode-characters/然后我找到了这篇博文: 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.虽然作者没有专门讨论重复字符,但它启发了我尝试仅使用一个INPUT结构的SendInput() This technique works very well for me.这种技术对我来说效果很好。

In short:简而言之:

  1. Call SendInput() with only a single INPUT structure.仅使用一个INPUT结构调用SendInput()
  2. To simulate a single typed (regular) key, eg, z , try this:要模拟单个键入的(常规)键,例如z ,请尝试以下操作:
    • Send single KeyDown event: ki.dwFlags = KEYEVENTF_UNICODE发送单个 KeyDown 事件: ki.dwFlags = KEYEVENTF_UNICODE
    • Send single KeyUp event: ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP发送单个 KeyUp 事件: ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP

[1] https://github.com/kevinarpe/win32/tree/master/send_input [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:许多人遇到 keyup 和 keydown 调用被“忽略”或“丢弃”的问题,并且很多人通过在两者之间放置少量缓冲时间来解决他们的问题,以确保所有命令都被传输:

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

There's also a SendInput.SendWait command....还有一个SendInput.SendWait命令....

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.我想不出任何其他方法来结束与原始相同数量的“按键重复”,因为这些不会记录为单独的按键操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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