Click here to Skip to main content
Click here to Skip to main content

Low-level Windows API hooks from C# to stop unwanted keystrokes

By , 26 Mar 2007
 

Sample Image - CSLLKeyboard.jpg

Introduction

Cats and babies have a lot in common. They both like eating the house plants, and share the same hatred of closed doors. They also love using keyboards, with the result that the important email you were sending to your boss is dispatched in mid-sentence, your accounts in Excel are embellished with four rows of gobbledygook, and your failure to notice that Windows Explorer was open results in several files moving to the Recycle Bin.

The solution is an application which you can switch to as soon as the keyboard is under threat, and which will ensure that any keyboard activity is harmless. This article illustrates how the keyboard can be neutralized in a C# application using a low-level Windows API hook.

Background

There are a number of articles and code samples regarding hooks in Windows, and some of them are listed at the end of this article. Neutralizing the keyboard when children are around must be a common need -- someone here wrote almost exactly the same thing in C++[^]! However, when I was looking for source code to create my application, I found very few .NET examples, and none that involved a self-contained class in C#.

The .NET framework gives managed access to the keyboard events you'll need for most ordinary uses through KeyPress, KeyUp and KeyDown. Unfortunately, these events can't be used to stop Windows from processing key combinations like Alt+Tab or the Windows Start key, which allow users to navigate away from an application. The conveniently placed Windows key in particular was irresistible to my baby son!

The solution is to catch the keyboard events at the operating system level rather than through the framework. To do this, the application needs to use Windows API functions to add itself to the "hook chain" of applications listening for keyboard messages from the operating system. When it receives this type of message, the application can selectively pass the message on, as it normally should, or suppress it so that no further applications -- including Windows -- can act on it. This article explains how.

Please note, however, that this code only applies to NT-based versions of Windows (NT, 2000 and XP), and that it isn't possible to use this method to disable Ctrl+Alt+Delete (suggestions on how to do that can be found in this MSDN Magazine Q&A[^]).

Using the code

For ease of use, I have attached three separate zip files to this article. One contains only the KeyboardHook class which is the main focus of this article. The others are complete projects for an application called "Baby Keyboard Bash" which displays the keys' names or coloured shapes in response to keystrokes. For ease of use, I have included two projects, one for Microsoft Visual C# 2005 Express Edition and one for Visual Studio 2003.

Instantiating the class

The keyboard hook is set up and handled by the KeyboardHook class in keyboard.cs. This class implements IDisposable, so the simplest way to instantiate it is to use the using keyword in the application's Main() method, to enclose the Application.Run() call. This will ensure that the hook is set up as soon as the application starts and, more importantly, is disabled as the application shuts down.

The class raises an event to warn the application that a key has been pressed, so it is important for the main form to have access to the instance of KeyboardHook created in the Main() method; the simplest solution is to store this instance in a public member variable. In a Visual Studio 2003 project, this will usually go in the Form1 class (or whatever the application's main class is called), and in Visual Studio 2005, in the Program class in Program.cs.

KeyboardHook has three constructors to enable or disable certain settings:

  • KeyboardHook(): traps all keystrokes, passing nothing to Windows or other applications.
  • KeyboardHook(string param): Converts the string to one of the values in the Parameters enum and then calls the following constructor:
  • KeyboardHook(KeyboardHook.Parameters enum): Depending on the value selected from the Parameters enum, the following settings can be enabled:
    • Parameters.AllowAltTab: allows the user to switch to other applications using Alt+Tab.
    • Parameters.AllowWindowsKey: allows the user to access the taskbar and Start menu using Ctrl+Esc or one of the Windows keys.
    • Parameters.AllowAltTabAndWindows: enables Alt+Tab, Ctrl+Esc and the Windows keys.
    • Parameters.PassAllKeysToNextApp: if the parameter is true, all keystrokes will be passed to any other listening applications, including Windows.

Enabling Alt+Tab and/or the Windows keys allows the person who is actually using the computer to switch to another application and interact with it using the mouse while keystrokes continue to be trapped by the keyboard hook. The PassAllKeysToNextApp setting effectively disables the keystroke trapping; the class will still set up a low-level keyboard hook and raise its KeyIntercepted event, but it will also pass the keyboard events to other listening applications.

The simplest way to instantiate the class to trap all keystrokes is therefore:

public static KeyboardHook kh;

[STAThread]
static void Main()
{
  //Other code
  using (kh = new KeyboardHook())
  {
    Application.Run(new Form1());
  }

Handling the KeyIntercepted event

When a key is pressed, the KeyboardHook class raises a KeyIntercepted event containing some KeyboardHookEventArgs. This needs to be handled by a method of the type KeyboardHookEventHandler, which can be set up as follows:

kh.KeyIntercepted += new KeyboardHook.KeyboardHookEventHandler(kh_KeyIntercepted);

The KeyboardHookEventArgs returns the following information on the key that was pressed:

  • KeyName: the key's name, obtained by casting the trapped key code to System.Windows.Forms.Keys.
  • KeyCode: the original key code returned by the keyboard hook
  • PassThrough: whether this instance of KeyboardHook is configured to allow this keystroke through to other applications. Checking this is useful if you want to allow a user to switch to another application using Alt+Tab or Ctrl+Esc/Windows keys.

A method with the appropriate signature can then be used to perform whatever tasks the keystroke calls for. Here is an example from the enclosed sample application:

void kh_KeyIntercepted(KeyboardHookEventArgs e)
{
  //Check if this key event is being passed to
  //other applications and disable TopMost in 
  //case they need to come to the front
  if (e.PassThrough)
  {
    this.TopMost = false;
  }
  ds.Draw(e.KeyName);
}

The rest of this article explains how the low-level keyboard hook is implemented in KeyboardHook.

Implementing a low-level Windows API keyboard hook

The Windows API contains three methods in user32.dll that are useful for this purpose:

  • SetWindowsHookEx, which sets up the keyboard hook
  • UnhookWindowsHookEx, which removes the keyboard hook
  • CallNextHookEx, which passes the keystroke information to the next application listening for keyboard events

The key to creating an application which can hijack the keyboard is to implement the first two methods, and forgo the third. The result is that any keys pressed go no further than the application.

In order to achieve this, the first step is to include the System.Runtime.InteropServices namespace and import the API methods, starting with SetWindowsHookEx:

using System.Runtime.InteropServices
...
//Inside class:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
  LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

The code to import UnhookWindowsHookEx and CallNextHookEx is listed in the sections concerning those methods further in this article.

The next step is to call SetWindowsHookEx to set up the hook, passing the following four parameters:

  • idHook: This number determines the type of hook to be set up. For example, SetWindowsHookEx can also be used to hook into mouse events; a complete list can be found on MSDN[^]. In this case, we're only interested in number 13, which is the keyboard hook's id. To make the code more legible, this has been assigned to the constant WH_KEYBOARD_LL.
  • lpfn: A long pointer to the function that will handle the keyboard events. In C#, the "pointer" is achieved by passing an instance of a delegate type, referring to the appropriate method. This is the method that will be called every time the hook is used.
    An important point to note here is that the delegate instance needs to be stored in a member variable in the class. This is to prevent it being garbage collected as soon as the first method call ends.
  • hMod: An instance handle for the application which is setting up the hook. Most of the samples I found simply set this to IntPtr.Zero, on the grounds that it is unlikely that there will be more than one instance of the application. However, this code uses GetModuleHandle from kernel32.dll to identify the exact instance to make the class potentially more flexible.
  • dwThreadId: The ID of the current thread. Setting this to 0 makes the hook global, which is the appropriate setting for a low-level keyboard hook.

SetWindowsHookEx returns a hook ID which will be used to unhook the application when it shuts down, so this needs to be stored in a member variable for future use. The relevant code from the KeyboardHook class is as follows:

private HookHandlerDelegate proc;
private IntPtr hookID = IntPtr.Zero;
private const int WH_KEYBOARD_LL = 13;


public KeyboardHook()
{
  proc = new HookHandlerDelegate(HookCallback);
  using (Process curProcess = Process.GetCurrentProcess())
  using (ProcessModule curModule = curProcess.MainModule)
  {
     hookID = SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
  }
}

Processing keyboard events

As mentioned above, SetWindowsHookEx requires a pointer to the callback function that will be used to process the keyboard events. It expects a function with the following signature:

LRESULT CALLBACK LowLevelKeyboardProc
(   int nCode,
    WPARAM wParam,
    LPARAM lParam
);

The C# method for setting up a "pointer to a function" is to use a delegate, so the first step in giving SetWindowsHookEx what it needs is to declare a delegate with the right signature:

    private delegate IntPtr HookHandlerDelegate(
        int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);

And then write a callback method with the same signature; this method will contain all the code that actually processes the keyboard event. In the case of KeyboardHook, it checks whether the keystroke should be passed to other applications and then raises the KeyIntercepted event. Here is a simplified version without the keystroke handling code:

private const int WM_KEYUP = 0x0101;
private const int WM_SYSKEYUP = 0x0105;

private IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
{
  //Filter wParam for KeyUp events only - otherwise this code
  //will execute twice for each keystroke (ie: on KeyDown and KeyUp)
  //WM_SYSKEYUP is necessary to trap Alt-key combinations
  if (nCode >= 0)
  { 
      if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
      {
        //Raise the event
        OnKeyIntercepted(new KeyboardHookEventArgs(lParam.vkCode, AllowKey));
      }
      //Return a dummy value to trap the keystroke
      return (System.IntPtr)1;
  }
  //The event wasn't handled, pass it to next application
  return CallNextHookEx(hookID, nCode, wParam, ref lParam);
}

A reference to HookCallback is then assigned to an instance of HookHandlerDelegate and passed in the call to SetWindowsHookEx, as illustrated in the previous section.

Whenever a keyboard event occurs, the following parameters will be passed to HookCallBack:

  • nCode: According to the MSDN documentation[^], the callback function should return the result of CallNextHookEx if this value is less than zero. Normal keyboard events will return an nCode of 0 or more.
  • wParam: This value indicates what type of event occurred: key up or key down, and whether the key pressed was a system key (left or right-hand Alt keys).
  • lParam: A structure to store precise information on the keystroke, such as the code of the key which was pressed. The structure declared in KeyboardHook is as follows:
private struct KBDLLHOOKSTRUCT
{ 
  public int vkCode;
  int scanCode;
  public int flags;
  int time;
  int dwExtraInfo;
}

The two public parameters are the only ones used by the callback method in KeyboardHook. vkCoke returns the virtual key code, which can be cast to System.Windows.Forms.Keys to obtain the key's name, while flags indicates if this is an extended key (the Windows Start key, for instance) or if the Alt key was pressed at the same time. The complete code for the HookCallback method illustrates which flags values to check for in each case.

If the information provided by flags and the other components of the KBDLLHOOKSTRUCT are not needed, the signature of the callback method and delegate can be changed as follows:

private delegate IntPtr HookHandlerDelegate(
        int nCode, IntPtr wParam, IntPtr lParam);

In this case, lParam will return only the vkCode.

Passing keystrokes to the next application

A well-behaved keyboard hook callback method should end by calling the CallNextHookEx function and returning its result. This ensures that other applications get a chance to handle the keystrokes destined for them.

However, the key functionality of the KeyboardHook class is preventing keystrokes from being propagated to any further applications. So whenever it processes a keystroke, HookCallback returns a dummy value instead:

return (System.IntPtr)1;

On the other hand, it does call CallNextHookEx if it didn't handle the event, or if the parameter passed with KeyboardHook's overloaded constructor allows certain key combinations through.

CallNextHookEx is enabled by importing the function from user32.dll as shown in the following code:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
  IntPtr wParam, ref KeyInfoStruct lParam);

The imported method is then called by this line in the HookCallback method, which ensures that all the parameters received through the hook are passed on to the next application:

CallNextHookEx(hookID, nCode, wParam, ref lParam);

As mentioned before, if the flags in lParam are not relevant, the signature for the imported CallNextHookEx can be changed to define lParam as System.IntPtr.

Removing the hook

The last step in processing the hook is to remove it when the instance of the KeyboardHook class is destroyed, using the UnhookWindowsHookEx function imported from user32.dll as follows.

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

Since KeyboardHook implements IDisposable, this can be done in the Dispose method.

public void Dispose()
{
  UnhookWindowsHookEx(hookID);
}

hookID is the id returned by the call to SetWindowsHookEx in the constructor. This removes the application from the hook chain.

Sources

Here are some good sources on Windows hooks in C# and in general:

It seems that articles in any language seem to attract at least one response on the lines of "how do I do the same thing in (some other language)?", so here are some samples I found:

And nothing to do with Windows API hooks or C#, but I would like to recommend Mike Ellison's excellent Word 2003 template if you're ever planning to write an article for Code Project!

History

  • 1.4 (23 Mar 07) - Fixed a bug which made Alt key appear stuck when the program exited:
    • Changed
      if (nCode >= 0 && (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP))
      to
      if (nCode >= 0)<br />
      {<br />
        if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)

      Many thanks to "Scottie Numbnuts" for the solution.
  • 1.3 (13 Feb 07) - Improved modifier key support:
    • Added CheckModifiers() method
    • Deleted LoWord/HiWord methods as they weren't necessary
    • Implemented Barry Dorman's suggestion to AND GetKeyState values with 0x8000 to get their result
  • 1.2 (10 Jul 06) - Added support for modifier keys:
    • Changed filter in HookCallback to WM_KEYUP instead of WM_KEYDOWN
    • Imported GetKeyState from user32.dll
    • Moved native DLL imports to a separate internal class as this is a Good Idea according to Microsoft's guidelines
  • 1.1 (18 Jun 06) - Modified proc assignment in constructor to make class backward compatible with 2003.
  • 1.0 (17 Jun 06) - First version published on Code Project.

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

About the Author

Emma Burrows
Web Developer
United Kingdom United Kingdom
Member
Emma's first steps in programming took place at primary school over thirty years ago, thanks to a TI-99/4A and the LOGO language. Following a Master's degree in English Studies (obtained, strangely enough, with a paper on the birth of the microcomputer), Emma started her career in IT.
 
Over the last ten years, she has worked as a localiser, technical writer, editor, web designer, systems administrator, team leader and support engineer for companies ranging from Microsoft to the more modest British software company Equisys. After all this, Emma recently found her dream job as an XSLT developer for a pharmaceutical publishing company, and is thrilled that she's finally getting paid for coding after doing it for free half her life.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralThankyoumemberGun Gun Febrianza22 Aug '12 - 8:58 
oh god thank you this article help me Smile | :)
Indonesian IT Intelijensi
Freedom of Revealing And Sharing Knowledge.
 
<img src="http://i564.photobucket.com/albums/ss86/febrianza/558392_461174860568975_902574845_n-1.jpg" border="0" alt="Photobucket">
 
www.net-sourcecode.blogspot.com

GeneralMy vote of 5memberGun Gun Febrianza22 Aug '12 - 8:58 
nice one Smile | :)
GeneralMy vote of 5memberakram_alhomedi2 Jun '12 - 4:01 
very excellent , thanks too much
GeneralMy vote of 5membermanoj kumar choubey12 Mar '12 - 21:55 
Nice
QuestionThanks a lot for this hookmemberchrispizz9117 Nov '11 - 10:48 
Very interesting to understand Kernel32 usings
Chris
GeneralIt doesn't stop keyboard outputmembermendy aaron26 May '11 - 10:59 
Hi.
 
I thought the program was supposed to intercept the keystrokes.
But when I change the form to normal ( not maximized ) and go to notepad,
I can see the keys in notepad as well as drawing on the form.
 
Can you tell me how to disable it?
I think the config setting is correct.
 
<add key="KeyboardHookConfig" value="None"/>
 
Thanks.
GeneralMy vote of 5membervahapdemir11 May '11 - 1:32 
Very simple to understand keyboard hooks. Worked well. Thanks a lot.
Generalthanks!memberalejandro29A28 Jan '11 - 2:27 
very nice emma! just what i need now!
Dios existe pero duerme...
Sus pesadillas son nuestra existencia.
(Ernesto Sabato)

GeneralNumLock key appears to be stuckmemberrajdey122 Jun '10 - 17:45 
Hi
It was a great article to read through but when went to into details i found that if the NumLock key is preesed while the windows hook code was active than NumLOck key Appear Stuck...
 
Would be happy if some one can fix the bug i have tried but failed in this regard
 

Hope someone will be able to fix the bug
GeneralGreat Work...memberahsan sarfraz20 Jan '10 - 18:50 
I was in search of these keyyboard hooks n have been trying different things to control thenm ...but useless...
you have done a great job ,.. it was very very very helpful to me.
tahnk you
regards
 
AHSAN SARFRAZ
UNIVERSITY OF ENGINEERING AND TECHNOLOGY TAXILA PAKISTAN
COMPUTER SYSTEM ENGINEERING DEPARTEMENT

GeneralwelldonememberMember 198406222 Dec '09 - 23:19 
Nice Article Emaa keep up the goodThumbs Up | :thumbsup: work
GeneralKeyboard eventsmembervinodachu8 Oct '09 - 21:58 
thanks a lot
GeneralWinForms Keys to WPF KeysmemberSpacelord_XaN28 Apr '09 - 23:48 
Thanks for that great Article!
 
If someone needs it I found this:
 
How to convert Form keys to Wpf Keys?
Generalthanksmemberc8709166 Apr '09 - 22:01 
thank you for your help Poke tongue | ;-P
QuestionHello Emma .... Its Doing so in ASP.NETWEBSITE?memberLuizItatiba4 Mar '09 - 8:52 
Would do this or adapt the code in ASP.NET AJAX ENABLED WEB APPLICATION PROJECTS AND ASP.NET WEBSITES.Se would rather have the procedure as example?
 

I look at now and I thank
 
Translated from Portuguese into English by Google
 
LADEF

QuestionHello Emma. need your help.memberdhaddo2 Mar '09 - 8:26 
Hello,
 
For one of my academic projects requirement, I want to make program which will take input from user and act for the game as input for the game(take input from my program which will be output for game). However for other applications its working just fine but it is not working for games due to some game guard or game listener. I need to bypass the GG or place kbrd input on such file that game would take the input. Please help me.
 
Regards,
Haris
GeneralThanksmemberflaunt20 Dec '08 - 8:54 
This was a good starting point for what i'm trying to do.
GeneralNew WPF Version AvailablememberBarryDorman26 Nov '08 - 8:53 
Hi Emma, my daughter has spent hours in front of this application over the past year. Thanks for your great contribution.
 
I wanted to let you (and anyone else interested) know that I've uploaded a similar application written in WPF. You can view it here - http://www.codeproject.com/KB/cs/ShapeShow.aspx
 
Thanks!
QuestionHelp! Demo works but seems to have a memory issue.membercflux11 Sep '08 - 17:29 
Hi first I want to say excellent article. But I was playing with the example code and noticed that the applications process memory resources keeps increasing as more keys are pressed. Is anyone else seeing this behavior? Does anyone know why this is happening or how to fix it?
 
Thanks
GeneralExcellent workmemberjtradke28 Aug '08 - 16:37 
Hi - just wanted to say that I'm using your code in a new open source project I'm working on (linked below). It pops up an OSD notification when you press CAPSLOCK, NUMLOCK, etc. Thanks!
 
http://code.google.com/p/lock-osd/
QuestionEsc key acts as toggle?membermikedrummo6 Jul '08 - 23:27 
I am only using GetKeyState in VBA to see if the Escape key is pressed when I select some Excel cells.
Res = GetKeyState(vbKeyEscape)
 
The result are that the Esc key acts as a toggle.
 
I haven't found any documentation about this yet.
 
Can you offer any help?
 
thanks
Mike
QuestionHelp! How come using this class as a Console App doesn't work?membertroy4u1 Jul '08 - 22:13 
I used the supplied Keyboard.cs with 2 different types of apps:
 
Both apps were setup almost in the exact same way.
 
1. Windows Forms: worked perfectly
2. Console App: call backs won't fire
 
Is there a reason why a Win Form is needed? Can it work with a console app somehow?
 
ThanksConfused | :confused:
QuestionRe: Help! How come using this class as a Console App doesn't work?membertroy4u1 Jul '08 - 23:11 
I found out the problem. I forgot to call Application.Run() which creates the needed windows message pump.
Now here's a more interesting problem, how do I hook up a message pump with a windows service?
 
i.e. something that inherits from System.ServiceProcess.ServiceBase
 
I see no good place to add the pump and still have the service run properly.
Any advice would be great!Unsure | :~
AnswerRe: Help! How come using this class as a Console App doesn't work?memberWashier29 Jul '10 - 23:42 
Hi,
 
Found a way to start a message pump, it's not pretty though :
Before starting the service via ServiceBase.Run(MyService), start a thread that creates the hook and calls Application.Run()
 
Also be sure to run the service under the Local System Account - you may need to check the "Allow application to interact with desktop" option in the service properties dialog.
QuestionHow to neutralize keyboard for one form rather than the entire application?memberjonny_chympo26 Jun '08 - 8:27 
Great article Emma!
 
I was previously using code from this website (which has a great method for disabling ctrl+alt+del for those interested..): [^]
but found that the keyboard hook was not functioning properly and causing unhandled exceptions for some odd reason...
 
I was lucky to stumble upon your article and your method works perfectly!
 
I was wondering how I might be able to use your code in order to disable the keyboard for just one form in my application??
So instead of:
public static KeyboardHook kh;
 
[STAThread]
static void Main()
{
  //Other code

  using (kh = new KeyboardHook())
  {
    Application.Run(new Form1());
  }
}
I would like to use it in the following manner:
public partial class Form A : Form
    {
 
        public static KeyboardHook kh;
        
        //.....

        private void Button_Click(object sender, EventArgs e)
        {
            using (kh = new KeyboardHook())
            {
                FormB b = new FormB(param1, param2);
                b.Show();
            }
              
        }
    }
Is this possible? The code compiles and runs but the keyboard hooks are not working in Form B - all the keys are still active. Is there another way to do it? Maybe without the "using" block?
 
Thanks a lot! Again, great article!
QuestionHow to prevent keyboard's event raise?memberhoangnguyenletran10 Mar '08 - 23:49 
Hi,
 
I appreciate your program. However, now I'm in stuck with how to lock keyboards, it means prevent keyboard's event raised, including media keys, browser keys and extra keys. Because when my app is running, I don't want user can do anything else even press CTRL TAB, ALT TAB, CTRL ALT DEL or anything else. Please response me asap.
 
I am looking forward to hearing from you. Thank you so much for your time
QuestionWindows servicememberleecha6 Nov '07 - 22:59 
Hello,
 
Does anybody tried to use this in windows service, and if it's posible please respond.
10x !
AnswerRe: Windows servicememberSandeep Aparajit15 May '08 - 2:30 
I dont think it is possible, since a Windows service is started even before you logon to the system. On a server machine like Windows 2003 server, their can be n-number of logons i.e. number of different user sessions at a time. Hence if a key is presses it would be difficult to know in which session and on which window the key was presses. One more reason is Operating System security.
 
Well, this is just a guess, Im not very sure if it is possible.
 
------------------------------
Sandeep Aparajit
Mark usefull posts as Helpful/Answers.
http://sandeep-aparajit.blogspot.com

GeneralA suggestionmemberMohamad K Ayash5 Sep '07 - 4:09 
Very good work but let me suggest you tell the readers how windows kernel does a hook since a lot may be wondering about this, the answer is that when a key is pressed it goes to a port in the computer numbered 0x60 and then the scan code( a special representation of the key pressed) goes to interrupt 0x9 and their the opearating system retrieve the key and interpret it so to hook we can program the interrupt to ignore some keys and poof its hooked...
 
Best Wishes...
 
To follow the path, Walk with the MASTER, See through the MASTER, Be the MASTER!

GeneralCtrl and Windows keymemberdigfreelancer14 Aug '07 - 4:50 
I want all keys are allows to pass to next applications accepts Ctrl and Windows key. Please help...
GeneralProblems when hooking to the Esc keymemberZoltan Balazs30 May '07 - 5:17 
I played around with the solution attached to the article and noticed the following:
if I try to display a window of any kind to the user as a response to the Esc key
the application becomes iresponsive. It just locks for a few seconds. Have you got any ideas
what's going on?
 
I replaced the kh_KeyIntercepted method as follows:
void kh_KeyIntercepted(KeyboardHook.KeyboardHookEventArgs e)
{
   switch (e.KeyCode)
   {
      case (int)Keys.Escape:
          MessageBox.Show("test"); 
          break;
   }
}

 

GeneralNormally using the keystrokes in my appmemberJohannesAckermann24 May '07 - 4:58 
Great article! One problem, and I'm sure I'm just being a total moron:
The class you supplied block all the keystrokes wonderfully... so wonderfully in fact that even my own app doesn't see them! My question is this: without having to resort to SenKeys or something like that in the KeyHook event handler, how can I make my app accept keys as per usual but simply block any other apps from receiving them?
I'm basically writing a standard app that must be the ONLY app accessable by the user of the PC. There is a close button which only closes the app if a correct password is entered. That's beside the point... the problem is that my app is just standard WindowsForms with textboxes etc. Implementing this class as is and doing nothing with the hooked keys results in my own app not getting the keystrokes... i.e. typing in a textbox does nothing. Now, can I somehow just let my app handle its own input, but block the rest (alt-tab,windowskey, etc)?
 
thanks in advance!
 
Johannes
GeneralRe: Normally using the keystrokes in my appmemberEmma Burrows24 May '07 - 7:27 
Have a look at form1.cs in the VS 2003 or 2005 sample projects to see how my sample application handles the keystrokes before they are blocked. Basically, you attach a handler to the keyboard class's KeyIntercepted event, and then you do whatever you want to do with the intercepted key strokes in the handler. In my case, I pass the info to another class to display coloured text or shapes.
 
HTH
GeneralRe: Normally using the keystrokes in my appmemberJohannesAckermann24 May '07 - 9:35 
Hi,
 
Thanks for the reply.
 
I get exactly what you do in the sample, but it still doesn't solve my problem:
Let's say I've got a standard textbox. The user clicks inside the textbox and start typing. Now the keyboard hook catches each key press, so the textbox doesn't get the keypress. The only way I managed to get the key passed on to the textbox as per usual is by calling SendKey, but this is not really a solution. Firstly it seems to be extremely slow, and secondly I have to write a uge switch statment to see if the key was a special key, because SendKey.Send wants special keys in curly braces, and characters as standard. I can't just pass everything in curly braces, because then all letter appear as capitals... which is the key, not the character. Also checking for Shift etc... it all becomes extremely complicated. Holding a key down also causes problem, like holding down Backspace made the app crash.
 
I basically just want my app to accept keypresses as per usual... e.g. when typing text into a text box I don't want to have to manually interperet what is being typed. All I actually want is to trap and discard System-wide key presses like Alt-Tab, the Windows Key etc.
 
Maybe I'm missing something simple in your documentation, and it is highly likely that I'm just being stupid, but I can't figure it out. Sorry!
 
Any advice would be greatly appreciated!
 
Johannes
QuestionCheckModifiers() incorrect on VistamemberDarkInGray30 Apr '07 - 17:55 
Hi Emma, nice work, deeply appreciated.Blush | :O
Ever tested on Windows Vista?
I ran demo code on two Vista machines and found "AllowAltTabAndWindows" mechanism does not work.
I traced into the CheckModifiers() method, it seems that GetKeyState result bit test are not reflecting the actual key-up states.
I'm not good enough at DLLImport interOps, so why those modifier bits incorrect are still mysterious to me.
I'm using VS2005 SP1 + KS2005_SP1_Vista_20070306
 
Thanks,
DarkInGray
QuestionHandling % charactermembergkowaljow11 Apr '07 - 10:05 
Hello, I'm trying to use this class with a magnetic card reader.
All the cards begin with a % simbol, the idea is to handle the keys pressed between the % and return (13). I´ve made some modifications to the code myself but I can´t solve the next problem.
 
% is made by 2 keys 160 (LeftShift) y 53 (5), so, I have to handle the keyup only when the previous key was 160 and the current key is 53, I thought that if I only handle the 53, it won't be a problem to let pass the Shift, but I can´t make the % handle, all the rest of the code untill the return works fine, but the % allways is displayed on screen.
 
Anybody knows some algorithm to make this work?
Thanks a millon in advance.
GK
GeneralWindows Keyboard LockmemberMuhammed Sahin27 Mar '07 - 22:28 
Hi,
 
This realy good works. But i have a question. Why lock my keyboard use this class. I can't press any key in windows just mouse.
GeneralRe: Windows Keyboard LockmemberEmma Burrows24 Apr '07 - 4:57 
Sorry for the late response - I only just saw your question. Unfortunately, I'm not quite sure what you're asking. The purpose of the code is to prevent the keyboard from having any effect. In other words, you press a key and nothing happens - if this is what you're getting, then that's the whole point of the code. It's what it's designed to do. But let me know if I've misunderstood your question.
GeneralNot Behavingmemberscottie_numbnuts22 Mar '07 - 19:00 
I've been having problems with this code not behaving when the application exits. I've worked out what was causing my problems. The example seems to only check for keyup events. This means that all the keydown events are still being passed to the processes further down the hook chain. Thus simulating a stuck key to the operating system.
 
If you want to stop the keystrokes you need to stop all the events from being passed through. Simply change the If statement in the HookCallBack method
 
From:
 
if (nCode >= 0 && (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP))
 
To:
 
if (nCode >= 0)
 

GeneralRe: Not BehavingmemberEmma Burrows23 Mar '07 - 7:14 
Good piece of troubleshooting! This sounds like it could be the solution to the problems some people have reported concerning the Alt key in particular. Because that seemed to be the only key affected, it didn't occur to me that all the WM_KEYDOWN messages were still getting through! Blush | :O
 
I'll have a play with it and see about making a version 1.4. Thanks again for the info!
GeneralRe: Not Behavingmemberscottie_numbnuts25 Mar '07 - 18:57 
Glad I could be of help.Smile | :)
 
I wasn't 100% sure how to use your modifiers method so I made my own with an array list. If you're interested I'll send it to you.
 
Scott.
QuestionAlt-Tab causes troublememberkfawell6 Mar '07 - 21:13 
Hello,
 
When I run the program and type the combo of Alt-Tab, the pop-up showing the processes actually gets shown. However, the process chosen is ignored. In other words, it seems that all keys combinations are ignored except Alt-Tab. And Alt-Tab does not work quite right even though it does "get through". Finally, after using Alt-Tab and exiting the program by clicking the close-box in the upper-right corner, some keys are temporarily suppressed for a short time, like 10 or 15 seconds. For example, pressing the Windows key does open the Start menu.
 
In short, Alt-Tab does not get "fully" suppressed.
 
Does this happen to you? Any ideas why it is happening on my machine?
 
Thank you.
AnswerRe: Alt-Tab causes troublememberscottie_numbnuts7 Mar '07 - 16:15 
I'm having a very similar problem, except instead of supressing keys it seems to be locking random modifier keys on. If I press 'l' key after exiting the program it locks the computer, implying that Windows believes I'm holding down the Start(Windows) key. It doesn't last just a few seconds, it stays that way for about 3 or 4 minutes.
 
I haven't implemented it quite the way Emma shows. I declare KeyboardHook as a global in a form and then initialize it in the Form_Load method.
 
I've tried calling KeyboardHook.Dispose as the form is closing and also assigning null to variable, none of which has made any difference.
 
I'm using VS2005.
 
ThanksSmile | :)
QuestionQuestion, about DirectXmembergehannan archmage3 Mar '07 - 8:22 
I am new to C# and looking to make an application and have found your article that is close to want I need, I think? I am looking to artifically create a keypress and have been attempting to figure out your code. This is way above me currently and was hoping that you could tell me if an artifical keypress is possible? I am looking to have some event happen and then have the Enter key pressed or the Space key pressed. I also would like this to be able to go to another application. I have been trying the below code out below but does not seem to work and do not know enough about it to understand why it is failing.
 
So when I need an 'Enter' pressed.
 
Program.kh.OnKeyIntercepted((new BattleClient.KeyboardHook.KeyboardHookEventArgs(asciiValue, true)));
 
Am I completely in the wrong ball field here?

AnswerRe: Question, about DirectXmembergehannan archmage5 Mar '07 - 9:51 
I messed with this most of Sunday and was unable to figure out a way to capture the keypress and then re-direct, that press as something else. So, a real 'a' pressed is re-directed into a fake but real 'b' press. Has anyone been able to do this with DirectX?
GeneralRe: Question, about DirectXmemberEmma Burrows6 Mar '07 - 2:33 
Sorry for the late response - I've been busy with other things. You're not the first person who has asked me how to convert keystrokes like this. Unfortunately, my code doesn't do it - it either passes the original keystroke or nothing at all. You can use SendKeys to add keystrokes but the original ones still go through as well. I've done no work with DirectX, so I don't know if that would help or not.
 
However, in response to someone else's question below[^], Daniel Pistelli suggested a method which involved using my code to trap the keystroke, and then sending a message to another process which actually generates the replacement key. It's not beginner material, though, and I haven't tested it myself so I don't know how easy it would be to implement.
 
Converting keystrokes is such a popular request that I'm surprised no one has written an article about it. Smile | :)
Question"Repair" stuck key?memberRaymond Verbruggen14 Feb '07 - 22:57 
Hello,
 
I have an old notebook which has the F12 key stuck.
Could I use this demo program to run in background to filter away all F12 key actions, and still use all of my applications?
 
Kindest regards
Raymond Verbruggen
Netherlands
AnswerRe: "Repair" stuck key?memberJamie Nordmeyer19 Feb '07 - 10:27 
System level hooks like this one are very low level, and while useful, can chew up your CPU cycles if they're constantly processing. You can try it and see how well it works in your situation, but I'd think that a constantly striking key would bring your system to a halt. Again, try it and see. You never know. Smile | :)
 
Kyosa Jamie Nordmeyer - Taekwondo Yi (2nd) Dan
Portland, Oregon, USA
www.defaultn.com

GeneralRe: "Repair" stuck key?memberRaymond Verbruggen24 Feb '07 - 10:30 
Hey everybody,
 
I'm glad to mention; it works fine!
 
I've captured the F12 keycode (which was the stucked key) and sent everything else to the next application.
Also I have minimized the key repetition delay time and key repetition speed.
 
CPU load absolute minimum.
 
Thanks a lot for the code!
 
Raymond
Netherlands
GeneralGreatmemberNavneet Hegde14 Feb '07 - 1:49 
Emma its great to get such a wonderful code , it refreshed my :-ObrainRose | [Rose]
 
Develop2Program & Program2Develop

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 26 Mar 2007
Article Copyright 2006 by Emma Burrows
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid