Reputation: 5719
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.
Upvotes: 1
Views: 527
Reputation: 5719
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
}
}
Upvotes: 1
Reputation: 670
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
Upvotes: 1