Click here to Skip to main content
11,813,557 members (42,638 online)
Click here to Skip to main content

Processing Global Mouse and Keyboard Hooks in C#

, 31 Aug 2011 CPOL 215.8M 142.5K 980
Rate this:
Please Sign up or sign in to vote.
This class allows you to tap keyboard and mouse and/or to detect their activity even when an application runs in the background or does not have any user interface at all.


This article was posted in 2004 and updated in 2006 and 2008. During all this time until now I receive a lot of positive feedback and recommendations. There where also many useful contributions which where usually posted as code snippets in forum. Now instead of publishing yet another version on my own I decided to ask you all to actively participate. So please be enthusiastic, feel free to join the project at

You can help by:
  • Contributing code.
  • Creating issue items requesting additional features or reporting defects.
  • Voting for features and fixes you are interested in.
  • Testing the component in different environments.
  • Writing developer documentation.

This will us also allow to keep this original article up to date.

Thank you all for all your great comments on CodeProject forum and looking forward for your brilliant contributions at


This class allows you to tap keyboard and mouse and/or to detect their activity even when an application runs in the background or does not have any user interface at all. This class raises common .NET events with KeyEventArgs and MouseEventArgs, so you can easily retrieve any information you need.


There are a number of applications that run in the background and detect user inactivity to change their mode. For example, MSN Messenger (or any other messenger). I was going to write such an application, so I searched MSDN and found "exactly" what I needed: 318804 - HOW TO: Set a Windows Hook in Visual C# .NET. This article describes how to tap the mouse movement, but it works only when an application is active. At the end of this article, I found this explanation: "Global hook is not supported in .NET Framework. You cannot implement global hooks in Microsoft .NET Framework...". Anyway, I continued my research and found out that there are exceptions. There are WH_KEYBOARD_LL and WH_MOUSE_LL hooks that can be installed globally. So, I have basically replaced WH_MOUSE with WH_MOUSE_LL in the MSDN example, and it works.

The second step was to extract the information received into a .NET EventArgs and raise the appropriate events.

I found a similar article in CodeProject, under Global System Hooks in .NET by Michael Kennedy, but what I dislike is, there is an unmanaged DLL in C++ that is a main part of this solution. This unmanaged DLL is in C++, and a number of classes make it complicated to integrate it in my own tiny application.


This article was posted in 2004 and updated in 2006. During all this time until now I receive a lot of positive feedback and recommendations. There were also a number of technology improvements like .NET Framework 3.5 or Visual Studio 2008. So I have decided to update it once more.

I have refactored and improved the solution, made it more flexible, stable and efficient. But this refactoring also had some drawbacks:

  1. Number of code lines and files has grown.
  2. Backward compatibility to older .NETs is lost.

That's why I attend to leave the old version also to be available for download.

Using the Code [Version 2]

The Simple Way

If you are developing a Windows Forms application and prefer drag & drop programming, there is a component named GlobalEventProvider inside the assembly Gma.UserActivityMonitor.dll. Just drag and drop it to your form and create events using the property editor events tab.

The Alternative Way

Use events provided by the static class HookManager. Note that the sender object in events is always null.

For more usage hints, see the source code of the attached demo application.

Using the Code [Version 1]

To use this class in your application, you need to just create an instance of it and hang on events you would like to process. Hooks are automatically installed when the object is created, but you can stop and start listening using appropriate public methods.

UserActivityHook actHook;
void MainFormLoad(object sender, System.EventArgs e)
    actHook= new UserActivityHook(); // crate an instance

    // hang on events

    actHook.OnMouseActivity+=new MouseEventHandler(MouseMoved);
    actHook.KeyDown+=new KeyEventHandler(MyKeyDown);
    actHook.KeyPress+=new KeyPressEventHandler(MyKeyPress);
    actHook.KeyUp+=new KeyEventHandler(MyKeyUp);

Now, an example of how to process an event:

public void MouseMoved(object sender, MouseEventArgs e)
    labelMousePosition.Text=String.Format("x={0}  y={1}", e.X, e.Y);
    if (e.Clicks>0) LogWrite("MouseButton     - " + e.Button.ToString());

Changes and Updates from [Version 0] to [Version 1]

I'd like to thank you all for all the useful comments in the discussion forum. There were a lot of bugs and proposals posted after this article was published on 4th June, 2004. Over and over again came the same topics, and I had to refer to previous posts in the discussion, that is why I have decided to revise the code and publish a FAQ. Here is the list of the most important changes:

  • The project was converted into Visual Studio 2005
  • The problem with upper case characters is solved
  • Mouse wheel information is now included in event arguments
  • Better exception handling
  • Cancellation of keyboard events using the Handled property of event arguments
  • XML documentation of functions

FAQ [Version 1]


The project cannot be run in Visual Studio .NET 2005 in debug mode because of an exception error caused by calling the SetWindowsHookEx. Why? Is it a problem of .NET 2.0?


The compiled release version works well so that cannot be a .NET 2.0 problem. To workaround, you just need to uncheck the check box in the project properties that says: "Enable Visual Studio hosting process". In the menu: Project -> Project Properties... -> Debug -> Enable the Visual Studio hosting process.


I need to suppress some keystrokes after I have processed them.


Just set the e.Handled property to true in the key events you have processed. It prevents the keystrokes being processed by other applications.


Is it possible to convert your global hooks to application hooks which capture keystrokes and mouse movements only within the application?


Yes. Just use...

private const int WH_MOUSE = 7;
private const int WH_KEYBOARD = 2;

... everywhere, instead of:

private const int WH_MOUSE_LL = 14;
private const int WH_KEYBOARD_LL = 13;


Does it work on Win98 (Windows ME, Windows 95)?


Yes and No. The global hooks WH_MOUSE_LL and WH_KEYBOARD_LL can be monitored only under Windows NT/2000/XP. In other cases, you can only use application hooks (WH_MOUSE and WH_KEYBOARD) which capture keystrokes and mouse movement only within the application.


I have a long delay when closing applications using hooks by clicking the x button in the titlebar. If I close the application via another event (button click) for example, that works fine.


It's a known bug of Microsoft. It has to do with the Windows themes. If you disable the Windows themes, the problem goes away. Another choice is to have the hook code run in a secondary thread.


How do I catch key combinations like Ctrl+Shift+A?


You'll have to track which keys have gone down but not up. Only the most recently pressed key keeps sending KeyDown messages, but the others will still send a KeyUp when released. So if you make three flags IsCtrlDown, IsShiftDown, and IsADown, and set them to true at KeyDown and false at KeyUp, the expression (IsCtrlDown && IsShiftDown && IsADown) will give you the required result.


Does it works with .NET Framework 1.1 and Visual Studio 2003?


Yes. The file UserActivityHook.cs can be used without any changes, in a Visual Studio 2003 .NET 1.1 project.


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


About the Author

George Mamaladze
Software Developer
Germany Germany
Tweeter: @gmamaladze
Google+: gmamaladze

You may also be interested in...

Comments and Discussions

AnswerRe: Solution exception due to Gma.UserActivityMonitor (Visual Studio 2012, C#) Pin
George Mamaladze4-Nov-14 0:40
memberGeorge Mamaladze4-Nov-14 0:40 
GeneralRe: Solution exception due to Gma.UserActivityMonitor (Visual Studio 2012, C#) Pin
Member 112925077-Dec-14 5:31
memberMember 112925077-Dec-14 5:31 
BugHook without Administrator privileges conflicts with other programs! Pin
TMSxCodeProj30-Oct-14 7:36
memberTMSxCodeProj30-Oct-14 7:36 
Generalvote 5 Pin
waertf.chen15-Oct-14 23:07
memberwaertf.chen15-Oct-14 23:07 
QuestionHow to capture the scroll button pressed? Pin
Will580120-Sep-14 4:48
memberWill580120-Sep-14 4:48 
GeneralMy vote of 5 Pin
Member 100358588-Sep-14 7:05
memberMember 100358588-Sep-14 7:05 
SuggestionMessage Automatically Removed Pin
31-Aug-14 0:24
memberMember 1104824331-Aug-14 0:24 
QuestionModule not found Exception while using in .NET 4 - Solution Pin
Vitasimplex28-Aug-14 22:32
memberVitasimplex28-Aug-14 22:32 
AnswerRe: Module not found Exception while using in .NET 4 - Solution Pin
Spencer Kittleson3-Sep-14 19:12
professionalSpencer Kittleson3-Sep-14 19:12 
AnswerRe: Module not found Exception while using in .NET 4 - Solution Pin
Member 112925077-Dec-14 5:29
memberMember 112925077-Dec-14 5:29 
GeneralRe: Module not found Exception while using in .NET 4 - Solution Pin
Vitasimplex7-Dec-14 6:47
memberVitasimplex7-Dec-14 6:47 
AnswerRe: Module not found Exception while using in .NET 4 - Solution Pin
Sturms20-Apr-15 10:42
memberSturms20-Apr-15 10:42 
QuestionDisable mouse wheel Pin
Member 953813318-Aug-14 5:34
memberMember 953813318-Aug-14 5:34 
SuggestionMessage Automatically Removed Pin
18-Jul-14 2:47
memberMember 1093440018-Jul-14 2:47 
QuestionDoesn't work for simulation e.g. SendKeys.Send() method Pin
RizwanAkram25-Jun-14 0:00
memberRizwanAkram25-Jun-14 0:00 
QuestionError while registering event handler Pin
sachin Bhosale @ code5-Jun-14 19:27
membersachin Bhosale @ code5-Jun-14 19:27 
QuestionUpdated to .NET Framework 4.0 Pin
homi54319-May-14 6:33
memberhomi54319-May-14 6:33 
AnswerRe: Updated to .NET Framework 4.0 Pin
dirend30-May-14 3:29
memberdirend30-May-14 3:29 
GeneralGetting error while registering my form event handler Pin
m.kashif.ashraf6-May-14 22:23
memberm.kashif.ashraf6-May-14 22:23 
GeneralRe: Getting error while registering my form event handler Pin
Vitasimplex28-Aug-14 22:33
memberVitasimplex28-Aug-14 22:33 
Questionuser controlled key to hook Pin
Member 1074046525-Apr-14 6:04
memberMember 1074046525-Apr-14 6:04 
Questionvb Pin
Noel Buenaventura22-Apr-14 5:36
memberNoel Buenaventura22-Apr-14 5:36 
QuestionDisabling keyboard Pin
Dr. Tepster24-Mar-14 22:08
memberDr. Tepster24-Mar-14 22:08 
AnswerRe: Disabling keyboard Pin
delkernel26-Jul-14 11:22
memberdelkernel26-Jul-14 11:22 
QuestionAfter minimize remote desktop screen, Keyboard Hook Procedure is not working in C# Window Application Pin
Mr Tin Linn Soe24-Mar-14 0:40
memberMr Tin Linn Soe24-Mar-14 0:40 
AnswerRe: After minimize remote desktop screen, Keyboard Hook Procedure is not working in C# Window Application Pin
George Mamaladze24-Mar-14 1:36
memberGeorge Mamaladze24-Mar-14 1:36 
QuestionLost hooks during debugging Pin
Member 443327412-Mar-14 7:10
memberMember 443327412-Mar-14 7:10 
AnswerRe: Lost hooks during debugging Pin
George Mamaladze24-Mar-14 1:31
memberGeorge Mamaladze24-Mar-14 1:31 
GeneralGreat work Pin
MichaelMena28-Feb-14 2:57
memberMichaelMena28-Feb-14 2:57 
QuestionPower physical button Pin
osamaworx10-Feb-14 7:21
memberosamaworx10-Feb-14 7:21 
Questionhow to disable mouse right click event Pin
AnsariAzam6-Feb-14 0:41
memberAnsariAzam6-Feb-14 0:41 
Questiondemo version 2 crashes in Win 8/64 Pin
BillWoodruff19-Jan-14 1:12
memberBillWoodruff19-Jan-14 1:12 
GeneralRe: demo version 2 crashes in Win 8/64 Pin
sonu verma s27-Jan-14 18:07
membersonu verma s27-Jan-14 18:07 
QuestionHi problem is coming Pin
amit_8318-Dec-13 6:53
memberamit_8318-Dec-13 6:53 
AnswerRe: Hi problem is coming Pin
amit_8318-Dec-13 7:14
memberamit_8318-Dec-13 7:14 
GeneralRe: Hi problem is coming Pin
Member 1049498730-Dec-13 12:42
memberMember 1049498730-Dec-13 12:42 
QuestionThreading Pin
Nicke Da Silva Manarin28-Nov-13 4:40
memberNicke Da Silva Manarin28-Nov-13 4:40 
AnswerRe: Threading Pin
IGood10-Feb-14 15:35
memberIGood10-Feb-14 15:35 
GeneralRe: Threading Pin
Nicke Da Silva Manarin11-Feb-14 10:03
memberNicke Da Silva Manarin11-Feb-14 10:03 
GeneralRe: Threading Pin
IGood12-Feb-14 13:11
memberIGood12-Feb-14 13:11 
Question.NET 2.0 version? Pin
Onur Guzel10-Nov-13 11:17
memberOnur Guzel10-Nov-13 11:17 
QuestionUse Mouse hook to make a Mouse Clicker??? Pin
Member 102879151-Nov-13 12:43
memberMember 102879151-Nov-13 12:43 
Questionwindows 8 Pin
ppdjango14-Oct-13 21:13
memberppdjango14-Oct-13 21:13 
Question5 star vote Pin
Member 101408338-Oct-13 6:28
memberMember 101408338-Oct-13 6:28 
QuestionExcessive Lag Time Pin
MDLEIDE3-Oct-13 8:48
memberMDLEIDE3-Oct-13 8:48 
QuestionUnicode? Pin
Member 1029995326-Sep-13 7:41
memberMember 1029995326-Sep-13 7:41 
GeneralMy vote of 5 Pin
Alistair Tudor23-Aug-13 3:03
memberAlistair Tudor23-Aug-13 3:03 
Questionwhen i used your class in window service then it gives eroor "Win32Exception" Pin
Jayesh Goyani11-Aug-13 22:56
memberJayesh Goyani11-Aug-13 22:56 
QuestionHello Pin
bgsjust10-Jul-13 22:35
memberbgsjust10-Jul-13 22:35 
Questionsmall quibble Pin
sbarnes5-Jul-13 8:30
membersbarnes5-Jul-13 8:30 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.151002.1 | Last Updated 31 Aug 2011
Article Copyright 2004 by George Mamaladze
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid