Пример #1
0
        /// <summary>
        /// A callback function which will be called every time a keyboard activity detected.
        /// https://docs.microsoft.com/en-us/windows/win32/winmsg/lowlevelkeyboardproc
        /// </summary>
        /// <param name="code">
        /// Specifies whether the hook procedure must process the message.
        /// If code is HC_ACTION, the hook procedure must process the message.
        /// If code is less than zero, the hook procedure must pass the message to the
        /// CallNextHookEx function without further processing and must return the
        /// value returned by CallNextHookEx.
        /// </param>
        /// <param name="wParam">
        /// Specifies whether the message was sent by the current thread.
        /// If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
        /// </param>
        /// <param name="lParam">
        /// Pointer to a CWPSTRUCT structure that contains details about the message.
        /// </param>
        /// <returns>
        /// If code is less than zero, the hook procedure must return the value returned by CallNextHookEx.
        /// If code is greater than or equal to zero, it is highly recommended that you call CallNextHookEx
        /// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC
        /// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook
        /// procedure does not call CallNextHookEx, the return value should be zero.
        /// </returns>
        private IntPtr KeyboardHookProc(int code, uint wParam, IntPtr lParam)
        {
            //Indicates if any of the underlaying events set the e.Handled flag.
            var handled = false;

            //If it was Ok and there are no listeners.
            if (code < 0 || KeyDown == null && KeyUp == null && KeyPress == null)
            {
                return(User32.CallNextHookEx(_keyboardHookHandle, code, wParam, lParam));
            }

            //Read structure KeyboardHookStruct at lParam
            var keyboard   = (KeyboardHook)Marshal.PtrToStructure(lParam, typeof(KeyboardHook));
            var isInjected = (keyboard.Flags & 0x10) != 0;

            if (KeyDown != null && (wParam == MessageKeydown || wParam == MessageSystemKeyDown))
            {
                #region Raise KeyDown

                var isDownShift    = (User32.GetKeyState(KeyShift) & 0x80) == 0x80;
                var isDownCapslock = User32.GetKeyState(KeyCapital) != 0;


                var e = new CustomKeyEventArgs(KeyInterop.KeyFromVirtualKey(keyboard.KeyCode), isDownCapslock ^ isDownShift, isInjected);

                KeyDown?.Invoke(this, e);

                handled = e.Handled;

                #endregion
            }

            if (KeyPress != null && wParam == MessageKeydown)
            {
                #region Raise KeyPress

                var isDownShift    = (User32.GetKeyState(KeyShift) & 0x80) == 0x80;
                var isDownCapslock = User32.GetKeyState(KeyCapital) != 0;

                var keyState = new byte[256];
                User32.GetKeyboardState(keyState);
                var inBuffer = new byte[2];

                if (User32.ToAscii(keyboard.KeyCode, keyboard.ScanCode, keyState, inBuffer, keyboard.Flags) == 1)
                {
                    var key = (char)inBuffer[0];
                    if (isDownCapslock ^ isDownShift && char.IsLetter(key))
                    {
                        key = char.ToUpper(key);
                    }

                    var e = new CustomKeyPressEventArgs(key);
                    KeyPress?.Invoke(this, e);

                    handled = handled || e.Handled;
                }

                #endregion
            }

            if (KeyUp != null && (wParam == MessageKeyUp || wParam == MessageSystemKeyUp))
            {
                #region Raise KeyUp

                var e = new CustomKeyEventArgs(KeyInterop.KeyFromVirtualKey(keyboard.KeyCode), false, isInjected);

                KeyUp?.Invoke(this, e);

                handled = handled || e.Handled;

                #endregion
            }

            //If event handled in application do not handoff to other listeners.
            return(handled ? new IntPtr(1) : User32.CallNextHookEx(_keyboardHookHandle, code, wParam, lParam));
        }