Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Mouse and Keyboard Tracking and Simulator

0.00/5 (No votes)
21 Nov 2014 1  
Revision of the Global Mouse and Keyboard Library from Brian Geiman

Introduction

Have you ever wanted a program to record and then simulate certain keyboard and mouse actions but didn't know how to? Well then I might have the solution for you.

This is revision of the Global Mouse and Keyboard Library by Brian Geiman.

This article focuses mostly on the Global Macro Recorder Example included in the MouseKeyboardLibrary solution. The other included form called HookTestForm is very simplistic and does exactly what it says on the tin.

However, when I was testing and trying out the Global Macro Recorder, I felt that there was just something missing. It's a perfect example, don't get me wrong, but if you want something to fool your friends; it won't do.

Thus the reason why I love Code Project's Open License, I took the form and revised it. Glory to the benefit of Open Source.

This is the result of the revision.

What This Did

Clean up Process

If you had read my Manage YouTube using C# and YouTube API 1.6, a lot of the same process here.

When creating a new form, Microsoft Visual Studio always puts in the most used references in a list and waits for you to use them (like System, System.Drawing, System.Windows.Forms). Basically, extra items that are loaded and stand there being pretty hoping that you would use them. However, if you do not use them, they slow down the boot up and response time of your application.

I remove all the ones that are not needed into run the program.

Before:

Before

After:

After

The difference in application boot up time is quite noticeable. Of course, you need to remove the using references to see the performance boost application wide.

After I did that, I did some blank clean up on the code. A perfect example is when you are trying to do Form Designer code outside of the form.designer you do not need to type all of:

mouseHook.MouseMove += new MouseEventHandler(mouseHook_MouseMove);

All you need to type is:

mouseHook.MouseMove += mouseHook_MouseMove;

The compiler will do the rest.

Now let's talk about something that most people hardly care about but is very important. Let's talk about thread-safety! Thread safety is my most favorite topic being that multi-threaded programs are becoming more and more apparent in today's society. This goes on to do with the fact of race conditions/hazards. If you are making a program to do a set process; you want to make sure that it does that process without having any issues with other threads running.

In C#, you have the ultimate power of assigning attributes to control the semantics of your property. When you are assigning properties, you have the chance to change its memory visibility semantics.

Giving an example when you have a field that will not change its value nor its meaning like:

private KeyboardHook keyboardHook = new KeyboardHook();

you can add a readonly field:

private readonly KeyboardHook keyboardHook = new KeyboardHook();

to make it thread-safe. It changes how the value is compiled and declared. For readonly read this for more information on how it works and why it is important.

Now let's go through redundancy checking.

When you are initializing a field, don't be worried if a value is not attached to it at the same time. Just make sure that when the field is used it will have a value. MacroForm was a very well written program with only a single field having a redundant default value.

It was the lastTimeRecorded int field. The reason why it was redundant was because on first use it was initialized with Environment.TickCount. So it completely overwrote the default value to begin with. It makes no difference when you are doing an int, but if you are doing an object, depending on the object and how complicated it is, it can make a couple seconds wasted.

What is New

Now that the little picky stuff is out of the way, let's find what we can now do!

First, let's look at the old form:

old program (Does the job but isn't you know BOSS)

Now at the new form:

New program. (NOW THAT IS BOSS)

The new form spots these upgraded specs:

  1. Buttons are only enabled when they need to be.
  2. Bool values to see if the program is recording or if the hotkey warnings have been said.
  3. A backworker (called Playworker) for the playback of the process (made so that we can stop the playback).
  4. Hide Window option when playing back.
  5. Stop when mouse has selected the form option.
  6. Integration of my favorite Global Hotkey Activation.
    1. If the Hotkey is activated, you can enable forever loop and loop the playback until the Global hotkey is pressed.
  7. Added progress bar to retrieve progresses reports

I know people are going to ask, but NO I did not include a serializer to save mouse or keyboard movements. Saving a mouse event is a pain in the butt (being that you need to break down the event and create different variables for each of the internal objects). Nevertheless, if you save the mouse movement and then take it to another computer system with a different screen resolution, you can get an out of bounds pointer exception. It a mess of error corrections that will need to be done to get it working right.

Now that I explained why I did not include a save button, let's move on.

The Global Hotkeys work from setting a System IntPtr struct from the inputted key code and modifier under Windows.Forms.Keys. When the hotkey is pressed, there is a protected override void that's activated. From that void, it runs another void called HandleHotkey to handle the hotkey event.

The Backworker and Progress Bar are quite simple; it does what was programmed in for playback with the addition of three things.

  1. Before the Backworker is even told to do work, the recorded events are counted and set to the progress bar maximum.
  2. An internal variable then counts the events that the backworker ran and outputs that to the progress bar.
  3. Before the next event is run, there is a check to see if the worker has a cancellation pending; if there is, it exits the foreach command.

The Hide Window and Stop on Select are simple options that are self-explanatory. To be noted there is a check to see if the Hide Window is checked before changing the value of the progress bar. This is to counter an exception you can get when you hide the form but change a designer item's status.

Conclusion

Whether you wanted this application to see how to record mouse and keyboard inputs or if you wanted to have fun with your friend; it does the same thing.

Feel free to download both of the sources and compare them. It's tons of fun to play around with.

Cheer fellow nerds!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here