1

How can I simulate a button press in .NET?

I can do it with AutoHotKey with ease:

#Persistent
SetTimer,PressTheKey,1000
Return

PressTheKey:
Send, {F5}
Return

Any application will know that the button was pressed (just like it was pressed by me). I tried doing the same with:

[DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

or:

[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

or using Windows Input Simulator (https://inputsimulator.codeplex.com/):

inputSimulator.Keyboard.KeyDown(VirtualKeyCode.VK_H)

They all worked in Notepad or some other apps, but they never worked in my full screen game. Any idea how I can achieve it? I would like a solution which simulates a click globally on the system level.

Michal B.
  • 5,676
  • 6
  • 42
  • 70
  • Have you looked at this post: http://stackoverflow.com/questions/10787949/insert-into-windows-keyboard-buffer ? – David Tansey Feb 08 '16 at 19:43
  • https://msdn.microsoft.com/en-us/library/ms171548%28v=vs.110%29.aspx – T.S. Feb 08 '16 at 19:54
  • Have you looked at this. http://inputsimulator.codeplex.com/ – Jacobr365 Feb 08 '16 at 19:57
  • To answer comment above. Yes, I have tried SendKeys.SendWait() (forgot to mention). I also tried InputSimulator (mentioned that) - they have not worked for me. They seem to send key strokes to specific applications and apps can disregard it... I need something that simulates the keyboard key stroke.... – Michal B. Feb 08 '16 at 23:02

2 Answers2

1

There is a lib out there called Interceptor that is a wrapper for the windows keyboard driver, however there are limitations - namely win8 or above are not supported - and it seems that work on it has ceased (11 months ago now). Have a look into that if it suits your needs.

I've read somewhere that there are ways to do this via the DirectInput API - as to whether this is the case I'm unsure. I've used Interceptor a few times and it worked for my needs at the time.

Hope this helps

Also Link

Edit: Fixed links

Community
  • 1
  • 1
Gabe
  • 570
  • 1
  • 4
  • 15
1

I learned that my application is using DirectInput (thanks Gabe). This made me focus more on SendInput and I managed to send an "A" key to my application like this:

// A = 30
keyboardDirectInput.Press(30);

All key codes are available here: https://msdn.microsoft.com/en-us/library/windows/desktop/bb321074%28v=vs.85%29.aspx

The KeyboardDirectInput class:

public class KeyboardDirectInput
{
    [DllImport("user32.dll")]
    static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);

    public void Press(VirtualKeys key)
    {
        INPUT[] InputData = new INPUT[2];

        InputData[0].type = (int)InputType.INPUT_KEYBOARD;
        InputData[0].ki.wScan = (short)key;
        InputData[0].ki.dwFlags = (int)KEYEVENTF.SCANCODE;

        InputData[1].type = (int)InputType.INPUT_KEYBOARD;
        InputData[1].ki.wScan = (short)key;
        InputData[1].ki.dwFlags = (int)(KEYEVENTF.KEYUP | KEYEVENTF.SCANCODE);

        if (SendInput(2, InputData, Marshal.SizeOf(InputData[1])) == 0)
        {
            Logger.GetInstance().Warn("SendInput failed (CODE {0})", Marshal.GetLastWin32Error());
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct INPUT
    {
        [FieldOffset(4)]
        public HARDWAREINPUT hi;
        [FieldOffset(4)]
        public KEYBDINPUT ki;
        [FieldOffset(4)]
        public MOUSEINPUT mi;
        [FieldOffset(0)]
        public int type;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct HARDWAREINPUT
    {
        public int uMsg;
        public short wParamL;
        public short wParamH;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MOUSEINPUT
    {
        public int dx;
        public int dy;
        public int mouseData;
        public int dwFlags;
        public int time;
        public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct KEYBDINPUT
    {
        public short wVk;
        public short wScan;
        public int dwFlags;
        public int time;
        public IntPtr dwExtraInfo;
    }

    [Flags]
    public enum KEYEVENTF
    {
        KEYDOWN = 0,
        EXTENDEDKEY = 0x0001,
        KEYUP = 0x0002,
        UNICODE = 0x0004,
        SCANCODE = 0x0008,
    }

    [Flags]
    public enum InputType
    {
        INPUT_MOUSE = 0,
        INPUT_KEYBOARD = 1,
        INPUT_HARDWARE = 2
    }
}
Michal B.
  • 5,676
  • 6
  • 42
  • 70