如何创建包含Windows密钥的全局热键组合?

问题描述:

我使用SetWindowsHookEx捕获键盘以显示正在运行的应用程序。我可以使用CTRL,ALT,SHIFT和常规键创建组合。但是,我无法使用WINDOWS键创建组合(例如,CTRL + WINDOWS + A)。如何创建包含Windows密钥的全局热键组合?

我已经看到有关单独捕获WINDOWS键的文章(例如当游戏运行时阻止Windows 8启动屏幕),但从未创建组合。

我知道有可能将这些组合捕获为像AutoHotKey这样的软件。

SetWindowsHookEx是错误的方法吗?

我发现了一个类似的问题,其中包含一个帮助here的答案。 这使我走上了解决问题的正确道路。

它出现Keyboard.Modifiers无法检测到Windows键(至少在我的Win8实例)。

相反,我不得不以不同的方式使用Keyboard.IsKeyDown来处理Windows密钥。这导致构建一种方法来检查按下(从我的LowLevelKeyboardProc)按键和当前正在按下的修饰键的组合是否与属性HotKeyHotKeyModifiers中定义的键和修饰符相同。

这里的LowLevelKeyboardProc的C#:

/// <summary> 
/// Called by windows when a keypress occurs. 
/// </summary> 
/// <param name="nCode">A code the hook procedure uses to determine how to process the message. If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx.</param> 
/// <param name="wParam">The identifier of the keyboard message. This parameter can be one of the following messages: WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP. </param> 
/// <param name="lParam">A pointer to a KBDLLHOOKSTRUCT structure. </param> 
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
{ 
    if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)) 
    { 
     int vkCode = Marshal.ReadInt32(lParam); 
     var keyPressed = KeyInterop.KeyFromVirtualKey(vkCode); 

     if (IsKeyCombinationPressed(keyPressed)) 
      OnKeyCombinationPressed(new EventArgs()); 
    } 

    return CallNextHookEx(_hookId, nCode, wParam, lParam); 
} 

和C#的IsKeyCombinationPressed()方法:

/// <summary> 
/// Returns true if the registered key combination is pressed 
/// </summary> 
/// <remarks> 
/// Keyboard.Modifiers doesn't pick up the windows key (at least on Windows 8) so we use Keyboard.IsKeyDown to detect it (if required). 
/// </remarks> 
bool IsKeyCombinationPressed(Key keyPressed) 
{ 
    if (keyPressed != HotKey) return false; 

    //Handle windows key 
    bool isWindowsKeyRequired = (HotKeyModifiers & ModifierKeys.Windows) != 0; 
    bool isWindowsKeyPressed = Keyboard.IsKeyDown(Key.LWin) || Keyboard.IsKeyDown(Key.RWin); 

    //Remove windows key from modifiers (if required) 
    ModifierKeys myModifierKeys = isWindowsKeyRequired ? HotKeyModifiers^ModifierKeys.Windows : HotKeyModifiers; 
    bool isModifierKeysPressed = Keyboard.Modifiers == myModifierKeys; 

    return isWindowsKeyRequired 
     ? isWindowsKeyPressed && isModifierKeysPressed 
     : isModifierKeysPressed; 
}