1
votes

I would like to detect a keypress event only when a non-modifier key has pressed. I then also would like to know which modifier keys have been pressed at the same time.

For Instance:
When I press Shift:_______ I would like to output nothing.
When I press Shift+A:_____ I would like to output "Shift A".
When I press Shift+Alt+A:__ I would like to output "Shift+Alt A"
When I press Alt+A:_______ I would like to output "Alt A"

However, "Alt A" does not show because without Shift/Ctrl pressed, Alt key down can't be detected with Keyboard.IsKeyDown

Following is the part of my test code.

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    Key key = e.Key;

    if (key.ToString().Contains("Ctrl") | key.ToString().Contains("Shift") | key.ToString().Contains("Alt"))
        return;

    Label_Test.Content = "";

    if (Keyboard.IsKeyDown(Key.LeftShift) | Keyboard.IsKeyDown(Key.RightShift))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Shift";
    }
    if (Keyboard.IsKeyDown(Key.LeftCtrl) | Keyboard.IsKeyDown(Key.RightCtrl))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Ctrl";
    }
    if (Keyboard.IsKeyDown(Key.LeftAlt) | Keyboard.IsKeyDown(Key.RightAlt))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Alt";
    }
    if (Keyboard.IsKeyDown(Key.System))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Alt";
    }
    if (Label_Test.Content.ToString() != "")
        Label_Test.Content += " ";
    Label_Test.Content += key.ToString();
}

I also tried

if (e.KeyboardDevice.Modifiers.ToString().Contains("Alt"))

but the result was same. How could I detect "Alt + A"?



EDIT: Thanks, guys for your help. I edited the last if statement which checks for Key.System like this and It just worked as I wanted.

if (e.Key == Key.System)
{
    key = e.SystemKey;
    if (e.SystemKey.HasFlag(Key.LeftAlt) | e.SystemKey.HasFlag(Key.RightAlt))
        return;
    Label_Test.Content = "Alt";
}
1
Are you using the MVVM pattern? You can bin commands to input gestures without having the trouble of this code behind stuff.Mighty Badaboom
I was about to mention all you have to do to check for Alt + A (specifically A) is if ((Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) && e.SystemKey == Key.A)Josh
and mighty while this may be the case, I HAD to do this in the code behind because while clicking a button was causing the correct behavior, the mvvm xaml key bindings were causing different behavior, so I had to intercept the keys elsewhere and do something in addition when the user used the hotkey vs clicking the button. There's no way around it sometimes, especially when dealing with 3rd party components.Josh

1 Answers

3
votes

To check if only modifiers pressed compare e.Key with all modifier keys and return empty string in this case.

If e.Key is not a modifier key then we need to print it along with modifiers currently pressed. To get these modifiers just iterate through all values of ModifierKeys enum except None and call HasFlag for each value on the Keyboard.Modifiers.

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    var modifierKeys = new[]
    {
        Key.LeftCtrl, Key.RightCtrl,
        Key.LeftAlt, Key.RightAlt,
        Key.LeftShift, Key.RightShift,
        Key.LWin, Key.RWin
    };

    var key = e.Key;
    if (key == Key.System)
        key = e.SystemKey;
    else if (key == Key.ImeProcessed)
        key = e.ImeProcessedKey;

    if (modifierKeys.Contains(key))
    {
        Label_Test.Content = string.Empty;
        return;
    }

    var modifiers = Keyboard.Modifiers;
    var modifiersPressed = Enum.GetValues(typeof(ModifierKeys))
                               .OfType<ModifierKeys>()
                               .Where(k => k != ModifierKeys.None && modifiers.HasFlag(k));

    Label_Test.Content = string.Join("+", modifiersPressed.OfType<object>()
                                                          .Concat(new object[] { key }));
}