diff --git a/WindowsInput/IKeyboardSimulator.cs b/WindowsInput/IKeyboardSimulator.cs index dbfb2dc..83dc06b 100644 --- a/WindowsInput/IKeyboardSimulator.cs +++ b/WindowsInput/IKeyboardSimulator.cs @@ -27,6 +27,25 @@ public interface IKeyboardSimulator /// The for the key. IKeyboardSimulator KeyPress(VirtualKeyCode keyCode); + /// + /// Simulates the key press gesture for the specified key. + /// + /// The for the key. + IKeyboardSimulator CITRIXKeyPress(VirtualKeyCode keyCode); + + + /// + /// Simulates the key press gesture for the specified key. + /// + /// The VirtualKeyCode to release + IKeyboardSimulator CITRIXKeyUp(VirtualKeyCode keyCode); + + /// + /// Simulates the key press gesture for the specified key. + /// + /// The VirtualKeyCode to press and hold + IKeyboardSimulator CITRIXKeyDown(VirtualKeyCode keyCode); + /// /// Simulates a key press for each of the specified key codes in the order they are specified. /// diff --git a/WindowsInput/KeyboardSimulator.cs b/WindowsInput/KeyboardSimulator.cs index 1c397eb..d9cdd68 100644 --- a/WindowsInput/KeyboardSimulator.cs +++ b/WindowsInput/KeyboardSimulator.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using WindowsInput.Native; +using System.Runtime.InteropServices; namespace WindowsInput { @@ -224,5 +225,104 @@ public IKeyboardSimulator Sleep(TimeSpan timeout) Thread.Sleep(timeout); return this; } + + + // CITRIX HACK + // Function used to get the scan code + // source: https://stackoverflow.com/a/5029069 + [DllImport("user32.dll")] + static extern uint MapVirtualKey(uint uCode, uint uMapType); + + [DllImport("User32.dll")] + private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] input, int structSize); + + + /// + /// Calls the Win32 SendInput method ... + /// + /// The VirtualKeyCode to press + public IKeyboardSimulator CITRIXKeyPress(VirtualKeyCode keyCode) //prev public static void + { + var down = new INPUT(); + down.Type = (UInt32)InputType.Keyboard; + down.Data.Keyboard = new KEYBDINPUT(); + down.Data.Keyboard.KeyCode = (UInt16)keyCode; //prev .Keyboard.Vk + // Scan Code here, was 0 + down.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0); + down.Data.Keyboard.Flags = 0; + down.Data.Keyboard.Time = 0; + down.Data.Keyboard.ExtraInfo = IntPtr.Zero; + + var up = new INPUT(); + up.Type = (UInt32)InputType.Keyboard; + up.Data.Keyboard = new KEYBDINPUT(); + up.Data.Keyboard.KeyCode = (UInt16)keyCode; + // Scan Code here, was 0 + up.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0); + up.Data.Keyboard.Flags = (UInt32)KeyboardFlag.KeyUp; + up.Data.Keyboard.Time = 0; + up.Data.Keyboard.ExtraInfo = IntPtr.Zero; + + INPUT[] inputList = new INPUT[2]; + inputList[0] = down; + inputList[1] = up; + + var numberOfSuccessfulSimulatedInputs = SendInput(2, + inputList, Marshal.SizeOf(typeof(INPUT))); + if (numberOfSuccessfulSimulatedInputs == 0) + throw new Exception( + string.Format("The key press simulation for {0} was not successful.", + keyCode)); + return this; + } + + + /// + /// Calls the Win32 SendInput method ... + /// + /// The VirtualKeyCode to press and hold + /// a WindowsInput.Native.KeyboardFlag + private IKeyboardSimulator CITRIXKey(VirtualKeyCode keyCode, UInt32 keyFlag = 0) //prev public static void + { + var down = new INPUT(); + down.Type = (UInt32)InputType.Keyboard; + down.Data.Keyboard = new KEYBDINPUT(); + down.Data.Keyboard.KeyCode = (UInt16)keyCode; //prev .Keyboard.Vk + // Scan Code here, was 0 + down.Data.Keyboard.Scan = (ushort)MapVirtualKey((UInt16)keyCode, 0); + down.Data.Keyboard.Flags = keyFlag; + down.Data.Keyboard.Time = 0; + down.Data.Keyboard.ExtraInfo = IntPtr.Zero; + + INPUT[] inputList = new INPUT[1]; + inputList[0] = down; + + var numberOfSuccessfulSimulatedInputs = SendInput(1, + inputList, Marshal.SizeOf(typeof(INPUT))); + if (numberOfSuccessfulSimulatedInputs == 0) + throw new Exception( + string.Format("The key press simulation for {0} was not successful.", + keyCode)); + return this; + } + + + /// + /// Calls the Win32 SendInput method ... + /// + /// The VirtualKeyCode to press and hold + public IKeyboardSimulator CITRIXKeyDown(VirtualKeyCode keyCode) //prev public static void + { + return CITRIXKey(keyCode); + } + + /// + /// Calls the Win32 SendInput method ... + /// + /// The VirtualKeyCode to release + public IKeyboardSimulator CITRIXKeyUp(VirtualKeyCode keyCode) //prev public static void + { + return CITRIXKey(keyCode, (UInt32)KeyboardFlag.KeyUp); + } } -} \ No newline at end of file +}