Click here to Skip to main content
15,502,919 members
Articles / Desktop Programming / Win32
Article
Posted 23 Jul 2008

Stats

491.7K views
26.8K downloads
322 bookmarked

Global Mouse and Keyboard Library

Rate me:
Please Sign up or sign in to vote.
4.94/5 (132 votes)
8 Aug 2008CPOL3 min read
Easy-to-use library with global mouse and keyboard hooks and simulators.

Image 1

Introduction

This article explains how to use the mouse and keyboard library that I have created. This library consists of two things: global mouse and keyboard hooks, and global mouse and keyboard simulators.

The global hooks contain a set of events that follow the .NET event model, so they should be very simple to use if you've done anything with events before.

The simulators will actually simulate mouse movements, clicks, keyboard presses, etc. This can be useful for macro recording (which is one of the sample projects), and of course, messing with your friends. :)

Background

I've found a lot of hook and simulator code out there, but a lot of it was not very organized, and a bit hard to use. The goal here is to make a very simple and easy-to-use library for mouse and keyboard operations not natively supported by .NET.

Global Hooks

This section will explain how to use the global hooks which can capture mouse and keyboard events from any application. These events are very similar to the ones that appear on Windows controls, so they should look familiar.

Using the mouse hook:

C#
// Create the mouse hook
MouseHook mouseHook = new MouseHook();

// Capture the events
mouseHook.MouseMove += new MouseEventHandler(mouseHook_MouseMove);
mouseHook.MouseDown += new MouseEventHandler(mouseHook_MouseDown);
mouseHook.MouseUp += new MouseEventHandler(mouseHook_MouseUp);
mouseHook.MouseWheel += new MouseEventHandler(mouseHook_MouseWheel); 

// Start watching for mouse events
mouseHook.Start();

...

// Stop watching (don't forget to do this before closing application!)
mouseHook.Stop();

Using the keyboard hook:

C#
// Create the keyboard hook
KeyboardHook keyboardHook = new KeyboardHook();

// Capture the events
keyboardHook.KeyDown += new KeyEventHandler(keyboardHook_KeyDown);
keyboardHook.KeyUp += new KeyEventHandler(keyboardHook_KeyUp);
keyboardHook.KeyPress += new KeyPressEventHandler(keyboardHook_KeyPress);

// Start watching for keyboard events
keyboardHook.Start();

...

// Stop watching (don't forget to do this before closing application!)
keyboardHook.Stop();

Note: When you are setting the events, Visual Studio will name and create a blank method for you. You only need to type this much on the event ...

C#
keyboardHook.KeyDown +=

...and then hit TAB two times. Visual Studio will finish the rest of the line, and will go out and create the blank method for you. This is a nice feature, and saves a lot of time; use it!

Simulators

This section will explain how to use the the mouse and keyboard simulators to simulate mouse clicks and keyboard key presses. Both the KeyboardSimulator and MouseSimulator classes are static, so they are pretty simple to use.

Simulating mouse events:

C#
// Press Left Mouse Button Down
MouseSimulator.MouseDown(MouseButton.Left);

// Let Left Mouse Button Up
MouseSimulator.MouseUp(MouseButton.Left);

// Press down and Let up Left Mouse Button
// (equivalent to two lines above)
MouseSimulator.Click(MouseButton.Left);

// Double click Left Mouse button
// (equivalent to two Click()s above)
MouseSimulator.DoubleClick(MouseButton.Left);

The code above is used to simulate pressing and letting up a certain mouse button. The one parameter is just an enumeration of the three possible mouse buttons: Left, Right, and Middle.

Moving the mouse position:

C#
// Move mouse cursor to Top Left of screen
MouseSimulator.X = 0;
MouseSimulator.Y = 0;

// Move the mouse cursor to the right by 20 pixels
MouseSimulator.X += 20;

The X and Y above are properties. You can use them to get the current position of the mouse cursor, or you can set them to move the mouse cursor to a new location.

Keyboard simulators:

C#
// Press the A Key Down
KeyboardSimulator.KeyDown(Keys.A);

// Let the A Key back up
KeyboardSimulator.KeyUp(Keys.A);

// Press A down, and let up (same as two above)
KeyboardSimulator.KeyPress(Keys.A);

The code above will simulate keyboard key presses. You can press a key down (first line), which doesn't let it up yet. The second line, KeyUp, will release a key that has been pressed down, the third line with do both steps in one shot.

I also included some standard keyboard shortcuts. These can all be done with the code above, but it simplifies it a bit, and makes the code a bit more readable and obvious.

C#
// Simulate (Ctrl + C) shortcut, which is copy for most applications
KeyboardSimulator.SimulateStandardShortcut(StandardShortcut.Copy);

// This does the same as above
KeyboardSimulator.KeyDown(Keys.Control);
KeyboardSimulator.KeyPress(Keys.C);
KeyboardSimulator.KeyUp(Keys.Control);

The code above does the exact same thing twice, except the first is a bit shorter and more obvious.

A Sample Application: Global Macro Recorder

Image 2

A macro recorder is a great example for this library, since we can use the hooks to record the macro, and the simulators to play back.

Check out the Macro project in the downloadable source code.

Future Additions / Revisions

I'm going to edit and add to this library over time as I get feedback. If you think something should be added, changed, or find a problem, please post in the comments section, and I'll do what I can. Thanks. :)

Revision History

  • 7/23/08: Released first version in three versions of .NET.
  • 7/28/08: Added the Application.ApplicationExit event to make sure hooks stop.
  • 8/8/08: Got rid of the debug code in the Macro example, added the MouseWheel method to the MouseSimulator class, and got rid of the duplicate MousePoint class used in MouseSimulator.

License

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


Written By
Software Developer GEA Refrigeration
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: How to recognize TouchPad from Mouse ? Pin
Randor 20-Jan-09 12:07
professional Randor 20-Jan-09 12:07 
GeneralRe: How to recognize TouchPad from Mouse ? Pin
MarkB1231-Feb-10 2:57
MarkB1231-Feb-10 2:57 
GeneralExcellent! Pin
BigWorld12-Jan-09 22:41
BigWorld12-Jan-09 22:41 
GeneralMouseWheel problem Pin
Member 345340111-Jan-09 5:24
Member 345340111-Jan-09 5:24 
GeneralMouseWheel doesn't work correctly Pin
tyranitar4-Jan-09 14:20
tyranitar4-Jan-09 14:20 
Generalcause WMI to crash Pin
Huisheng Chen25-Dec-08 18:18
Huisheng Chen25-Dec-08 18:18 
Questionhow do I.. Pin
Saiyad Faraz20-Dec-08 6:17
Saiyad Faraz20-Dec-08 6:17 
GeneralI implemented the serialization part for Macros. Here is the result... Pin
AnandChavali12-Dec-08 1:05
AnandChavali12-Dec-08 1:05 
Hi,
I implemented the serialization part for Macros. Here is the result...

Changes to Macro.cs file
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace GlobalMacroRecorder
{

    /// <summary>
    /// All possible events that macro can record
    /// </summary>
    [Serializable]
    public enum MacroEventType
    {
        MouseMove,
        MouseDown,
        MouseUp,
        MouseWheel,
        KeyDown,
        KeyUp
    }

    /// <summary>
    /// Series of events that can be recorded any played back
    /// </summary>
    [Serializable]
    public class MacroEvent
    {
        public MacroEventType MacroEventType;
        public MacroKeyEventArgs keyEventArgs;
        public MacroMouseEventArgs mouseEventArgs;
        public int TimeSinceLastEvent;

        public MacroEvent(MacroEventType macroEventType, MacroKeyEventArgs eventArgs, int timeSinceLastEvent)
        {
            MacroEventType = macroEventType;
            keyEventArgs = eventArgs;
            mouseEventArgs = null;
            TimeSinceLastEvent = timeSinceLastEvent;
        }

        public MacroEvent ( MacroEventType macroEventType , MacroMouseEventArgs eventArgs , int timeSinceLastEvent ) {
            MacroEventType = macroEventType;
            keyEventArgs = null;
            mouseEventArgs = eventArgs;
            TimeSinceLastEvent = timeSinceLastEvent;
        }

    }
    [Serializable]
    public class MacroKeyEventArgs {
        Keys KeyData; bool SupressKeyPress;
        public MacroKeyEventArgs ( Keys theKeyData , bool theSupressKeyPress ) {
            KeyData = theKeyData;
            SupressKeyPress = theSupressKeyPress;
        }        
        public KeyEventArgs GetKeyEventArgs(){
            KeyEventArgs args = new KeyEventArgs(KeyData);
            args.SuppressKeyPress = SupressKeyPress;
            return args;
        }
    }
    [Serializable]
    public class MacroMouseEventArgs {
        MouseButtons button; int clicks; int x; int y; int delta;
        public MacroMouseEventArgs ( MouseButtons thebutton , int theclicks , int thex , int they , int thedelta ) {
            button = thebutton;
            clicks = theclicks;
            x = thex;
            y = they;
            delta = thedelta;            
        }
        public MouseEventArgs GetMouseEventArgs () {
            return new MouseEventArgs(button , clicks , x , y , delta);
        }
    }

}


Then say that I have added an OpenFile and a SaveFileDialog to MacroForm, here are code changes in MacroForm:

private void mySaveBtn_Click ( object sender , EventArgs e ) {
    if (events.Count == 0) {
        MessageBox.Show("No events to save.");
        return;
    }
    if (mySaveFileDialog.ShowDialog() == DialogResult.OK) {
        string path = Path.GetFullPath(mySaveFileDialog.FileName);
        using (StreamWriter writer = new StreamWriter(path , false)) {
            BinaryFormatter binFormatter = new BinaryFormatter();
            foreach (MacroEvent e1 in events) {
                binFormatter.Serialize(writer.BaseStream , e1);
            }
        }
    } else {
        MessageBox.Show("User cancelled.");
    }
}

private void myOpenBtn_Click ( object sender , EventArgs e ) {
    if (myOpenFileDialog.ShowDialog() == DialogResult.OK) {
        string path = Path.GetFullPath(myOpenFileDialog.FileName);
        events.Clear();
        BinaryFormatter binFormatter = new BinaryFormatter();
        using (StreamReader reader = new StreamReader(path)) {
            while (reader.BaseStream.Position != reader.BaseStream.Length) {
                MacroEvent e1 = binFormatter.Deserialize(reader.BaseStream) as MacroEvent;
                events.Add(e1);
            }
        }
    }


}


Also while adding events to list, I have done some minor changes so that I do not add the mouse events from this application (recorder). I do check for IsSameWindow and if that returns false, I add the mouse events only then. In this way I can get rid of last "Stop" button presses if any.

[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow ();

bool IsSameWindow {
   get {
      if (myEventsFromSameAppChBox.Checked) {
          return (
             GetActiveWindow() == this.Handle);
      } else {
          return false;
      }
   }
}


Hope some body finds this useful.

Thanks and Regards,
Anand.

modified on Monday, December 15, 2008 1:15 AM

GeneralRe: I implemented the serialization part for Macros. Here is the result... Pin
Célio18-Dec-08 6:38
Célio18-Dec-08 6:38 
QuestionRe: I implemented the serialization part for Macros. Here is the result... Pin
Célio19-Dec-08 3:41
Célio19-Dec-08 3:41 
GeneralRe: I implemented the serialization part for Macros. Here is the result... Pin
Leo Chien Teen3-Dec-09 22:15
Leo Chien Teen3-Dec-09 22:15 
GeneralRe: I implemented the serialization part for Macros. Here is the result... Pin
Célio6-Dec-09 4:43
Célio6-Dec-09 4:43 
QuestionHow to count Mouseclick? Pin
Ericdepars24-Nov-08 6:08
Ericdepars24-Nov-08 6:08 
Generalis it possible to... Pin
jadothebest7-Nov-08 9:29
jadothebest7-Nov-08 9:29 
GeneralA problem with mouseHook_MouseMove Pin
Pezoo5-Nov-08 5:16
Pezoo5-Nov-08 5:16 
Generaldouble click event never fired Pin
xd12519-Oct-08 19:05
xd12519-Oct-08 19:05 
GeneralRe: double click event never fired Pin
qwang@mail.sportscn.com16-Feb-09 22:32
qwang@mail.sportscn.com16-Feb-09 22:32 
QuestionMouse Cursor changing Pin
mr_squall8-Oct-08 3:23
mr_squall8-Oct-08 3:23 
GeneralLittle rewrite of your Library Pin
SeriousM8-Sep-08 21:58
SeriousM8-Sep-08 21:58 
GeneralProblem with Vista. Pin
Shevchenko78-Sep-08 9:59
Shevchenko78-Sep-08 9:59 
GeneralRe: Problem with Vista. Pin
Brian Geiman8-Sep-08 16:39
Brian Geiman8-Sep-08 16:39 
GeneralRe: Problem with Vista. Pin
Shevchenko715-Sep-08 7:20
Shevchenko715-Sep-08 7:20 
GeneralGreat program! Pin
Member 33485337-Sep-08 3:21
Member 33485337-Sep-08 3:21 
GeneralRe: Great program! Pin
Brian Geiman8-Sep-08 16:36
Brian Geiman8-Sep-08 16:36 
GeneralCorruption of certain characters Pin
dReep29-Aug-08 11:47
dReep29-Aug-08 11:47 

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.