Click here to Skip to main content
11,487,406 members (72,160 online)
Click here to Skip to main content
Add your own
alternative version

Global Windows Hooks

, 24 Sep 2010 CPOL 205.1K 6.4K 217
A single component that contains various Windows hooks
Library_Files.zip
Library Files
WindowsHookLib.dll
Source_Code_and_Demo.zip
Source Code and Demo
WindowsHookDemo
WindowsHookDemo.suo
WindowsHookDemo
bin
Debug
WindowsHookDemo.exe
WindowsHookDemo.vshost.exe
WindowsHookLib.dll
Release
My Project
Application.myapp
Settings.settings
WindowsHookDemo.vbproj.user
WindowsHookLib
WindowsHookLib.suo
WindowsHookLib
bin
Release
x86
Release
WindowsHookLib.dll
WindowsHookLib.dll.lastcodeanalysissucceeded
WindowsHookLib.pdb
Properties
Resources
clipboard.ico
keyboard.ico
mouse.ico
Thumbs.db
WindowsHookLib_Component.zip
WindowsHookLib Component
WindowsHookLib.dll
// Author: Arman Ghazanchyan
// Created: 11/02/2006
// Modified: 09/13/2010

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

namespace WindowsHookLib
{
    /// <summary>
    /// Provides functionality to hook the keyboard system wide (low level).
    /// </summary>
    [DebuggerNonUserCode]
    [DefaultEvent("KeyDown"), ToolboxBitmap(typeof(KeyboardHook), "Resources.keyboard"),
    Description("Component that hooks the keyboard system wide and raises some useful events.")]
    public partial class KeyboardHook : Component
    {
        #region ' Event Handlers and Delegates '

        /// <summary>
        /// Occurs when the KeyboardHook state changed.
        /// </summary>
        [Description("Occurs when the KeyboardHook state changed.")]
        public event System.EventHandler<WindowsHookLib.StateChangedEventArgs> StateChanged;
        /// <summary>
        /// Occurs when a key is first pressed.
        /// </summary>
        [Description("Occurs when a key is first pressed.")]
        public event System.EventHandler<WindowsHookLib.KeyboardEventArgs> KeyDown;
        /// <summary>
        /// Occurs when a key is released.
        /// </summary>
        [Description("Occurs when a key is released.")]
        public event System.EventHandler<WindowsHookLib.KeyboardEventArgs> KeyUp;
        /// <summary>
        /// Represents the method that will handle the keyboard message event.
        /// </summary>
        delegate IntPtr KeyboardMessageEventHandler(Int32 nCode, IntPtr wParam, ref UnsafeNativeMethods.KeyboardData lParam);

        #endregion

        #region ' Members '

        // Holds a method pointer to KeyboardProc for callback.
        // Needed for InstallHook method.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [MarshalAs(UnmanagedType.FunctionPtr)]
        private KeyboardHook.KeyboardMessageEventHandler _keyboardProc;
        // Holds the keyboard hook handle. Needed 
        // for RemoveHook and KeyboardProc methods.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private IntPtr _hKeyboardHook;
        // Holds a bitwise combination of the keys that are up or down.
        // Needed for key down and key up events’ KeyEventArgs object.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Keys _keyData;

        #endregion

        #region ' Properties '

        /// <summary>
        /// Gets the component's assembly information.
        /// </summary>
        public static Assembly AssemblyInfo
        {
            get
            {
                return Assembly.GetExecutingAssembly();
            }
        }

        /// <summary>
        /// Gets a Boolean value indicating if the ALT key is down.
        /// </summary>
        public bool AltKeyDown
        {
            get
            {
                return (this._keyData & Keys.Alt) == Keys.Alt;
            }
        }

        /// <summary>
        /// Gets a Boolean value indicating if the CTRL key is down.
        /// </summary>
        public bool CtrlKeyDown
        {
            get
            {
                return (this._keyData & Keys.Control) == Keys.Control;
            }
        }

        /// <summary>
        /// Gets a Boolean value indicating if the SHIFT key is down.
        /// </summary>
        public bool ShiftKeyDown
        {
            get
            {
                return (this._keyData & Keys.Shift) == Keys.Shift;
            }
        }

        /// <summary>
        /// Gets the state of the hook.
        /// </summary>
        public HookState State
        {
            get
            {
                if (this._hKeyboardHook != IntPtr.Zero)
                    return HookState.Installed;
                else
                    return HookState.Uninstalled;
            }
        }

        #endregion

        #region ' Methods '

        /// <summary>
        /// Default constructor.
        /// </summary>
        public KeyboardHook()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Installs the keyboard hook for this application. 
        /// </summary>
        public void InstallHook()
        {
            if (this._hKeyboardHook == IntPtr.Zero)
            {
                this._keyboardProc = new KeyboardHook.KeyboardMessageEventHandler(KeyboardProc);
                IntPtr hinstDLL = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);
                this._hKeyboardHook = UnsafeNativeMethods.SetWindowsHookEx(UnsafeNativeMethods.WH_KEYBOARD_LL, this._keyboardProc, hinstDLL, 0);
                if (this._hKeyboardHook == IntPtr.Zero)
                {
                    // Failed to hook. Throw a HookException
                    int eCode = Marshal.GetLastWin32Error();
                    this._keyboardProc = null;
                    throw new WindowsHookException(new Win32Exception(eCode).Message);
                }
                else
                {
                    this.OnStateChanged(new WindowsHookLib.StateChangedEventArgs(this.State));
                }
            }
        }

        /// <summary>
        /// Removes the keyboard hook for this application.
        /// </summary>
        public void RemoveHook()
        {
            if (this._hKeyboardHook != IntPtr.Zero)
            {
                if (!UnsafeNativeMethods.UnhookWindowsHookEx(this._hKeyboardHook))
                {
                    // Failed to remove the hook. Throw a HookException
                    int eCode = Marshal.GetLastWin32Error();
                    throw new WindowsHookException(new Win32Exception(eCode).Message);
                }
                else
                {
                    this._keyboardProc = null;
                    this._hKeyboardHook = IntPtr.Zero;
                    this._keyData = Keys.None;
                    this.OnStateChanged(new WindowsHookLib.StateChangedEventArgs(this.State));
                }
            }
        }

        /// <summary>
        /// Safely removes the hook without throwing exception.
        /// </summary>
        private void SafeRemove()
        {
            if (this._hKeyboardHook != IntPtr.Zero)
            {
                UnsafeNativeMethods.UnhookWindowsHookEx(this._hKeyboardHook);
                this._keyboardProc = null;
                this._hKeyboardHook = IntPtr.Zero;
                this._keyData = Keys.None;
                this.OnStateChanged(new WindowsHookLib.StateChangedEventArgs(this.State));
            }
        }

        // This sub processes all the keyboard messages and passes to the other windows
        private IntPtr KeyboardProc(int nCode, IntPtr wParam, ref UnsafeNativeMethods.KeyboardData lParam)
        {
            if (nCode >= UnsafeNativeMethods.HC_ACTION)
            {
                WindowsHookLib.KeyboardEventArgs e;
                Keys keyCode = (Keys)lParam.vkCode;
                if ((int)wParam == UnsafeNativeMethods.WM_KEYDOWN | (int)wParam == UnsafeNativeMethods.WM_SYSKEYDOWN)
                {
                    if (keyCode == Keys.LMenu | keyCode == Keys.RMenu)
                    {
                        this._keyData = (this._keyData | Keys.Alt);
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | Keys.Menu, keyCode);
                    }
                    else if (keyCode == Keys.LControlKey | keyCode == Keys.RControlKey)
                    {
                        this._keyData = (this._keyData | Keys.Control);
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | Keys.ControlKey, keyCode);
                    }
                    else if (keyCode == Keys.LShiftKey | keyCode == Keys.RShiftKey)
                    {
                        this._keyData = (this._keyData | Keys.Shift);
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | Keys.ShiftKey, keyCode);
                    }
                    else
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | keyCode, keyCode);

                    this.OnKeyDown(e);
                    if (e.Handled)
                        return new IntPtr(1);
                }
                else if ((int)wParam == UnsafeNativeMethods.WM_KEYUP | (int)wParam == UnsafeNativeMethods.WM_SYSKEYUP)
                {
                    if (keyCode == Keys.LMenu | keyCode == Keys.RMenu)
                    {
                        this._keyData = (this._keyData & ~Keys.Alt);
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | Keys.Menu, keyCode);
                    }
                    else if (keyCode == Keys.LControlKey | keyCode == Keys.RControlKey)
                    {
                        this._keyData = (this._keyData & ~Keys.Control);
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | Keys.ControlKey, keyCode);
                    }
                    else if (keyCode == Keys.LShiftKey | keyCode == Keys.RShiftKey)
                    {
                        this._keyData = (this._keyData & ~Keys.Shift);
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | Keys.ShiftKey, keyCode);
                    }
                    else
                        e = new WindowsHookLib.KeyboardEventArgs(this._keyData | keyCode, keyCode);

                    this.OnKeyUp(e);
                    if (e.Handled)
                        return new IntPtr(1);
                }
            }
            return UnsafeNativeMethods.CallNextHookEx(this._hKeyboardHook, nCode, wParam, ref lParam);
        }

        #endregion

        #region ' On Event '

        /// <summary>
        /// Raises the WindowsHookLib.KeyboardHook.StateChanged event.
        /// </summary>
        /// <param name="e">A WindowsHookLib.StateChangedEventArgs
        /// that contains the event data.</param>
        protected virtual void OnStateChanged(WindowsHookLib.StateChangedEventArgs e)
        {
            if (StateChanged != null)
                StateChanged(this, e);
        }

        /// <summary>
        /// Raises the WindowsHookLib.KeyboardHook.KeyUp event.
        /// </summary>
        /// <param name="e">A WindowsHookLib.KeyBoardEventArgs
        /// that contains the event data.</param>
        protected virtual void OnKeyUp(WindowsHookLib.KeyboardEventArgs e)
        {
            if (KeyUp != null)
                KeyUp(this, e);
        }

        /// <summary>
        /// Raises the WindowsHookLib.KeyboardHook.KeyDown event.
        /// </summary>
        /// <param name="e">A WindowsHookLib.KeyBoardEventArgs
        /// that contains the event data.</param>
        protected virtual void OnKeyDown(WindowsHookLib.KeyboardEventArgs e)
        {
            if (KeyDown != null)
                KeyDown(this, e);
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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

Share

About the Author

VBDT
Software Developer (Senior) ZipEdTech
United States United States
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150520.1 | Last Updated 24 Sep 2010
Article Copyright 2007 by VBDT
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid