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

A Simple C# Global Low Level Keyboard Hook

By , 30 May 2007
 
Screenshot - key_preview.jpg

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:

private void Form1_Load(object sender, EventArgs e) {
    gkh.HookedKeys.Add(Keys.A);
    gkh.HookedKeys.Add(Keys.B);
    gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
    gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
} 

void gkh_KeyUp(object sender, KeyEventArgs e) {
    lstLog.Items.Add("Up\t" + e.KeyCode.ToString());
    e.Handled = true ;
}

void gkh_KeyDown(object sender, KeyEventArgs e) {
    lstLog.Items.Add("Down\t" + e.KeyCode.ToString());
    e.Handled = true ;
} 

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.

[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx
    (int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);

The parameters were worked out to be:

IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);

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.

History

  • 5/30/07 - First version

License

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

About the Author

StormySpike
Software Developer
United States United States
Member
I currently work as a Software Engineer for a company in North Carolina, mainly working with C#.

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   
GeneralMy vote of 5 PinmemberAnotherKen15 May '13 - 20:52 
This is exactly what I needed for a project I am working with. In very little time I had it detecting a control sequence while another application had focus. Perfect. Thank you for sharing this.
QuestionUsing this class in a WPF application PinmemberVSZM14 Apr '13 - 12:47 
Hello!
 
I would like to use this class in a WPF application. I am kinda new to WPF and Winforms, can anybody give me hints about what to modify on the original class, or how to use it with WPF?
QuestionATT: Developer of (Simple-C-Global-Low-Level-Keyboard-Hook) PinmemberDJBruteForce5 Apr '13 - 2:17 
The code does not work for Framework 4 or higher. Please update Smile | :)
 
Error at (
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]
)
 
This needs to be replaced with:
 
GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName)
 
and the DLL for GetModuleHandle:
 
[DllImport("kernel32.dll")]
    public static extern IntPtr GetModuleHandle(string name);
 

Good stuff.
Cheers Smile | :)
BugA callback was made on a garbage collected delegate of type .... PinmemberMember 41208549 Jan '13 - 22:52 
Hi there,
 
you have no reference of the callback-method.
 
After:
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
 
just add a new line with:
private keyboardHookProc _keyboardHookProc;
 
And in function "hook" you have to change code to:
hInstance = LoadLibrary("User32");
_keyboardHookProc = new keyboardHookProc(hookProc);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboardHookProc, hInstance, 0);
 
with these changes the delegate won't be garbage collected
BugI need help PinmemberMember 97217003 Jan '13 - 1:18 
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.
GeneralRe: I need help PinmemberJean Meyblum9 Jan '13 - 20:49 
GeneralThx for Nice Article PinmemberiHUPPz Rwt7 Sep '12 - 8:26 
It's good A Simple C# I hope this will be fun Big Grin | :-D
QuestionAnti Virus - Because of Set Windows Hook Pinmemberaces277 Sep '12 - 3:50 
1 . Usually Anti Viruses are not happy to see Set Windows Hook
This 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.
 
Thanks.
Question32 Bit / 64 Bit Pinmemberaces277 Sep '12 - 3:47 
Please explain how this would behave for a 32 bit Windows system and a 64 bit system.
Will a build compiled in a 32 bit system work on a 64 bit machine and vice versa ?
Any other points to consider.
Questionhow to avoid repeated pressing of a key PinmemberIgorBogomolov6 Sep '12 - 11:16 
only I have a question: how to avoid repeated pressing of a key.
I need only one pressing
GeneralMy vote of 5 PinmemberIgorBogomolov6 Sep '12 - 11:13 
thanks, it was very useful to me
Bugnot stable PinmemberMartype2.028 Aug '12 - 22:54 
it stops working after some key strokes have been made. i do the following to get a double press event for the control button:
 
DateTime ctrlPressedOnce = DateTime.MinValue;
 
void gkh_KeyDown(object sender, KeyEventArgs e)
       {
           if (e.KeyCode == Keys.LControlKey)
           {
               TimeSpan ctrlActionSpan = DateTime.Now - ctrlPressedOnce;
 
               if (ctrlPressedOnce == DateTime.MinValue)
                   ctrlPressedOnce = DateTime.Now;
               else if (ctrlActionSpan.Seconds == 0 && ctrlActionSpan.Milliseconds < 500)
               {
                    ctrlPressedOnce = DateTime.MinValue;
                    MessageBox.Show("OK");
               }
               else
               {
                   ctrlPressedOnce = DateTime.MinValue;
               }
           }
           else
           {
               ctrlPressedOnce = DateTime.MinValue;
           }
 
           e.Handled = true;
       }
 
the first time i double tap my control button all works fine. but the second or sometimes the third time the gkh_KeyDown event simply is not fired anymore. please fix this.
GeneralAdding Modifier Key Handling using GetKeyState Pinmemberjonegerton20 Aug '12 - 21:55 
Modifier handling can be added to work on the global hook by adding GetKeyState to the globalKeyboardHook class.
 
This can be done in such a way the KeyEventArgs passed in the events have their Control, Alt and Shift properties correctly set.
 
I've blogged on how to do this, including a full version of globalKeyboardHook with the extra code built in, here.
GeneralRe: Adding Modifier Key Handling using GetKeyState PinmemberVSZM14 Apr '13 - 13:22 
QuestionHow to hook combination of keys, not one by one ? PinmemberNithrouS1 Aug '12 - 12:01 
For example LControl + Printscreen, but only combination.
GeneralMy vote of 4 PinmemberBurak Tunçbilek27 Jul '12 - 10:06 
thank you
Suggestionsuggestion for improvement PinmemberChristoph Strehle12 May '12 - 7:15 
To avoid problems with the GC you should keep a reference to the delegate.
Something like:
 
 75          keyboardHookProc proc;
 76          public void hook() {
 77              IntPtr hInstance = LoadLibrary("User32");
 78              proc = new keyboardHookProc(hookProc);
 79              hhook = SetWindowsHookEx(WH_KEYBOARD_LL, proc, hInstance, 0);
 
Otherwise an CallbackOnCollectedDelegate exception can occur.
Questionabout the Shift+A does not work Pinmemberlsh201113 Nov '11 - 21:07 
sir,If I want to hook combination key,such as Shift+A,
the setup code gkh.HookedKeys.Add(Keys.A & Keys.Control);
does't work, please help me.
GeneralMy vote of 5 PinmemberAdelino Araújo10 Nov '11 - 3:03 
works on c# 2010 express, simple to use, thanks
GeneralMy vote of 5 Pinmembermr_Prankster16 Aug '11 - 4:25 
Thanks)
QuestionCan it run without the .NET framework Pinmemberaces2723 Jul '11 - 21:02 
Hi ,
Is it possible to run this without the .NET framework installed on the Windows system.
 
If not , then let us think of alternates.
A low level hook should be pretty compatible every place.
QuestionHow to send small letters with SHIFT key using SendKeys.Send? [modified] PinmemberShrish Pandit26 Mar '11 - 4:58 
I am unable to send small letters using SendKeys.Send() with SHIFT modifier key pressed. My app needs (for example) if the user presses K button "a" should be sent and if he presses SHIFT+K, "b" should be sent. The code is:
 
void gkh_KeyDown(object sender, KeyEventArgs e)
{
	if (e.KeyCode == Keys.K)
	{
		if (Control.ModifierKeys == Keys.Shift)
			SendKeys.Send("b");
		else
			SendKeys.Send("a");
	}
        e.Handled == true;   
}
 
But it sends "B" (Capital letter) instead of "b", that is the SHIFT key changes the sent keystroke "b" to uppercase. This happens even after adding Keys.Shift to the hook.
 
I tried many approaches including using e.SupressKeyPress, SendKeys("b".toLower()) and putting above code in KeyUp event but in vein.
 
Pls help me, I am very frustated, my application developement is struck at this point.
modified on Saturday, March 26, 2011 11:19 AM

GeneralKey Modifiers - Shift and Symbols Pinmemberaces2724 Mar '11 - 21:19 
Hi ,
Can you please give some light on how to use this to make is case sensitive and
also to detect symbols like " , .;: / ? etc.
 
Tried using ASCII value , but e.Modifier , e.Shift are always None.
 
And No Idea how to approach for the special symbol keys , and to get the ones Shift + numbers.
 
Minor modifications or guidelines , please provide any insight.
 
Thanks
 
Aces J
AnswerRe: Key Modifiers - Shift and Symbols [modified] PinmemberShrish Pandit25 Mar '11 - 15:52 
QuestionModifiers? Pinmemberf r i s c h24 Mar '11 - 11:09 
They seem not to be working. It always says Modifiers None even if i am holding Shift/Ctrl/Alt.
AnswerRe: Modifiers? Pinmemberaces2724 Mar '11 - 21:21 
GeneralThanks! PinmemberAshenafiD.6 Feb '11 - 21:07 
Great Code!
Thank you a lot!
Generalproblem with keyboardhook Pinmembermahboobeh mohamadi31 Jan '11 - 19:57 
hi StormySpike
tnx for your great atricle.
but i have a problem,actually when i use keyboardhook to hook a key and send it for active window with sendkey() i have this error:
A callback was made on a garbage collected delegate of type 'keyboardhook!Utilities.globalKeyboardHook+keyboar dHookProc::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. 
 

most time when i press a key(that i hooked it) and press a key and keep it down it for a long time.(i press a key and keep my finger on that).
and this id my code:
************
gkh.HookedKeys.Add(Keys.OemPipe);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
***********
void gkh_KeyDown(object sender, KeyEventArgs e)
        {
            if (stringgetName() == "00000429")
            {
                Char ch_Ye = (Char)1740;
                Char ch_K = (Char)1705;
                Char ch_P = (Char)1662;
                Char ch_Zh = (Char)1688;
 
                switch (e.KeyCode)
                {
                    case Keys.D:
                        System.Windows.Forms.SendKeys.Send(ch_Ye.ToString());
                        break;
                    case Keys.OemSemicolon:
                        System.Windows.Forms.SendKeys.Send(ch_K.ToString());
                        break;
                    case Keys.Oemtilde:
                        System.Windows.Forms.SendKeys.Send(ch_P.ToString());
                        break;
                    case Keys.OemPipe:
                        System.Windows.Forms.SendKeys.Send(ch_Zh.ToString());
                        break;
                }
                e.Handled = true;
            }
        }
tnx for your attention.
و این منم زنی تنها در آستانه فصلی سرد...

QuestionUrgent Help NEEDED ! PinmemberMuthu7726 Jan '11 - 15:43 
Hi Guys,
 
Does anyone know how to apply this code to Windows Service on Windows 7.
Windows Service is unable to detect KeyEventHandler in the code even though
I added Windows Form in the NameSpace.
 
Thank you for any help provided.
mk77

GeneralWindows Service PinmemberMuthu7725 Jan '11 - 1:32 
How do I use this for Windows Service?
I tried it on Win Service but it does not recognise
the keyevent handler
mk77

GeneralMy vote of 5 PinmemberLevon Hovhannisyan21 Dec '10 - 5:49 
very useful
GeneralCallbackOnCollectedDelegate Exception PinmemberGrangeJM18 Dec '10 - 23:42 
The sample works fine but in more sophisticated mdi interface you get a CallbackOnCollectedDelegate Exception.
 
To avoid this porblem just change code.
 
Replace
 

public void hook() {
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
}

 
by
 

public void hook() {
IntPtr hInstance = LoadLibrary("User32");
// Avoid CallbackOnCollectedDelegate Exception
// when calling delegates from unmanaged code
hkbProc = new keyboardHookProc(hookProc);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hkbProc, hInstance, 0);
}

Jean-Michel Grange

GeneralRe: CallbackOnCollectedDelegate Exception Pinmembermahboobeh mohamadi31 Jan '11 - 22:51 
GeneralRe: CallbackOnCollectedDelegate Exception PinmemberLeye011 Apr '12 - 22:13 
GeneralAwesome! PinmemberKhoiTran197 Dec '10 - 17:45 
This is the simplest and neatest hook code I have seen. Can you make one like that to hook keyboards too?
GeneralMy vote of 5 Pinmembermesuhas_sit7 Dec '10 - 16:52 
Thanks StormySpike...
Helped me to learn a lot..
Generalctrl+alt+i Pinmemberpukino18030 Sep '10 - 10:13 
can also do Ctrl + alt + i? :(
GeneralRe: ctrl+alt+i PinmemberDungVinh12 Feb '12 - 23:48 
QuestionForeign characters? Pinmemberlvq68411 Sep '10 - 2:36 
How do you add characters to the hook like danish æ, ø and å. Or other european special characters?
GeneralAll keys PinmemberMember 724777630 Jul '10 - 5:35 
Is it possible to do with all keys? Also KeyPress event would be nice
GeneralRe: All keys Pinmemberjrbosch2 Jan '11 - 21:47 
GeneralMy vote of 4 Pinmemberangelamerkel28 Jun '10 - 10:11 
error garbage collected delegate but solution in ocmments
GeneralMy vote of 1 PinmemberMember 356761318 Jun '10 - 1:38 
it crash when we type very fast
QuestionKey combination like CTRL+ALT+A? Pinmemberuhcafigdc4 Jun '10 - 9:03 
Is there a way to capture a key combination like CTRL+ALT+A, where those three keys are pressed simultaneously?
General[My vote of 2] Sorry not perfect... Pinmemberjohannesnestler25 May '10 - 23:50 
Have a look at your marshalling! (Attributes) Your code can lead to some (seldom but nasty) errors.
So sorry for the bad vote but your code seems to be reused by a lot of people, i will revote if you improve your code.
A good site is: http://www.pinvoke.net[^]
Maybe you are also interested in the way I get the Instance handle for the process containing the callback.
 
Have a look at the code I use for a keyboard hook:
 
/* File: GlobalKeyboardHook.cs
 * Proj: Common
 * Date: 20.03.2009
 * Desc: GlobalKeyboardHook - Helper class for global (system-wide) keyboard hooks. 
 * Elem: CLASS GlobalKeyboardHook - -"-
 * Auth: © Johannes Nestler 2009 */
 

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 

namespace Common
{
    #region CLASS GlobalKeyboardHook
 
    /// <summary>
    /// Helper class for global (system-wide) keyboard hooks.
    /// </summary>        
    public class GlobalKeyboardHook
    {
        #region TYPES
 
        #region CLASS KeyboardHookStruct
 
        /// <summary>
        /// Marshalling of the Windows-API KBDLLHOOKSTRUCT structure.#
        /// Contains information about a low-level keyboard input event.
        /// This is named "struct" to be consistent with the Windows API name,
        /// but it must be a class since it is passed as a pointer in SetWindowsHookEx.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        class KeyboardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
 
        #endregion // CLASS KeyboardHookStruct

        #region DELEGATE HookProc
 
        /// <summary>
        /// Represents the method called when a hook catches a monitored event.
        protected delegate int HookProc(int nCode, int wParam, IntPtr lParam);
 
        #endregion // DELEGATE HookProc

        #endregion // TYPES

        #region CONSTANTS
 
        const int WH_KEYBOARD_LL = 13;
        const int WH_KEYBOARD = 2;
 
        const int WM_KEYDOWN = 0x100;
        const int WM_KEYUP = 0x101;
        const int WM_SYSKEYDOWN = 0x104;
        const int WM_SYSKEYUP = 0x105;
 
        const byte VK_SHIFT = 0x10;
        const byte VK_CAPITAL = 0x14;
        const byte VK_NUMLOCK = 0x90;
 
        const byte VK_LSHIFT = 0xA0;
        const byte VK_RSHIFT = 0xA1;
        const byte VK_LCONTROL = 0xA2;
        const byte VK_RCONTROL = 0x3;
        const byte VK_LALT = 0xA4;
        const byte VK_RALT = 0xA5;
 
        // const byte LLKHF_ALTDOWN = 0x20; // not used

        #endregion // CONSTANTS

        #region VARIABLES
 
        /// <summary>
        /// Value indicating if hook is active.
        /// </summary>
        bool m_bHookActive;
 
        /// <summary>
        /// Stored hook handle returned by SetWindowsHookEx
        /// </summary>
        int m_iHandleToHook;
 
        /// <summary>
        /// Stored reference to the HookProc delegate (to prevent delegate from beeing collected by GC!)
        /// </summary>
        protected HookProc m_hookproc;
 
        #endregion // VARIABLES

        #region EVENTS
 
        /// <summary>
        /// Occurs when a key is pressed.
        /// </summary>
        public event KeyEventHandler KeyDown;
        /// <summary>
        /// Occurs when a key is released.
        /// </summary>
        public event KeyEventHandler KeyUp;
        /// <summary>
        /// Occurs when a character key is pressed.
        /// </summary>
        public event KeyPressEventHandler KeyPress;
 
        #endregion // EVENTS

        #region CONSTRUCTION & DESTRUCTION
 
        /// <summary>
        /// Dtor.
        /// </summary>
        ~GlobalKeyboardHook()
        {
            Unhook();
        }
 
        #endregion // CONSTRUCTION & DESTRUCTION

        #region PROPERTIES
 
        /// <summary>
        /// Gets a value indicating if hook is active.
        /// </summary>
        public bool HookActive
        {
            get { return m_bHookActive; }
        }
 
        #endregion // PROPERTIES

        #region METHODS
 
        /// <summary>
        /// Install the global hook. 
        /// </summary>
        /// <returns> True if hook was successful, otherwise false. </returns>
        public bool Hook()
        {
            if(!m_bHookActive)
            {
                m_hookproc = new HookProc(HookCallbackProcedure);
 
                IntPtr hInstance = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
                m_iHandleToHook = SetWindowsHookEx(
                    WH_KEYBOARD_LL,
                    m_hookproc,
                    hInstance,
                    0);                
 
                if(m_iHandleToHook != 0)
                {
                    m_bHookActive = true;
                }
            }
            return m_bHookActive;
        }
 
        /// <summary>
        /// Uninstall the global hook.
        /// </summary>
        public void Unhook()
        {
            if(m_bHookActive)
            {
                UnhookWindowsHookEx(m_iHandleToHook);
                m_bHookActive = false;
            }
        }
 
        /// <summary>
        /// Raises the KeyDown event.
        /// </summary>
        /// <param name="kea"> KeyEventArgs </param>
        protected virtual void OnKeyDown(KeyEventArgs kea)
        {
            if(KeyDown != null)
                KeyDown(this, kea);
        }
 
        /// <summary>
        /// Raises the KeyUp event.
        /// </summary>
        /// <param name="kea"> KeyEventArgs </param>
        protected virtual void OnKeyUp(KeyEventArgs kea)
        {
            if(KeyUp != null)
                KeyUp(this, kea);
        }
 
        /// <summary>
        /// Raises the KeyPress event.
        /// </summary>
        /// <param name="kea"> KeyEventArgs </param>
        protected virtual void OnKeyPress(KeyPressEventArgs kpea)
        {
            if(KeyPress != null)
                KeyPress(this, kpea);
        }
 
        #endregion // METHODS

        #region EVENTHANDLER
 
        /// <summary>
        /// Called when hook is active and a key was pressed.
        /// </summary>
        int HookCallbackProcedure(int nCode, int wParam, IntPtr lParam)
        {
            bool bHandled = false;
 
            if(nCode > -1 && (KeyDown != null || KeyUp != null || KeyPress != null))
            {
                // Get keyboard data
                KeyboardHookStruct khs = (KeyboardHookStruct) Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
 
                // Get key states
                bool bControl = ((GetKeyState(VK_LCONTROL) & 0x80) != 0) || ((GetKeyState(VK_RCONTROL) & 0x80) != 0);
                bool bShift = ((GetKeyState(VK_LSHIFT) & 0x80) != 0) || ((GetKeyState(VK_RSHIFT) & 0x80) != 0);
                bool bAlt = ((GetKeyState(VK_LALT) & 0x80) != 0) || ((GetKeyState(VK_RALT) & 0x80) != 0);
                bool bCapslock = (GetKeyState(VK_CAPITAL) != 0);
 
                // Create KeyEventArgs 
                KeyEventArgs kea = new KeyEventArgs((Keys) (khs.vkCode |
                        (bControl ? (int) Keys.Control : 0) |
                        (bShift ? (int) Keys.Shift : 0) |
                        (bAlt ? (int) Keys.Alt : 0)));
 
                // Raise KeyDown/KeyUp events
                if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
                {
                    OnKeyDown(kea);
                    bHandled = kea.Handled;
                }
                else if(wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
                {
                    OnKeyUp(kea);
                    bHandled = kea.Handled;
                }
 
                // Raise KeyPress event
                if(wParam == WM_KEYDOWN && !bHandled && !kea.SuppressKeyPress)
                {
                    byte[] abyKeyState = new byte[256];
                    byte[] abyInBuffer = new byte[2];
                    GetKeyboardState(abyKeyState);
 
                    if(ToAscii(khs.vkCode, khs.scanCode, abyKeyState, abyInBuffer, khs.flags) == 1)
                    {
                        char chKey = (char) abyInBuffer[0];
                        if((bCapslock ^ bShift) && Char.IsLetter(chKey))
                            chKey = Char.ToUpper(chKey);
                        KeyPressEventArgs kpea = new KeyPressEventArgs(chKey);
                        OnKeyPress(kpea);
                        bHandled = kea.Handled;
                    }
                }
            }
 
            if(bHandled)
                return 1;
            else
                return CallNextHookEx(m_iHandleToHook, nCode, wParam, lParam);
        }
 
        #endregion // EVENTHANDLER

        #region EXTERN
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        static extern int UnhookWindowsHookEx(int idHook);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
 
        [DllImport("user32.dll")]
        static extern int GetKeyboardState(byte[] pbKeyState);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        static extern short GetKeyState(int vKey);
 
        [DllImport("user32.dll")]
        static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
 
        #endregion // EXTERN
    }
 
    #endregion // CLASS GlobalKeyboardHook
}
 
btw: This is .NET not Java - the convention is: type names start with capital letters...
GeneralRe: [My vote of 2] Sorry not perfect... PinmemberVHong99923 Sep '11 - 16:45 
GeneralI get an error.... Pinmembermoni9425 May '10 - 0:42 
I've made a program using this hook and on about the 40th second I get an exception:
 
A callback was made on a garbage collected delegate of type 'SuperLogger!Utilities.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.
 
That's quite weird. Any ideas?
GeneralRe: I get an error.... Pinmembermahboobeh mohamadi31 Jan '11 - 20:08 
GeneralStrange problem concernign Arrow Keys [modified] Pinmembermuff997 Apr '10 - 1:28 
Hi,
 
First of all, thanks for sharing this code!
 
Second: I got a problem using this code, I'm hooking some "normal" keys (like A, S, Q...) and the alt key. After a while (30-240 minutes), my application crashes. I surrounded all of my code with try-catches and debug output in the catch clause, so i'm almost sure its not my code that causes the crash (bold statement, I know ... not to be taken too seriously).
The only piece of information I found so far: The crash seems to occur shortly after using the arrow keys (which I did not hook).
 
My system: Win XP SP3, 32 Bit, german language
 
UPDATE: After testing some more, its not bound to the arrow keys ... it happens with all keys. I had some more crashes today that occured while I was typing.
modified on Wednesday, April 7, 2010 11:16 AM

GeneralOverride F1 PinmemberFullmetal9901229 Mar '10 - 8:24 
I need to use the F1 in my application, and ive tried e.handled, but everytime ive hit F1, it brings up help.

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 30 May 2007
Article Copyright 2007 by StormySpike
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid