Introduction

The WindowsHookLib is a single library to hook the mouse, keyboard and the clipboard system wide. WindowsHookLib library has been rewritten in C# and therefore it uses Common Language Runtime (CLR). This means that the library can be referenced from various projects in .NET. The mouse and keyboard hooks are low level so you can use the Handled property of the MouseEventArgs or the KeyboardEventArgs to prevent the windows messages being passed to the other applications. Note you need to use the DLL file, not the classes in your projects; otherwise they might not work correctly.

Clipboard hook

Keyboard hook

Mouse hook

This component differs from what I have seen in other similar articles, by providing two more things:

Preventing a message to be passed to other windows

Raising the MouseClick and MouseDoubleClick events (I have never seen implementation of this in other low level hooks!)

Mouse Hook

The MouseHook class of the 'WindowsHookLib' library is designed to hook the mouse globally and raise some useful events. Since this hook is low level and low level mouse hooks don't get the MouseClick and MouseDoubleClick messages, it simulates these events. In order to use these events, the class object variable should be declared with the WithEvents keyword.

The MouseDown, MouseUp, MouseWheel, and MouseMove event handlers have a WindowsHookLib.MouseEventArgs class object which provides all the relevant information about the mouse as does the System.Windows.Forms.MouseEventArgs, and two additional properties, Handled and Control. You can set the Handled property to True to prevent the message from being passed to the other windows. The Control property provides the handle of the control under the mouse pointer. If you decide to set the Handled property in the MouseUp event, then it is recommended to set it in the MouseDown event as well for application performance. Conversely, if you decide to set the Handled property in the MouseDown event, then it is recommended to set it in the MouseUp event.

Note: If you set the Handled property in the mentioned events unconditionally, then you might not be able to use the mouse. To condition (block the mouse message to be passed to other windows or controls), you should compare the Control property's value against allowed control handle(s). If the allowed controls' handle list doesn't contain the Control property value, then you can set the Handled property to True; otherwise, don't set it. You can check the demo project's examples to see how you can condition the mouse handled process.

Note: Before you exit your application, you must call the hook object's Dispose method to uninstall the hook and free the class variables.

Keyboard Hook

The KeyboardHook class of the 'WindowsHookLib' library can be used to hook the keyboard globally. The class provides three events whose KeyDown and KeyUp event handlers contain a WindowsHookLib.KeyEventArgs object that has all the relevant information about the key as the System.Windows.Forms.KeyEventArgs. As with the mouse hook, you can set the Handled property to True in the KeyDown and KeyUp event handlers to prevent the message from being passed to other windows.

Clipboard Hook

The ClipboardHook class of the 'WindowsHookLib' library can be used to hook a window to the clipboard chain. The class provides two events, ClipbordChanged and StateChanged. The ClipboardChanged event handler contains a WindowsHookLib.ClipboardEventArgs object that has all the relevant information about the event.

Using the Code

Note: You need to use the DLL file by referencing it in your project, not the classes; otherwise, they might not work correctly. If you need the method descriptions, then you need to copy the 'WindowsHookLib.xml' file into your project folder.

Background

In the core of this component lies the API methods. All hooks use some API methods to hook and monitor for Windows messages. The following list is the API methods that have been used:

SetWindowsHookEx

UnhookWindowsHookEx

CallNextHookEx

WindowFromPoint

SendInput

SetClipboardViewer

ChangeClipboardChain

Points of Interest

I learned many things from this project like how to make a DLL file component that can be used in various projects (VB.NET, C#, C++, J#) in the .NET environment. Also, how to apply attributes to classes or methods that will make a component professional.

Since low level mouse hooks don't get the MouseClick and MouseDoubleClick event messages (which I believe are generated by a window that gets the MouseDown and MouseUp messages), I tried to simulate these events such that they are generated in the same pattern as the Windows MouseClick and MouseDoubleClick events.

Comments and Discussions

I have a simple test program that is able to reproduce the error. It appears that when the computer is under load the error appears. Then when I close the program and release the hook I get an "Invalid hook handle". Glad to send you the source code if that would help you.

I have tested the hook demo on windows 7 at my work for hours and have not seen the problem you are describing. Try the hook demo project and see if you encounter the problem. The problem could be system related since my tests do not show any problem whit the library.
You can download the demo project from my website http://www.code2point.com/Project.aspx?proj=4[^]

This is a known issue with all low level hooks (mouse and keyboard) in win 7. So this bug has nothing to do with this proposed hooking class here at all.
The solution I discovered for my real world freeware "Transmiti" (www.transmiti.org) is a extra thread which checks permanently the hooks and rehooks automatically in case the hook is lost.
It is an not so easy task as it sounds, because you have to be aware of some important details, like a call to the windows api function SystemParametersInfo with the parameters (SPI_SETBLOCKSENDINPUTRESETS,TRUE,NULL,0) to set the screensaver timer not to be reseted by a virtual keystroke which I send every one second to check the low level keyboard hook.
If you are interested in my real world source I can post some code snippets here.

Now I succed to make your demo working (at home on a Win7), but I am now stucked with the SetWindowsHookEx call when I set he WH_CBT flag.
I got a "Impossible d’établir un hook non local sans un descripteur de module
" message (meaning moreorless: Impossible to set a global hook without a module description).

Can I ask you if you can try just to try modify the SetWindowsHookEx call and let me know if you experience any problem?

Hi Paolo,
It seems that in framework 4 getting module handle with 'Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);' returns the wrong handle id. This was not a problem in framework 3.5, it seems things got changed or it is a bug in framework 4. Anyways, I changed that line above to an API (GetModuleHandle) function call that gets the right module handle. You can download the updated version of the assembly (1.1.1.3) from 'Download latest version' (my website) link on the top of this page. I don't have the project solution in there but only the code and assembly. If you want the project than you can download it from this page but you need to change the above line to the api function as I have discussed.

For installing WH_CBT hook I can only give you a reference link to the (CBTProc) Callback function that you should use to get notifications. Just read the specifications and try to do it. Now I don't have time for it, I am sorry.

Yesterday, I tried to follow your instructions and the hook now work without any problem.
Then I did a further step and I just changed your hook parameter in the SetWindowsHookEx call where I replaced UnsafeNativeMethods.WH_KEYBOARD_LL with the WH_CBT value.
Unfortunately, as result of this "setup" call, I got a "Impossible d’etabilir un hook non local sans un descripteur de module" (impossible to set a non-local hook without a module descriptor ??)

I tried as well with with UnsafeNativeMethods.WH_KEYBOARD param but I got the same.

Hi Ambaraba111,
Currently I don't have time to add other hooks to the library but the library project is provided so you can extend it if you want.
Check the API SetWindowsHookEx function. This function takes hook type (flag) like WH_CBT which will Install a hook procedure that receives notifications useful to a CBT application.

I started once again from your demo, thet I converted it in VB2010 and c#2010 without any problem.

I complied the .DLL project without any hassle and then in the VB project I added a reference to the new DLL (in \bin\x86\Release directory)

When I run the application and I hook the mouse, I get an (error) mesaage saying "The operation completed succesfully". The problem is that the hook is not activated (and in the groupbox header it shows "Mouse hook unistalled!"

The same happens with the keyboard hook, but it works when I hook the clipboard.

I tried as well to point to your original DLL, but the results are the same.

I am currently using XP professional version 2002 SP 3

Have you any hint? Many thaks in advance
Paolo

(update) the problems is in the
this._hMouseHook = UnsafeNativeMethods.SetWindowsHookEx(...)
that returns 0, but I don't know how to make it work ...

Really it’s nice article. Thanks for publish such type of article. It’s really imagine to seen such type of nice article.
I ask small question when I type small 'a' then show capital 'A' as well as when type capital 'A' then also show capital 'A'. Can we difference Capital and small.

I would prevent some KeyBoard and mouse events.
For example:
I would intercept the F1 keypress to open application Help in all opened forms, without manage KeyPreview in every opened forms.
I would intercept the CTRL+TAB combination such as in Visual Studio.
I would LogOff my application if there's no user activity (by using Mouse or KeyBoard) for 2 minutes, without manage KeyPreview and mouse move in every opened forms.
...

Of course, but if I start, for example, the Hook of CTRL+TAB combination it is intercepted in all opened application. For example, if I'm writing in Word application and press CTRL+TAB, the Hook activated in my application takes control, instead I would intercept only if CTRL+TAB is pressed in my application.
I do not know if it makes the idea

The Keyboard hook is a global hook (low level hook) there for the key down message is passed to the hook before any window.

If you want to set a key combination for your application than it makes sens to set it as a hotkey for your application. I created a class that will help you to set hotkeys for applications. Here is the link to the Hotkeys class. You can use and register a hotkey in your application and handle the "HotkeyPressed" event in your main form where the Hotkeys object is declared.

Or if you still want to use the Keyboard hook than you need to check to see if your application is active (has focus) when the key combination is down.

As far as I understand, you need to register a hotkey for your application. This dll can be used to achieve what you want as I mentioned above but this is not the best way of doing it. The right way is to register a hotkey.

A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process."

This means that you can't have "IntPtr.Zero, 0" for the last two parameters. If the first parameter of these two is IntPtr.Zero than the second one should contain a tread ID not zero. This is an assembly (dll) and the procedure is in it. there for the assembly handle should be specified and not be IntPtr.Zero.