Как я могу создать глобальную комбинацию горячих клавиш, которая включает в себя клавишу Windows?

Я использую SetWindowsHookEx для захвата клавиатуры, чтобы показать работающее приложение. Я могу создавать комбинации, используя клавиши CTRL, ALT, SHIFT и обычные клавиши. Однако я не могу создать комбинацию с помощью клавиши WINDOWS (например, CTRL + WINDOWS + A).

Я видел статьи о том, как захватить ключ WINDOWS изолированно (например, чтобы предотвратить запуск экрана Windows 8 во время игры), но никогда не создавал комбинацию.

Я знаю, что можно запечатлеть эти комбинации, как это делает AutoHotKey.

Является ли SetWindowsHookEx неправильным способом сделать это?

1 ответ

Я нашел аналогичный вопрос, который содержал ответ, который помог здесь. Это привело меня к правильному пути к решению.

Похоже, Keyboard.Modifiers не может обнаружить ключ Windows (по крайней мере, на моем экземпляре Win8).

Вместо этого мне пришлось обращаться с ключом Windows по-другому, используя Keyboard.IsKeyDown, Это привело к созданию метода для проверки того, совпадает ли комбинация нажатой клавиши (из моего LowLevelKeyboardProc) и текущих клавиш-модификаторов с определенной клавишей и модификаторами в свойствах. HotKey а также HotKeyModifiers,

Вот C# LowLevelKeyboardProc:

/// <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;
}
Другие вопросы по тегам