Simulating Keyboard with Sendinput API in Directinput Applications

Simulating Keyboard with SendInput API in DirectInput applications

I've found the solution to my own problem. So, I thought I'd post here to help anyone who may have similar issues in the future.

The keyup command was not working properly because when only sending the scan code, the keyup must be OR'ed with the scan code flag (effectively enabling both flags) to tell the SendInput() API that this is a both a KEYUP and a SCANCODE command.

For instance, the following code will properly issue a scan code key-up:

INPUT[] InputData = new INPUT[1];

InputData[0].Type = (UInt32)InputType.KEYBOARD;
//InputData[0].Vk = (ushort)DirectInputKeyScanCode; //Virtual key is ignored when sending scan code
InputData[0].Scan = (ushort)DirectInputKeyScanCode;
InputData[0].Flags = (uint)KeyboardFlag.KEYUP | (uint)KeyboardFlag.SCANCODE;
InputData[0].Time = 0;
InputData[0].ExtraInfo = IntPtr.Zero;

// Send Keyup flag "OR"ed with Scancode flag for keyup to work properly
SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)))

Thanks to Hans for the response. I did some investigating and sending two messages back to back like the original example does indeed simulate a "keypress" but it's very fast. It would not work well for a movement command, but would be ideal when action keys are to be "tapped" and not held down.

Also, the virtual key field is ignored when sending a scan code. MSDN had the following to say on the subject:

"Set the KEYEVENTF_SCANCODE flag to define keyboard input in terms of the scan code. This is useful to simulate a physical keystroke regardless of which keyboard is currently being used. The virtual key value of a key may alter depending on the current keyboard layout or what other keys were pressed, but the scan code will always be the same."

http://msdn.microsoft.com/en-us/library/ms646271%28v=VS.85%29.aspx

Simulating Keyboard with SendInput C#

You need to send a KEYEVENTF_KEYDOWN and then a KEYEVENTF_KEYUP event in order for the game to correctly process the key events.

Leave a little pause in between the sending of the key events.

This is needed if the game is polling the keys, it then has time to recognize the pressed key.

Can the sendinput API simulate a keyboard key being held down during some time?

SendInput can trigger events with INPUT structures including KEYBDINPUT. A KEYBDINPUT can specify key up and key down events using virtual keys or scan codes. So you want to use SendInput twice: send a key down event at the beginning, and a key up event at the end.

How to simulate specified keyboard keystroke in c++?

When using KEYEVENTF_UNICODE, the kb.wScan just has to be the wchar_t unicode character.
Don't use MapVirtualKey.

Also, don't forget to send the "Key Up" transition, just after the Key Down.

UINT res = SendInput ( 1 , & kInput , sizeof ( INPUT ) ) ;
kb.dwFlags |= KEYEVENTF_KEYUP;
res = SendInput ( 1 , & kInput , sizeof ( INPUT ) ) ;

Send Key Strokes to Games using Direct Input

An alternate way would be to hook the DirectInput API directly - Microsoft Research has provided a library to do this already: http://research.microsoft.com/en-us/projects/detours/

Once you hook into the API, you can do whatever you want with it. However, it's worth noting that in recent versions of Windows, DirectInput for mouse & keyboard input is just a wrapper around the Win32 windows messages. DirectInput spawns a thread in the background and simply intercepts window messages before passing them along back to the application. It's one of the reasons why Microsoft no longer recommends the use of DirectInput - and it means that messaging APIs like PostMessage should work just fine.

simulating key press event using SendInput with C#

but for now, for testing purposes I'm simulating only keyUP event

Which is okay I guess but that is not going to make Windows do anything. To generate a keystroke, you must first send a KEYDOWN. A "hold-time" doesn't have any useful effect so just put the two SendInput calls in the same method.

You should add error checking, winapi calls don't generate any exceptions. Throw a Win32Exception if the function returns 0. And fix the [DllImport] declaration with SetLastError = true.

You can avoid using that program you found at superuser.com by setting the ki.wVk field instead and omitting the KEYEVENTF_SCANCODE flag. So that you specify virtual keys instead of scan codes. The .NET Keys enumeration type gives you the values you need. Like Keys.A to generate a key press for the A key.



Related Topics



Leave a reply



Submit