0

I'm using SetWindowsHookEx to capture the keyboard in order to show a running application. I can create combinations using CTRL, ALT, SHIFT, and regular keys. However I can't create a combination using the WINDOWS key (for example, CTRL + WINDOWS + A).

I've seen articles about capturing the WINDOWS key in isolation (such as to prevent the Windows 8 start screen when a game is running), but never to create a combination.

I know it's possible to capture these combinations as software such as AutoHotKey does it.

Is SetWindowsHookEx the wrong way to do this?

4

1 回答 1

0

我发现了一个类似的问题,其中包含有帮助的答案。这使我找到了正确的解决方案。

看来 Keyboard.Modifiers 无法检测到 Windows 键(至少在我的 Win8 实例上)。

相反,我不得不使用不同的方式处理 Windows 键Keyboard.IsKeyDown。这导致构建了一个方法来检查按下的键(来自我的 LowLevelKeyboardProc)和当前按下的修饰键的组合是否与属性中定义的键和修饰键HotKey相同HotKeyModifiers

下面是 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);
}

以及 IsKeyCombinationPressed() 方法的 C#:

/// <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;
}
于 2013-11-12T07:35:54.590 回答