示例#1
0
        public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            var fEatKeyStroke = false;

            var wparamTyped = wParam.ToInt32();

            if (Enum.IsDefined(typeof(KeyboardState), wparamTyped))
            {
                var o        = Marshal.PtrToStructure(lParam, typeof(LowLevelKeyboardInputEvent));
                var p        = (LowLevelKeyboardInputEvent)o;
                var keyState = (KeyboardState)wparamTyped;
                var keyUp    = keyState == KeyboardState.KeyUp || keyState == KeyboardState.SysKeyUp;
                var keyDown  = keyState == KeyboardState.KeyDown || keyState == KeyboardState.SysKeyDown;
                var key      = (System.Windows.Forms.Keys)p.VirtualCode;
                var state    = keyUp ? KeyboardKeyState.Up : keyDown ? KeyboardKeyState.Down : KeyboardKeyState.Unknown;
                Console.WriteLine("---");
                var flags = new LowLevelKeyboardInputEventFlags(p.Flags);
                OnKeyEvent?.Invoke(new KeyboardKey {
                    IsInjected = flags.IsInjected, Value = key, State = state
                });
            }

            return(fEatKeyStroke ? (IntPtr)1 : CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam));
        }
示例#2
0
        /// <summary>
        /// HandlesKeyDown and KeyUp events for defined keys.
        /// When key has been depressed for configured period of time,
        /// it plays a sound (if so configured) and upon KeyUp send the
        /// key press to the system.
        /// If the configured period of time is less than 0, they key will be ignored
        /// and never reach the system.
        /// </summary>
        /// <param name="nCode">Can be HC_ACTION or HC_NOREMOVE. If less than 0  the hook procedure must pass the message to the CallNextHookEx function without further processing and return the value returned by CallNextHookEx</param>
        /// <param name="wParam">Int32 value that contains they virtual key code</param>
        /// <param name="lParam">Pointer to a struct LowLevelKeyboardInputEvent containing additional information</param>
        /// <returns>1 if the event should no be processed any further by the system, or the result of calling CallNextHookEx, which will call other hooks</returns>
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            // get the key
            int           wparamTyped = wParam.ToInt32();
            KeyboardState?kbdState    = null;

            if (Enum.IsDefined(typeof(KeyboardState), wparamTyped))
            {
                kbdState = (KeyboardState)wparamTyped;
            }

            // get additional information
            object o = Marshal.PtrToStructure(lParam, typeof(LowLevelKeyboardInputEvent));
            LowLevelKeyboardInputEvent p = (LowLevelKeyboardInputEvent)o;
            int  vkCode = p.VirtualCode;
            Keys vkKey  = (Keys)vkCode;
            LowLevelKeyboardInputEventFlags flags = (LowLevelKeyboardInputEventFlags)p.Flags;

            if (nCode >= 0 &&                                                             // as per spec, values less than 0 indicate that event should not be processed and CallNextHookEx be called immediately
                (!flags.HasFlag(LowLevelKeyboardInputEventFlags.LLKHF_INJECTED)) &&       // not injected, e. g.  generated by us
                kbdState != null &&
                (kbdState == KeyboardState.KeyDown || kbdState == KeyboardState.KeyUp) && // valid keyboard state
                KeyMap.dtKeys.Keys.Contains(vkKey) &&                                     // handled key
                getKeyDelay(vkKey) != 0)                                                  // key has a delay assigned (< 0 means deactivated, 0 means no delay)
            {
                //Debug.WriteLine("Timestamp: " + p.TimeStamp.ToString());
                //Debug.WriteLine("Extra Info: " + p.AdditionalInformation.ToString());
                //Debug.WriteLine("Injected: " + (((p.Flags & 0x00000010) > 0) ? "yes" : "no"));

                if (kbdState == KeyboardState.KeyDown)
                {
                    if (KeyMap.dtKeys[vkKey].started == null)
                    {
                        // remember first time they key was pressed (event will be repeated while it is kept down)
                        KeyMap.dtKeys[vkKey].started = DateTime.Now;
                    }
                    else if (Properties.Settings.Default.playSound &&
                             !soundPlayed &&
                             pressDurationSufficient(KeyMap.dtKeys[vkKey].started, vkKey))
                    {
                        // play a sound when configured delay has been reached
                        Sound.play();
                        // only play once, when the use keeps holding the key down
                        soundPlayed = true;
                    }
                }
                else if (kbdState == KeyboardState.KeyUp)
                {
                    DateTime?started = KeyMap.dtKeys[vkKey].started;
                    // reset time the key was first pressed
                    KeyMap.dtKeys[vkKey].started = null;
                    // reset soun played
                    soundPlayed = false;

                    if (pressDurationSufficient(started, vkKey))
                    {
                        // toggle
                        Debug.WriteLine("toggled");
                        // simulate the key being pressed, will have flag set to LLKHF_INJECTED,
                        // so the event will not be handled by us, othewise the cat would bite its own tail
                        pressKey(vkKey);
                    }
                }

                // cancel event propagation, aka "eat" event
                return((IntPtr)1);
            }

            // we did not handle the event, pass it on
            return(CallNextHookEx(hookID, nCode, wParam, lParam));
        }