/// <summary>Dispose the KeyboardHook.</summary>
 public void Dispose()
 {
     if (_hookHandle != null)
     {
         _hookHandle.Dispose();
         _hookHandle = null;
     }
 }
 public static extern IntPtr CallNextHookEx(SafeWindowsHookHandle hhk, int nCode, IntPtr wParam, IntPtr lParam);
        /// <summary>Initializes the keyboard hook.</summary>
        /// <param name="keyDown">The delegate to be called when a key down event occurs.</param>
        public KeyboardHook(int targetProcessID, KeyEventHandler keyDown)
        {
            if (keyDown == null) throw new ArgumentNullException("keyDown");

            // Store the user's KeyDown delegate
            _keyDown = keyDown;
            _pid = targetProcessID;

            // Create the callback and pin it, since it'll be called 
            // from unmanaged code
            _hookProc = new LowLevelKeyboardProc(HookCallback);

            // Set the hook for just the GUI thread
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                _hookHandle = SafeWindowsHookHandle.SetWindowsHookEx(
                    WH_KEYBOARD_LL, _hookProc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
            if (_hookHandle.IsInvalid)
            {
                Exception exc = new Win32Exception();
                Dispose();
                throw exc;
            }
        }