private IntPtr HookCallback(int nCode, IntPtr wParam, ref LowLevelKeyboardEvent lParam) { if (nCode < 0) { return(CallNextHookEx(_keyboardHookHandle, nCode, wParam, ref lParam)); } if (KeyboardStateManager.SimulatingKey) { return(_preventProcessing); } var currentKey = (VirtualKeys)lParam.VirtualKeyCode; var isKeyUp = (wParam == WM_KEYUP || wParam == WM_SYSKEYUP); var leaderKeyCurrent = currentKey == this._parser.LeaderKey; if (currentKey == _lastKey && _lastKeyDirection == isKeyUp && _hotKeyIsDown) { //already handled this case, early exit here since keydown triggers continuously return(_preventProcessing); } _lastKey = currentKey; _lastKeyDirection = isKeyUp; if (!isKeyUp) { this.PressedKeys.Add(currentKey); } if (leaderKeyCurrent) { _hotKeyIsDown = !isKeyUp; if (isKeyUp) { this.PressedKeys.Clear(); } return(_preventProcessing); } if (!_hotKeyIsDown || this.PressedKeys.Count == 0) { this.PressedKeys.Clear(); return(CallNextHookEx(_keyboardHookHandle, nCode, wParam, ref lParam)); } var currentCombination = new KeyboardCombination(this.PressedKeys); var combinationDown = this.Combinations.FirstOrDefault(c => c.IsPressed(currentCombination)); if (combinationDown == null || combinationDown.Shortcut.Count == 0) { if (isKeyUp) { this.PressedKeys.Remove(currentKey); } return(!isKeyUp ? _preventProcessing : CallNextHookEx(_keyboardHookHandle, nCode, wParam, ref lParam)); } //keyCombination is down, prevent from activating command unless we receive a keyup. //we could still be building up our key combination if (!isKeyUp) { return(_preventProcessing); } Task.Run(combinationDown.Action); if (isKeyUp) { this.PressedKeys.Remove(currentKey); } return(_preventProcessing); }
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref LowLevelKeyboardEvent lParam);