Click here to Skip to main content
15,881,173 members
Articles / Desktop Programming / Windows Forms

InputManager library - Track user input and simulate input (mouse and keyboard)

Rate me:
Please Sign up or sign in to vote.
4.98/5 (39 votes)
13 Oct 2010CPOL5 min read 290.1K   24K   148   128
A library that contains classes to simulate user input and track user input (mouse and keyboard), in C# and VB.NET.

Introduction

The InputManager library allows you to take control over the whole user common input. From tracking (hooking) user input to simulating user input. It allows you to send and receive global mouse and keyboard messages, in one easy to use library. It supports DirectX input simulation, which means you can send mouse or keyboard messages to any DirectX game you want, and the game will register it correctly.

With this library, you can create a complete macro recording application; it's well documented, and can be easily used with any application.

Background

Starting my way to create my own Macro Recording application, today known as Mouse Recorder Pro, I needed to find a way to register mouse and keyboard messages and track them down. After a number of version updates for Mouse Recorder Pro, and after improving my own coding skills, I made this library to help others.

The hook classes in this library were not written by me (but they were modified by me) to be honest. I don't remember the person who helped with it, but if I am able to track him, I will update this article.

The other classes were written by me, with some research and a lot of reading. The main problem I had was to be able to register user input in DirectX games, which I managed to accomplish afterwards.

The Concept (Or, How it Works)

The library was written in VB.NET, and tested on many systems (as part of its use in the Mouse Recorder Pro commercial application).

The keyboard and mouse messages are being sent with the SendInput API, which is a bit more flexible than other APIs. With the SendInput API, your application can send mouse and keyboard messages in a low level (as DirectX is). This allows you to register those messages in any DirectX game.

The mouse and keyboard hook classes allow you to track the user input. The classes use the SetWindowsHookEx API. This API "binds" any new mouse or keyboard message to a specific method in the hook classes. Every time a new message arrives, Windows calls that method. Within that method, an event is raised to inform you that a new input message has arrived.

Screenshot.jpg

Mouse Recorder Pro 2 - it uses the InputManager library!

Using the code

To use this library, we first need to add a reference for it in our project; download the InputManager library from the link above, and extract it. Now do the following:

  1. Open up your project.
  2. Right click on "References" and "Add Reference".
  3. Select the "Browse" tab and select the extracted "InputManager.dll".
  4. Accept all dialogs.
  5. To make this project work in Debug mode, double click on Properties, go to "Debug", and uncheck "Enable the Visual Studio hosting process".

I wasn't able to use the class hook classes (used for tracking) with .NET Framework 4, so if you are using .NET Framework 4, please change the target framework to 3.5 or any framework below by going to the project properties and selecting a different version of the .NET Framework.

Now, let's add the "using" statement to make it a bit easier for coding. Add the following using statement:

C#
using InputManager;

OK, let's get to know how to use this library.

Tracking User Mouse and Keyboard Messages

InputManagerHookExample.jpg

Download this hook example at the top

To track the user mouse and keyboard messages, we need to set up a hook. How do we do that? With InputManager, it's pretty easy.

To track user keyboard messages, in your Form_Load event handling method, add the following code:

C#
//Adding keyboard event handlers and installing the hook
KeyboardHook.KeyDown += new KeyboardHook.KeyDownEventHandler(KeyboardHook_KeyDown);
KeyboardHook.KeyUp += new KeyboardHook.KeyUpEventHandler(KeyboardHook_KeyUp);
KeyboardHook.InstallHook();

The first two lines allow us to track the keyboard messages. This is done by two methods we will create to handle those events. The third line tells the InputManager library to set up a hook and start reading the keyboard messages.

Now let's add the two methods we talked about earlier:

C#
void KeyboardHook_KeyUp(int vkCode)
{
    //Everytime the users releases a certain key up,
    //your application will go to this line
    //Use the vKCode argument to determine which key has been released
}

void KeyboardHook_KeyDown(int vkCode)
{
    //Everytime the users holds a certain key down,
    //your application will go to this line
    //Use the vKCode argument to determine which key is held down
}

To convert those keys to a string instead of a virtual key code, use this simple technique:

C#
string keyString = ((Keys)vkCode).ToString();
//Using the Keys Enum ToString method for translating

To track user mouse messages, in your Form_Load event handling method, add the following code:

C#
//Adding mouse event handlers and installing the hook
MouseHook.MouseEvent += new MouseHook.MouseEventEventHandler(MouseHook_MouseEvent);
MouseHook.MouseMove += new MouseHook.MouseMoveEventHandler(MouseHook_MouseMove);
MouseHook.WheelEvent += new MouseHook.WheelEventEventHandler(MouseHook_WheelEvent);
MouseHook.InstallHook();

The first three lines tell the InputManager library to add event handlers for each mouse message type (mouse button events, mouse move event, and wheel scrolled event). We will add the methods that handle those messages below. The fourth line tells the InputManager class to install the hook and start receiving the messages.

Let's add the methods that handle those messages:

C#
void MouseHook_WheelEvent(MouseHook.MouseWheelEvents wEvent)
{
    //Event time the wheel was scrolled the application will go to this line
    //Using the wEvent argument we can detect 
    //if the mouse was scrolled forward or backward
}

void MouseHook_MouseMove(MouseHook.POINT ptLocat)
{
    //Everytime the mouse moved, the application will go to this line
    //Using the ptLocat arguments you can detect 
    //which point the mouse cursor moved to
}

void MouseHook_MouseEvent(MouseHook.MouseEvents mEvent)
{
    //Everytime a mouse button changed it's state 
    //(from up to down or down to up) the application will go to this line
    //Using the mEvent argument we can detect which button changed it's state
}

To detect if the wheel was scrolled up or down within the MouseHook_WheelEvent method, we use the MouseHook.MouseWheelEvents enum:

C#
string scrollDirection;
if (wEvent == MouseHook.MouseWheelEvents.ScrollDown)
    scrollDirection = "scrolled down";
else scrollDirection = "scrolled up";

To detect the position (X and Y) of the mouse every time it moves, we use the ptLocat argument within the MouseHook_MouseMove method:

C#
textBox1.Text = "The mouse cursor moved to: " + ptLocat.x + ", " + ptLocat.y;
//Updating a textbox text to the current mouse position

To detect which button changed its state, we use the the mEvent argument within the MouseHook_MouseEvent method:

C#
textBox1.Text = "Mouse button changed state to: " + mEvent.ToString();
//Updates the textbox to show which button changed it's state last time

You can use the switch statement to handle each mouse button/state change differently:

C#
switch (mEvent)
{
   case MouseHook.MouseEvents.LeftDown:
       //Left button is down, do something here
       break;

   case MouseHook.MouseEvents.LeftUp:
        //Left button is up, do something here
         break;
}

Sending Mouse and Keyboard Messages (With DirectX Support)

To send keyboard messages (key strokes), we use the Keyboard class in the InputManager library.

To send key down/key up messages, we use the Keyboard.KeyDown or Keyboard.KeyUp methods. An example of writing "hello" in a textbox:

C#
ExampleText.Focus(); //Sets focus on the example text

//Writing Hello with keys sending
Keyboard.KeyDown(Keys.H);
Keyboard.KeyUp(Keys.H);

Keyboard.KeyDown(Keys.E);
Keyboard.KeyUp(Keys.E);

Keyboard.KeyDown(Keys.L);
Keyboard.KeyUp(Keys.L);

Keyboard.KeyDown(Keys.L);
Keyboard.KeyUp(Keys.L);

Keyboard.KeyDown(Keys.O);
Keyboard.KeyUp(Keys.O);

To send shortcut keys, we use the Keyboard.ShortcutKeys method, with an array of Keys:

C#
ExampleText.Focus(); //Sets focus on the example textbox

//Sends Shift + Control + Left to select a word
Keys[] keys = new Keys[] { Keys.RShiftKey, Keys.RControlKey, Keys.Left };
Keyboard.ShortcutKeys(keys);

To send mouse messages (mouse key strokes, mouse movements, wheel scroll), we use the Mouse class in the InputManager library.

To move the mouse to a certain location (in screen coordinates), we use the Mouse.Move method:

C#
Mouse.Move(Point.X, Point.Y);
//Moves the mouse to a certain location on the screen

To perform a mouse click message, we use the Mouse.PressButton method:

C#
Mouse.PressButton(Mouse.MouseKeys.Left); //Performing a left click

To send mouse button down or up messages, we use the Mouse.ButtonDown/Mouse.ButtonUp methods:

C#
Mouse.ButtonDown(Mouse.MouseKeys.Left); //Holding the left mouse down
Mouse.ButtonUp(Mouse.MouseKeys.Left); //Releasing the left mouse button

To scroll up or down, we use the Mouse.Scroll method:

C#
Mouse.Scroll(Mouse.ScrollDirection.Down); //Scroling down
Mouse.Scroll(Mouse.ScrollDirection.Up); //Scrolling up

InputManagerSendingMessagesExample.jpg

Download this input simulating example at the top

Points of Interest

Writing this library (parts of it) was really fun and a bit challenging. There are other ways of sending mouse and keyboard messages with different APIs which don't support DirectX and are easier to use, but I wanted to simplify it and create my own library, so you don't even need to know what API means. With this library, you can send and receive input messages easily!

History

  • 13.10.2010: Added an explanation on how the library works (the concept behind it).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Nemex Studios
Israel Israel
My name is Shay and I'm 21 years old.
At age 16 I created Nemex Studios (www.byshynet.com), an application development "company" (not official).
I'm the developer of "Mouse Recorder Pro", "Mouse Shaker" and many other applications, developed to help the community.

Comments and Discussions

 
AnswerHooking in .NET 4 [modified] Pin
Charl Pohlmann20-Sep-11 3:28
Charl Pohlmann20-Sep-11 3:28 
GeneralRe: Hooking in .NET 4 [modified] Pin
shynet22-Sep-11 3:43
shynet22-Sep-11 3:43 
GeneralRe: Hooking in .NET 4 [modified] Pin
Larissa Schön24-Feb-12 9:43
professionalLarissa Schön24-Feb-12 9:43 
GeneralRe: Hooking in .NET 4 [modified] Pin
shynet24-Feb-12 23:56
shynet24-Feb-12 23:56 
GeneralRe: Hooking in .NET 4 [modified] Pin
StormyC9-May-13 22:30
StormyC9-May-13 22:30 
GeneralAlso need to fix mouse hook! Pin
DanielBruno13-Aug-13 3:42
DanielBruno13-Aug-13 3:42 
GeneralRe: Also need to fix mouse hook! Pin
shynet13-Aug-13 9:04
shynet13-Aug-13 9:04 
QuestionC# version of InputManager Pin
Victuar24-Aug-11 20:06
Victuar24-Aug-11 20:06 
Here is version of InputManager in C#:
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;

namespace InputManager
{
  /// <summary>
  /// Provide methods to send keyboard input that also works in DirectX games.
  /// </summary>
  public class Keyboard
  {
    #region API Declaring
    #region SendInput
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int SendInput(
        int cInputs,
        ref INPUT pInputs,
        int cbSize);
    private struct INPUT
    {
      public uint dwType;
      public MOUSEKEYBDHARDWAREINPUT mkhi;
    }
    private struct KEYBDINPUT
    {
      public short wVk;
      public short wScan;
      public uint dwFlags;
      public int time;
      public IntPtr dwExtraInfo;
    }
    private struct HARDWAREINPUT
    {
      public int uMsg;
      public short wParamL;
      public short wParamH;
    }
    [StructLayout(LayoutKind.Explicit)]
    private struct MOUSEKEYBDHARDWAREINPUT
    {
      [FieldOffset(0)]
      public MOUSEINPUT mi;
      [FieldOffset(0)]
      public KEYBDINPUT ki;
      [FieldOffset(0)]
      public HARDWAREINPUT hi;
    }
    private struct MOUSEINPUT
    {
      public int dx;
      public int dy;
      public int mouseData;
      public uint dwFlags;
      public int time;
      public IntPtr dwExtraInfo;
    }
    const UInt32 INPUT_MOUSE = 0;
    const int INPUT_KEYBOARD = 1;
    const int INPUT_HARDWARE = 2;
    const UInt32 KEYEVENTF_EXTENDEDKEY = 0x01;
    const UInt32 KEYEVENTF_KEYUP = 0x02;
    const UInt32 KEYEVENTF_UNICODE = 0x04;
    const UInt32 KEYEVENTF_SCANCODE = 0x08;
    const UInt32 XBUTTON1 = 0x01;
    const UInt32 XBUTTON2 = 0x02;
    const UInt32 MOUSEEVENTF_MOVE = 0x01;
    const UInt32 MOUSEEVENTF_LEFTDOWN = 0x02;
    const UInt32 MOUSEEVENTF_LEFTUP = 0x04;
    const UInt32 MOUSEEVENTF_RIGHTDOWN = 0x08;
    const UInt32 MOUSEEVENTF_RIGHTUP = 0x10;
    const UInt32 MOUSEEVENTF_MIDDLEDOWN = 0x20;
    const UInt32 MOUSEEVENTF_MIDDLEUP = 0x40;
    const UInt32 MOUSEEVENTF_XDOWN = 0x80;
    const UInt32 MOUSEEVENTF_XUP = 0x100;
    const UInt32 MOUSEEVENTF_WHEEL = 0x800;
    const UInt32 MOUSEEVENTF_VIRTUALDESK = 0x4000;
    const UInt32 MOUSEEVENTF_ABSOLUTE = 0x8000;
    #endregion SendInput

    [DllImport("user32.dll", CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern UInt32 MapVirtualKey(UInt32 uCode, MapVirtualKeyMapTypes uMapType);

    [DllImport("user32.dll", CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern UInt32 MapVirtualKeyEx(UInt32 uCode, MapVirtualKeyMapTypes uMapType, IntPtr dwhkl);

    [DllImport("user32.dll", CharSet = CharSet.Auto,
    CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern IntPtr GetKeyboardLayout(uint idThread);

    /// <summary>The set of valid MapTypes used in MapVirtualKey
    /// </summary>
    /// <remarks></remarks>
    public enum MapVirtualKeyMapTypes : uint
    {
      /// <summary>uCode is a virtual-key code and is translated into a scan code.
      /// If it is a virtual-key code that does not distinguish between left- and
      /// right-hand keys, the left-hand scan code is returned.
      /// If there is no translation, the function returns 0.
      /// </summary>
      /// <remarks></remarks>
      MAPVK_VK_TO_VSC = 0x00,

      /// <summary>uCode is a scan code and is translated into a virtual-key code that
      /// does not distinguish between left- and right-hand keys. If there is no
      /// translation, the function returns 0.
      /// </summary>
      /// <remarks></remarks>
      MAPVK_VSC_TO_VK = 0x01,

      /// <summary>uCode is a virtual-key code and is translated into an unshifted
      /// character value in the low-order word of the return value. Dead keys (diacritics)
      /// are indicated by setting the top bit of the return value. If there is no
      /// translation, the function returns 0.
      /// </summary>
      /// <remarks></remarks>
      MAPVK_VK_TO_CHAR = 0x02,

      /// <summary>Windows NT/2000/XP: uCode is a scan code and is translated into a
      /// virtual-key code that distinguishes between left- and right-hand keys. If
      /// there is no translation, the function returns 0.
      /// </summary>
      /// <remarks></remarks>
      MAPVK_VSC_TO_VK_EX = 0x03,

      /// <summary>Not currently documented
      /// </summary>
      /// <remarks></remarks>
      MAPVK_VK_TO_VSC_EX = 0x04,
    } ///Enum
    #endregion API Declaring

    private static ScanKey GetScanKey(Keys VKey)
    {
      uint ScanCode = MapVirtualKey((uint)VKey, MapVirtualKeyMapTypes.MAPVK_VK_TO_VSC);
      bool Extended = (VKey == Keys.RMenu) || (VKey == Keys.RControlKey) || (VKey == Keys.Left) || (VKey == Keys.Right) || (VKey == Keys.Up) || (VKey == Keys.Down) || (VKey == Keys.Home) || (VKey == Keys.Delete) || (VKey == Keys.PageUp) || (VKey == Keys.PageDown) || (VKey == Keys.End) || (VKey == Keys.Insert) || (VKey == Keys.NumLock) || (VKey == Keys.PrintScreen) || (VKey == Keys.Divide);
      return new ScanKey(ScanCode, Extended);
    }
    private struct ScanKey
    {
      public uint ScanCode;
      public bool Extended;
      public ScanKey(uint sCode, Boolean ex/* = false*/)
      {
        ScanCode = sCode;
        Extended = ex;
      }
    }
    /// <summary>
    /// Sends shortcut keys (key down and up) signals.
    /// </summary>
    /// <param name="kCode">The array of keys to send as a shortcut.</param>
    /// <param name="Delay">The delay in milliseconds between the key down and up events.</param>
    /// <remarks></remarks>
    public static void ShortcutKeys(Keys[] kCode, int Delay /*= 0*/)
    {
      KeyPressStruct KeysPress = new KeyPressStruct(kCode, Delay);
      Thread t = new Thread(new ParameterizedThreadStart(KeyPressThread));
      t.Start(KeysPress);
    }
    /// <summary>
    /// Sends a key down signal.
    /// </summary>
    /// <param name="kCode">The virtual keycode to send.</param>
    /// <remarks></remarks>
    public static void KeyDown(Keys kCode)
    {
      ScanKey sKey = GetScanKey(kCode);
      INPUT input = new INPUT();
      input.dwType = INPUT_KEYBOARD;
      input.mkhi.ki = new KEYBDINPUT();
      input.mkhi.ki.wScan = (short)sKey.ScanCode;
      input.mkhi.ki.dwExtraInfo = IntPtr.Zero;
      input.mkhi.ki.dwFlags = KEYEVENTF_SCANCODE | (sKey.Extended ? KEYEVENTF_EXTENDEDKEY : 0);
      int cbSize = Marshal.SizeOf(typeof(INPUT));
      SendInput(1, ref input, cbSize);
    }
    /// <summary>
    /// Sends a key up signal.
    /// </summary>
    /// <param name="kCode">The virtual keycode to send.</param>
    /// <remarks></remarks>
    public static void KeyUp(Keys kCode)
    {
      ScanKey sKey = GetScanKey(kCode);
      INPUT input = new INPUT();
      input.dwType = INPUT_KEYBOARD;
      input.mkhi.ki = new KEYBDINPUT();
      input.mkhi.ki.wScan = (short)sKey.ScanCode;
      input.mkhi.ki.dwExtraInfo = IntPtr.Zero;
      input.mkhi.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP | (sKey.Extended ? KEYEVENTF_EXTENDEDKEY : 0);
      int cbSize = Marshal.SizeOf(typeof(INPUT));
      SendInput(1, ref input, cbSize);
    }
    /// <summary>
    /// Sends a key press signal (key down and up).
    /// </summary>
    /// <param name="kCode">The virtual keycode to send.</param>
    /// <param name="Delay">The delay to set between the key down and up commands.</param>
    /// <remarks></remarks>
    public static void KeyPress(Keys kCode, int Delay /*= 0*/)
    {
      Keys[] SendKeys = new Keys[] { kCode };
      KeyPressStruct KeysPress = new KeyPressStruct(SendKeys, Delay);
      Thread t = new Thread(new ParameterizedThreadStart(KeyPressThread));
      t.Start(KeysPress);
    }
    private static void KeyPressThread(object obj)
    {
      KeyPressStruct KeysP = (KeyPressStruct)obj;
      foreach (Keys k in KeysP.Keys)
      {
        KeyDown(k);
      }
      if (KeysP.Delay > 0) { Thread.Sleep(KeysP.Delay); }
      foreach (Keys k in KeysP.Keys)
      {
        KeyUp(k);
      }
    }
    private struct KeyPressStruct
    {
      public Keys[] Keys;
      public int Delay;
      public KeyPressStruct(Keys[] KeysToPress, int DelayTime /*= 0*/)
      {
        Keys = KeysToPress;
        Delay = DelayTime;
      }
    }
  }
  /// <summary>
  /// Provides methods to send keyboard input. The keys are being sent virtually and cannot be used with DirectX.
  /// </summary>
  /// <remarks></remarks>
  public class VirtualKeyboard
  {
    #region "API Declaring"
    [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Unicode, EntryPoint = "keybd_event",
           ExactSpelling = true, SetLastError = true)]
    public static extern bool keybd_event(UInt32 bVk, UInt32 bScan, UInt32 dwFlags, UInt32 dwExtraInfo);
    const UInt32 KEYEVENTF_EXTENDEDKEY = 0x01;
    const UInt32 KEYEVENTF_KEYUP = 0x02;
    #endregion

    /// <summary>
    /// Sends shortcut keys (key down and up) signals.
    /// </summary>
    /// <param name="kCode">The array of keys to send as a shortcut.</param>
    /// <param name="Delay">The delay in milliseconds between the key down and up events.</param>
    /// <remarks></remarks>
    public static void ShortcutKeys(Keys[] kCode, int Delay /*= 0*/)
    {
      KeyPressStruct KeyPress = new KeyPressStruct(kCode, Delay);
      Thread t = new Thread(new ParameterizedThreadStart(KeyPressThread));
      t.Start(KeyPress);
    }
    /// <summary>
    /// Sends a key down signal.
    /// </summary>
    /// <param name="kCode">The virtual keycode to send.</param>
    /// <remarks></remarks>
    public static void KeyDown(Keys kCode)
    {
      keybd_event((UInt32)kCode, 0, 0, 0);
    }
    /// <summary>
    /// Sends a key up signal.
    /// </summary>
    /// <param name="kCode">The virtual keycode to send.</param>
    /// <remarks></remarks>
    public static void KeyUp(Keys kCode)
    {
      keybd_event((UInt32)kCode, 0, KEYEVENTF_KEYUP, 0);
    }
    /// <summary>
    /// Sends a key press signal (key down and up).
    /// </summary>
    /// <param name="kCode">The virtual key code to send.</param>
    /// <param name="Delay">The delay to set between the key down and up commands.</param>
    /// <remarks></remarks>
    public static void KeyPress(Keys kCode, int Delay /*= 0*/)
    {
      Keys[] SendKeys = new Keys[] { kCode };
      KeyPressStruct KeyPress = new KeyPressStruct(SendKeys, Delay);
      Thread t = new Thread(new ParameterizedThreadStart(KeyPressThread));
      t.Start(KeyPress);
    }
    public static void KeyPressThread(object obj)
    {
      KeyPressStruct KeysP = (KeyPressStruct)obj;
      foreach (Keys k in KeysP.Keys)
      {
        KeyDown(k);
      }
      if (KeysP.Delay > 0) Thread.Sleep(KeysP.Delay);
      foreach (Keys k in KeysP.Keys)
      {
        KeyUp(k);
      }
    }
    private struct KeyPressStruct
    {
      public Keys[] Keys;
      public int Delay;
      public KeyPressStruct(Keys[] KeysToPress, int DelayTime /*= 0*/)
      {
        Keys = KeysToPress;
        Delay = DelayTime;
      }
    }
  }
  /// <summary>
  /// Provides methods to send mouse input that also works in DirectX games.
  /// </summary>
  /// <remarks></remarks>
  public class Mouse
  {
    #region "APIs"
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int GetSystemMetrics(int smIndex);
    private const int SM_SWAPBUTTON = 23;
    #region "SendInput"
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int SendInput(int cInputs, ref INPUT pInputs, int cbSize);
    private struct INPUT
    {
      public uint dwType;
      public MOUSEKEYBDHARDWAREINPUT mkhi;
    }
    private struct KEYBDINPUT
    {
      public short wVk;
      public short wScan;
      public int dwFlags;
      public int time;
      public IntPtr dwExtraInfo;
    }
    private struct HARDWAREINPUT
    {
      public int uMsg;
      public short wParamL;
      public short wParamH;
    }
    [StructLayout(LayoutKind.Explicit)]
    private struct MOUSEKEYBDHARDWAREINPUT
    {
      [FieldOffset(0)]
      public MOUSEINPUT mi;
      [FieldOffset(0)]
      public KEYBDINPUT ki;
      [FieldOffset(0)]
      public HARDWAREINPUT hi;
    }
    private struct MOUSEINPUT
    {
      public int dx;
      public int dy;
      public int mouseData;
      public uint dwFlags;
      public int time;
      public IntPtr dwExtraInfo;
    }

    const UInt32 INPUT_MOUSE = 0;
    const int INPUT_KEYBOARD = 1;
    const int INPUT_HARDWARE = 2;
    const UInt32 KEYEVENTF_EXTENDEDKEY = 0x1;
    const UInt32 KEYEVENTF_KEYUP = 0x2;
    const UInt32 KEYEVENTF_UNICODE = 0x4;
    const UInt32 KEYEVENTF_SCANCODE = 0x8;
    const UInt32 XBUTTON1 = 0x1;
    const UInt32 XBUTTON2 = 0x2;
    const UInt32 MOUSEEVENTF_MOVE = 0x1;
    const UInt32 MOUSEEVENTF_LEFTDOWN = 0x2;
    const UInt32 MOUSEEVENTF_LEFTUP = 0x4;
    const UInt32 MOUSEEVENTF_RIGHTDOWN = 0x8;
    const UInt32 MOUSEEVENTF_RIGHTUP = 0x10;
    const UInt32 MOUSEEVENTF_MIDDLEDOWN = 0x20;
    const UInt32 MOUSEEVENTF_MIDDLEUP = 0x40;
    const UInt32 MOUSEEVENTF_XDOWN = 0x80;
    const UInt32 MOUSEEVENTF_XUP = 0x100;
    const UInt32 MOUSEEVENTF_WHEEL = 0x800;
    const UInt32 MOUSEEVENTF_VIRTUALDESK = 0x4000;
    const UInt32 MOUSEEVENTF_ABSOLUTE = 0x8000;
    #endregion
    #endregion

    public enum MouseButtons
    {
      LeftDown = 0x2,
      LeftUp = 0x4,
      RightDown = 0x8,
      RightUp = 0x10,
      MiddleDown = 0x20,
      MiddleUp = 0x40,
      Absolute = 0x8000,
      Wheel = 0x800,
    }
    public enum MouseKeys
    {
      Left = -1,
      Right = -2,
      Middle = -3,
    }
    public enum ScrollDirection
    {
      Up = 120,
      Down = -120,
    }

    /// <summary>
    /// Returns true if mouse buttons are swapped
    /// </summary>
    /// <value></value>
    /// <returns></returns>
    /// <remarks></remarks>
    public static bool IsLeftHanded
    {
      get
      {
        try
        {
          return (GetSystemMetrics(SM_SWAPBUTTON) == 1);
        }
        catch (Exception ex)
        {
          return false;
        }
      }
    }
    /// <summary>
    /// Sends a mouse button signal. To send a scroll use the Scroll method.
    /// </summary>
    /// <param name="mButton">The button to send.</param>
    /// <remarks></remarks>
    public static void SendButton(MouseButtons mButton)
    {
      INPUT input = new INPUT();
      input.dwType = INPUT_MOUSE;
      input.mkhi.mi = new MOUSEINPUT();
      input.mkhi.mi.dwExtraInfo = IntPtr.Zero;
      input.mkhi.mi.dwFlags = (uint)mButton;
      input.mkhi.mi.dx = 0;
      input.mkhi.mi.dy = 0;
      int cbSize = Marshal.SizeOf(typeof(INPUT));
      SendInput(1, ref input, cbSize);
    }
    /// <summary>
    /// Sends a mouse press signal (down and up).
    /// </summary>
    /// <param name="mKey">The key to press.</param>
    /// <param name="Delay">The delay to set between the events.</param>
    /// <remarks></remarks>
    public static void PressButton(MouseKeys mKey, int Delay /*= 0*/)
    {
      ButtonDown(mKey);
      if (Delay > 0) System.Threading.Thread.Sleep(Delay);
      ButtonUp(mKey);
    }
    /// <summary>
    /// Send a mouse button down signal.
    /// </summary>
    /// <param name="mKey">The mouse key to send as mouse button down.</param>
    /// <remarks></remarks>
    public static void ButtonDown(MouseKeys mKey)
    {
      switch (mKey)
      {
        case MouseKeys.Left:
          SendButton(MouseButtons.LeftDown);
          return;
        case MouseKeys.Right:
          SendButton(MouseButtons.RightDown);
          return;
        case MouseKeys.Middle:
          SendButton(MouseButtons.MiddleDown);
          return;
      }
    }
    /// <summary>
    /// Send a mouse button up signal.
    /// </summary>
    /// <param name="mKey">The mouse key to send as mouse button up.</param>
    /// <remarks></remarks>
    public static void ButtonUp(MouseKeys mKey)
    {
      switch (mKey)
      {
        case MouseKeys.Left:
          SendButton(MouseButtons.LeftUp);
          return;
        case MouseKeys.Right:
          SendButton(MouseButtons.RightUp);
          return;
        case MouseKeys.Middle:
          SendButton(MouseButtons.MiddleUp);
          return;
      }
    }
    /// <summary>
    /// Moves the mouse to a certain location on the screen.
    /// </summary>
    /// <param name="X">The x location to move the mouse.</param>
    /// <param name="Y">The y location to move the mouse</param>
    /// <remarks></remarks>
    public static void Move(int X, int Y)
    {
      INPUT input = new INPUT();
      input.dwType = INPUT_MOUSE;
      input.mkhi.mi = new MOUSEINPUT();
      input.mkhi.mi.dwExtraInfo = IntPtr.Zero;
      input.mkhi.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
      input.mkhi.mi.dx = X * (65535 / Screen.PrimaryScreen.Bounds.Width);
      input.mkhi.mi.dy = Y * (65535 / Screen.PrimaryScreen.Bounds.Height);
      int cbSize = Marshal.SizeOf(typeof(INPUT));
      SendInput(1, ref input, cbSize);
    }
    /// <summary>
    /// Moves the mouse to a location relative to the current one.
    /// </summary>
    /// <param name="X">The amount of pixels to move the mouse on the x axis.</param>
    /// <param name="Y">The amount of pixels to move the mouse on the y axis.</param>
    /// <remarks></remarks>
    public static void MoveRelative(int X, int Y)
    {
      INPUT input = new INPUT();
      input.dwType = INPUT_MOUSE;
      input.mkhi.mi = new MOUSEINPUT();
      input.mkhi.mi.dwExtraInfo = IntPtr.Zero;
      input.mkhi.mi.dwFlags = MOUSEEVENTF_MOVE;
      input.mkhi.mi.dx = X;
      input.mkhi.mi.dy = Y;
      int cbSize = Marshal.SizeOf(typeof(INPUT));
      SendInput(1, ref input, cbSize);
    }
    /// <summary>
    /// Sends a scroll signal with a specific direction to scroll.
    /// </summary>
    /// <param name="Direction">The direction to scroll.</param>
    /// <remarks></remarks>
    public static void Scroll(ScrollDirection Direction)
    {
      INPUT input = new INPUT();
      input.dwType = INPUT_MOUSE;
      input.mkhi.mi = new MOUSEINPUT();
      input.mkhi.mi.dwExtraInfo = IntPtr.Zero;
      input.mkhi.mi.dwFlags = (uint)MouseButtons.Wheel;
      input.mkhi.mi.mouseData = (int)Direction;
      input.mkhi.mi.dx = 0;
      input.mkhi.mi.dy = 0;
      int cbSize = Marshal.SizeOf(typeof(INPUT));
      SendInput(1, ref input, cbSize);
    }
  }
  /// <summary>
  /// Creates a low level keyboard hook.
  /// </summary>
  /// <remarks></remarks>
  public class KeyboardHook
  {
    #region "Constants and API's Declaring"
    //This is Constants
    private const int HC_ACTION = 0;
    private const int WH_KEYBOARD_LL = 13;
    private const uint WM_KEYDOWN = 0x100;
    private const uint WM_KEYUP = 0x101;
    private const uint WM_SYSKEYDOWN = 0x104;
    private const uint WM_SYSKEYUP = 0x105;
    private const uint WM_KEYLAST = 0x108;
    //Key press events
    public struct KBDLLHOOKSTRUCT
    {
      public int vkCode;
      public int scancode;
      public uint flags;
      public int time;
      public int dwExtraInfo;
    }
    //API Functions
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true, EntryPoint = "SetWindowsHookExA")]
    private static extern int SetWindowsHookEx(int idHook,
    KeyboardProcDelegate lpfn,
    int hmod,
    int dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int CallNextHookEx(int hHook, int nCode, uint wParam, KBDLLHOOKSTRUCT lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int UnhookWindowsHookEx(int hHook);

    // Keyboard Delegates
    public delegate int KeyboardProcDelegate(int nCode, uint wParam, ref KBDLLHOOKSTRUCT lParam);
    public delegate void KeyDownEventHandler(int nCode);
    public delegate void KeyUpEventHandler(int nCode);

    // KeyPress events
    public static event KeyDownEventHandler KeyDown/*(int vkCode)*/;
    public static event KeyUpEventHandler KeyUp/*(int vkCode)*/;

    //The identifyer for our KeyHook
    private static int KeyHook;
    //KeyHookDelegate
    private static KeyboardProcDelegate KeyHookDelegate;
    #endregion

    private static int KeyboardProc(int nCode, uint wParam, ref KBDLLHOOKSTRUCT lParam)
    {
      //If it's a keyboard state event...
      if (nCode == HC_ACTION)
      {
        switch (wParam)
        {
          case WM_KEYDOWN:
          case WM_SYSKEYDOWN: //If it's a keydown event...
            if (KeyDown != null) KeyDown(lParam.vkCode);
            break;
          case WM_KEYUP:
          case WM_SYSKEYUP: //If it's a keyup event... 
            if (KeyUp != null) KeyUp(lParam.vkCode);
            break;
        }
      }
      //Next
      return CallNextHookEx(KeyHook, nCode, wParam, lParam);
    }
    /// <summary>
    /// Installs low level keyboard hook. This hook raises events every time a keyboard event occured.
    /// </summary>
    /// <remarks></remarks>
    public static void InstallHook()
    {
      KeyHookDelegate = new KeyboardProcDelegate(KeyboardProc);
      KeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyHookDelegate, Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
    }
    /// <summary>
    /// Uninstalls the low level keyboard hook. Hooks events are stopped from being raised.
    /// </summary>
    /// <remarks></remarks>
    public static void UninstallHook()
    {
      UnhookWindowsHookEx(KeyHook);
    }

    ~KeyboardHook()
    {
      //On close it UnHooks the Hook
      UnhookWindowsHookEx(KeyHook);
    }
  }
  /// <summary>
  /// Creates a low level mouse hook.
  /// </summary>
  /// <remarks></remarks>
  public class MouseHook
  {
    #region "Constants and API's Declaring"
    public enum MouseEvents
    {
      LeftDown = 0x201,
      LeftUp = 0x202,
      LeftDoubleClick = 0x203,
      RightDown = 0x204,
      RightUp = 0x205,
      RightDoubleClick = 0x206,
      MiddleDown = 0x207,
      MiddleUp = 0x208,
      MiddleDoubleClick = 0x209,
      MouseScroll = 0x20A,
    }
    public enum MouseWheelEvents
    {
      ScrollUp = 7864320,
      ScrollDown = -7864320,
    }

    //Constants
    private const int HC_ACTION = 0;
    private const int WH_MOUSE_LL = 14;
    private const int WM_MOUSEMOVE = 0x200;
    private const int WM_LBUTTONDOWN = 0x201;
    private const int WM_LBUTTONUP = 0x202;
    private const int WM_LBUTTONDBLCLK = 0x203;
    private const int WM_RBUTTONDOWN = 0x204;
    private const int WM_RBUTTONUP = 0x205;
    private const int WM_RBUTTONDBLCLK = 0x206;
    private const int WM_MBUTTONDOWN = 0x207;
    private const int WM_MBUTTONUP = 0x208;
    private const int WM_MBUTTONDBLCLK = 0x209;
    private const int WM_MOUSEWHEEL = 0x20A;

    //Mouse Structures
    public struct POINT
    {
      public int x;
      public int y;
    }
    public struct MSLLHOOKSTRUCT
    {
      public POINT pt;
      public int mouseData;
      private uint flags;
      private int time;
      private uint dwExtraInfo;
    }

    //API Functions
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true, EntryPoint = "SetWindowsHookExA")]
    private static extern int SetWindowsHookEx(int idHook, MouseProcDelegate lpfn, int hmod, int dwThreadId);
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int CallNextHookEx(int hHook, int nCode, int wParam, ref MSLLHOOKSTRUCT lParam);
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private static extern int UnhookWindowsHookEx(int hHook);

    // Mouse Delegate
    public delegate int MouseProcDelegate(int nCode, int wParam, ref MSLLHOOKSTRUCT lParam);
    public delegate void MouseMoveEventHandler(POINT ptLocat);
    public delegate void MouseEventEventHandler(MouseEvents nComEventde);
    public delegate void WheelEventHandler(MouseWheelEvents wEvent);

    // Mouse events
    public static event MouseMoveEventHandler MouseMove;//(ByVal ptLocat As POINT)
    public static event MouseEventEventHandler MouseEvent;//(ByVal mEvent As MouseEvents)
    public static event WheelEventHandler WheelEvent;//(ByVal wEvent As MouseWheelEvents)

    //The identifyer for our MouseHook
    private static int MouseEventHook;
    //MouseHookDelegate
    private static MouseProcDelegate MouseHookDelegate;
    #endregion

    /// <summary>
    /// Installs low level mouse hook. This hook raises events every time a mouse event occured.
    /// </summary>
    /// <remarks></remarks>
    public static void InstallHook()
    {
      MouseHookDelegate = new MouseProcDelegate(MouseProc);
      MouseEventHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookDelegate, Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
    }
    /// <summary>
    /// Uninstalls the low level mouse hook. Hooks events are stopped from being raised.
    /// </summary>
    /// <remarks></remarks>
    public static void UninstallHook()
    {
      UnhookWindowsHookEx(MouseEventHook);
    }

    private static int MouseProc(int nCode, int wParam, ref MSLLHOOKSTRUCT lParam)
    {
      //If it is a Mouse event
      if (nCode == HC_ACTION)
      {
        if (wParam == WM_MOUSEMOVE)
        {
          //If the mouse is moving...
          if (MouseMove != null) MouseMove(lParam.pt);
        }
        else if (wParam == WM_LBUTTONDOWN || wParam == WM_LBUTTONUP || wParam == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDOWN || wParam == WM_RBUTTONUP || wParam == WM_RBUTTONDBLCLK || wParam == WM_MBUTTONDOWN || wParam == WM_MBUTTONUP || wParam == WM_MBUTTONDBLCLK)
        {
          //If a mouse button event happend...
          if (MouseEvent != null) MouseEvent((MouseEvents)wParam);
        }
        else if (wParam == WM_MOUSEWHEEL)
        {
          //If the wheel moved...
          if (WheelEvent != null) WheelEvent((MouseWheelEvents)lParam.mouseData);
        }
      }
      //Calls the next hook chain
      return CallNextHookEx(MouseEventHook, nCode, wParam, ref lParam);
    }
    ~MouseHook()
    {
      UnhookWindowsHookEx(MouseEventHook);
    }
  }
}

AnswerRe: C# version of InputManager Pin
MarkcusD200926-Aug-11 10:55
MarkcusD200926-Aug-11 10:55 
GeneralRe: C# version of InputManager Pin
shynet26-Aug-11 22:09
shynet26-Aug-11 22:09 
GeneralThis doesn't work well in DirectX Game Pin
chenxiemin19-Apr-11 15:32
chenxiemin19-Apr-11 15:32 
GeneralRe: This doesn't work well in DirectX Game Pin
shynet19-Apr-11 19:49
shynet19-Apr-11 19:49 
SuggestionRe: This doesn't work well in DirectX Game Pin
Member 807273113-Jul-11 4:02
Member 807273113-Jul-11 4:02 
GeneralRe: This doesn't work well in DirectX Game Pin
Member 855838215-Feb-12 1:00
Member 855838215-Feb-12 1:00 
GeneralUsing InputManager in VB.NET project Pin
neohimura3-Apr-11 21:46
neohimura3-Apr-11 21:46 
GeneralRe: Using InputManager in VB.NET project Pin
shynet4-Apr-11 5:21
shynet4-Apr-11 5:21 
GeneralRe: Using InputManager in VB.NET project Pin
Member 857637317-Jan-12 22:11
Member 857637317-Jan-12 22:11 
GeneralRe: Using InputManager in VB.NET project Pin
shynet19-Jan-12 3:56
shynet19-Jan-12 3:56 
GeneralRe: Using InputManager in VB.NET project Pin
Rohit Dubey from Hyderabad23-Jan-12 13:34
Rohit Dubey from Hyderabad23-Jan-12 13:34 
GeneralRe: Using InputManager in VB.NET project Pin
shynet24-Jan-12 5:33
shynet24-Jan-12 5:33 
QuestionHow to use this dll in MFC project Pin
bluespeed0013-Jan-11 1:22
bluespeed0013-Jan-11 1:22 
AnswerRe: How to use this dll in MFC project Pin
shynet6-Jan-11 8:37
shynet6-Jan-11 8:37 
GeneralCongratulations, Shay Pin
Marcelo Ricardo de Oliveira3-Dec-10 0:12
Marcelo Ricardo de Oliveira3-Dec-10 0:12 
GeneralRe: Congratulations, Shay Pin
shynet3-Dec-10 0:38
shynet3-Dec-10 0:38 
GeneralThank you for your program Pin
c1ick14-Nov-10 11:29
c1ick14-Nov-10 11:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.