Introduction

This article discusses a class that I wrote that wraps a global low level keyboard hook. The sample hooks the A and B keys, just for demonstration.

Background

I was trying to find a way for an application that I am writing to restore itself when a combination of keys was pressed. This was born from searching around for the answer.

Using the Code

First download the source, and add globalKeyboardHook.cs to your project. Then add...

using Utilities;

... to the top of the file you are going to use it in. Next add an instance of globalKeyboardHook to your class:

globalKeyboardHook gkh = new globalKeyboardHook() ;

When a globalKeyboardHook is constructed, it automatically installs the hook, so all there is left to do is add some keys for it to watch, and define some event handlers for the KeyDown and KeyUp events. I usually do this on the main form's load event handler, like this:

Here I have chosen to watch for the A and B keys, and defined handlers for the KeyUp and KeyDown events that both log to a listbox called lstLog. So whenever the user presses the A or B keys, no matter what has focus, the application will be notified. Setting e.Handled to true makes it so no other notifications for this event go out, in the sample, this effectively stops the user from typing an A or B. This can be useful in ensuring that key combinations are not also typed out when used.

You can add hooks for as many keys as you would like, just add them like above. Don't get frustrated if you add a hook for a key and it doesn't work, many of them, like Keys.Shift show up as other more specific keys, like Keys.LShiftKey or Keys.RShiftKey. Keys.Alt shows up as Keys.LMenu or Keys.RMenu, Keys.Control shows up as Keys.LControl or Keys.RControl, just to name a few.

If you would like to hook or unhook the keyboard hook at any point, just call your globalKeyboardHook's hook and unhook methods, like so:

//unhook
gkh.unhook()
//set the hook again
gkh.hook()

Points of Interest

The bulk of the work in this code is done in the globalKeyboardHook class, although it is a fairly simple piece of code itself. The hardest part of doing this was finding the correct parameters for SetWindowsHookEx.

The first parameter WH_KEYBOARD_LL is just saying that we want to hook the low level keyboard events, hookProc is the callback for the event, hInstance is a handle to User32.dll, where this event is first processed (I think). The last parameter is if you want to hook a specific thread, then you would just pass a thread id instead of using the hInstance.

Comments and Discussions

I started with C# not a long time ago so maybe this question is stupid (sorry for that). I tried to change the hooked keys (from "A" and "B"). It worked very well with nearly every key (numbers, space, enter,...). But it didnt work with the control key wich would be important for my use. So i dont know if it's a bug or i am just too stupid. Thanks for your answer!

I saw others have the same problem and i have it too.
For example i set the keys Left-Ctrl + G or even if it's only G the first 3-4 times i press the key/s it's working fine but then i keep pressing the key/s and it does nothing. Like the event stopped or something.

HI, I tried to use your code on my vs2010 and dot net 4 based program, it gives the error on a random basis and says "A callback was made on a garbage collected delegate of type 'bengali keyboard!bengali_keyboard.globalKeyboardHook+keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called." Could you please help me on this? I have instatiated the class just as you had shown.

Also, I cannot trap shift key despite adding it to gkh.HookedKeys.Add(Keys.ShiftKey); when i try to handle this in keydown event as
if (e.Shift==true)
{
textBoxExt1.Text = "true";

}
it is unable to trap it, i am using only the keydown event and all single keys seems to work fine, also in my form I can detect the shift key using the above code, if the textbox has focus, by using the textbox's own keydownevent. Thank you.

I tried Member 4120854' s way of delegates, but it still gives error, now this happens at return CallNextHookEx(hhook, code, wParam, ref lParam); in fucntion public int hookProc(int code, int wParam, ref keyboardHookStruct lParam).

Ok, now it seems to be working fine after i rectified my errors, but still it gives that gc error whenever i try to pass

So what I am wondering is, should I use the code I have commented out in the second method? It works fine as is, but I can't help wondering if I am making a mess in memory if I don't remove the key hooks and keyhandlers.

I may have answered this for myself. It turned out that if I re-added the key hooks and keyhandlers then there would be multiple ones running so that when I hit the trigger key the event would be processed as many times as there were handlers. This was quickly resolved by simply keeping track of the first instance of each and then ensuring that no more were instantiated.

From what I can tell it is not even possible to remove the hooked keys manually or even remove the key event handlers. The gkh.unhook() method does not do that either. It seems to come down to allowing windows to dispose of these when the application terminates.

I was using it till while. And suddenly it stopped working. Any keys that are hook will not get to application they should. For example if i use ur demo program and try to type "A" here it will get in listbox but not here. I tried redownloading the source files again and just program still same problem.

1 . Usually Anti Viruses are not happy to see Set Windows HookThis code expecially using the paramater "0" attaches itself to all the threads , which probably is not a good thing. Please provide your opinion.The only change that I have done is to add all the alphabets.

I was trying to add other language characters as well.Please explain as to how that may be achieved.

Keys do not equal characters - there's more characters in your charmap than there are keys on the keyboard. There's modifier keys that may change the character that's produced. Press shift and press the "a" key.