views:

328

answers:

3

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.

A: 

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

Anthony M. Powers
Unfortunately, SendInput doesn't allow delays. You just give it the key events to send, as INPUT[], and it sends them right away - in one piece, with no other events coming in between them. SendWait is a .NET method, I'm not using .NET here. Also, that "wait" doesn't affect the actual SendInput call as can be seen with .NET Reflector.
LonelyPixel
(was over limit) Sending a key once always works, no problem here. It just doesn't always work to send it repeatedly, like in your syntax: sendinput 3 keydown; sendinput 3 keydown; sendinput 3 keydown; sendinput 3 keyup. (This is the sequence in which the hook function reports repeated key strokes by the user.)
LonelyPixel
A: 

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.

karoberts
Sorry, I don't understand what you mean. I'm sending the exact events I record from the hook function to SendInput(). There's a time member in that data structure but it doesn't seem to have any effect.
LonelyPixel
The time member is for a timestamp, not a duration. You want to simulate the user holding down a key for 350ms, then you send a key down, wait 350ms, and send a key up.
karoberts
A: 

Hi,

You can 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].ki.wVk = 0;
input[0].ki.wScan = 'a';
input[0].ki.dwFlags = 0;

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

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

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

SendInput(4, input, sizeof(INPUT));
S.Mark
Yes, I think that's what I need to do. But oddly, those key_up events cannot be seen from the hook function. So if you're using the real keyboard, it really only sends (down, down, up) and not (down, up, down, up). I was hoping I could send events the same way as they can be recorded. The next question then is after what key events to insert a key_up event. Obviously, when pressing the Alt key, holding it and then pressing a letter, inserting key_ups is not desired as it could focus the menu or something.
LonelyPixel