Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions WindowsInput/IKeyboardSimulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ public interface IKeyboardSimulator
/// <param name="keyCode">The <see cref="VirtualKeyCode"/> for the key.</param>
IKeyboardSimulator KeyPress(VirtualKeyCode keyCode);

/// <summary>
/// Simulates the key press gesture for the specified key.
/// </summary>
/// <param name="keyCode">The <see cref="VirtualKeyCode"/> for the key.</param>
IKeyboardSimulator CITRIXKeyPress(VirtualKeyCode keyCode);


/// <summary>
/// Simulates the key press gesture for the specified key.
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to release</param>
IKeyboardSimulator CITRIXKeyUp(VirtualKeyCode keyCode);

/// <summary>
/// Simulates the key press gesture for the specified key.
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press and hold</param>
IKeyboardSimulator CITRIXKeyDown(VirtualKeyCode keyCode);

/// <summary>
/// Simulates a key press for each of the specified key codes in the order they are specified.
/// </summary>
Expand Down
102 changes: 101 additions & 1 deletion WindowsInput/KeyboardSimulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading;
using WindowsInput.Native;
using System.Runtime.InteropServices;

namespace WindowsInput
{
Expand Down Expand Up @@ -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);


/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press</param>
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;
}


/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press and hold</param>
/// <param name="keyFlag">a WindowsInput.Native.KeyboardFlag</param>
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;
}


/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to press and hold</param>
public IKeyboardSimulator CITRIXKeyDown(VirtualKeyCode keyCode) //prev public static void
{
return CITRIXKey(keyCode);
}

/// <summary>
/// Calls the Win32 SendInput method ...
/// </summary>
/// <param name="keyCode">The VirtualKeyCode to release</param>
public IKeyboardSimulator CITRIXKeyUp(VirtualKeyCode keyCode) //prev public static void
{
return CITRIXKey(keyCode, (UInt32)KeyboardFlag.KeyUp);
}
}
}
}