Как определить состояния ключей модификатора в WPF?


151

Существуют ли какие-либо глобальные конструкции, которые я могу использовать всякий раз, когда мне нужно получить доступ к кнопкам Control, Shift, Alt? Например, внутри MouseDownсобытия TreeView.

Если так, то как?

Ответы:


257

Используйте класс Keyboard. С помощью Keyboard.IsKeyDownвы можете проверить, не работает ли Control, Shift, Alt.

Для смены:

if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
{ /* Your code */ }

Для управления:

if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{ /* Your code */ }

Для Alt:

if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))
{ /* Your code */ }

125

Есть также:

// Have to get this value before opening a dialog, or user will have released the control key
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
{

}

13
Гораздо лучшее решение. Это также позволяет проверить все модификаторы одновременно. Если вы хотите обрабатывать Ctrl + F, вам не нужно обрабатывать Ctrl + Shift + F, поэтому вы можете просто проверить (e.Key == Key.F && e.KeyboardDevice.Modifiers == ModifierKeys.Control)вместо всего остального ...
ygoe

35
Обратите внимание, что сравнение в приведенных выше примерах дает разные результаты! Поскольку перечисление ModifierKeys имеет атрибут Flags, вы можете иметь любые комбинации значений в перечислении. Если вы хотите поймать ТОЛЬКО нажатую клавишу Shift, используйте Keyboard.Modifiers == ModifierKeys.Shiftоператор. Если вы хотите поймать клавишу Shift, но вам все равно, нажимаются ли одновременно другие модификаторы, используйте (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shiftсинтаксис HasFlag или намного лучший вариантKeyboard.Modifiers.HasFlag(ModifierKeys.Shift)
Patrik B

4
Я не мог поймать модификатор ключа Windows, используя этот метод. (CTRL работал нормально.) Я пытался поймать WIN+RightArrow.
ANEves

1
@ ANeves Интересно, Keyboard.Modifiersпоказывает какNone
Чак Сэвидж

8
    private bool IsShiftKey { get; set; }

    private void OnPreviewKeyDown(object sender, KeyEventArgs e)
    {
        IsShiftKey = Keyboard.Modifiers == ModifierKeys.Shift ? true : false;

        if ((Key.Oem3 == e.Key || ((IsShiftKey && Key.Oem4 == e.Key) || (IsShiftKey && Key.Oem6 == e.Key) || (IsShiftKey && Key.Oem5 == e.Key)) && (validatorDefn as FormatValidatorDefinition).format == "packedascii"))
        {
           e.Handled = true;
        }
    }

2
Ответы лучше с комментариями, а также с кодом. Пожалуйста, предоставьте некоторый контекст.
Крис

1
отличная идея добавить его как свойство
RollRoll

1
Когда я использовал PreviewKeyDown в поисках Alt + другой ключ, мне пришлось использовать e.SystemKey вместо e.Key (значение e.Key было «System» в случае использования alt + другой символ, в моем случае)
Josh

3

Вот как я справляюсь (используя PreviewKeyDown), скажем, мы ищем Alt + R ...

private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
    if ((Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)
       && e.SystemKey == Key.R)
    {
       //do whatever
    }
}

Может быть, кто-то может прояснить, почему я должен был использовать e.SystemKey, а не просто e.Key, возможно, из-за модификатора? но это сработало для меня безупречно при поиске модификатора + ключ.



0

Частично заимствуя у @Josh, и несколько похож на @Krushik, а также ссылаясь на вопрос о разнице между KeyEventArgs.systemKey и KeyEventArgs.Key (отвечая, почему Джош должен использовать SystemKey); где с ключами-модификаторами (такими как Alt) e.Key возвращает Key.System, и, таким образом, «реальный» ключ находится в e.SystemKey.

Чтобы обойти это, сначала нужно получить «реальный» ключ, а затем выполнить ваше условие:

private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
    // Fetch the real key.
    var key = e.Key == Key.System ? e.SystemKey : e.Key;

    if ((Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))
        && key == Key.Return)
    {
        // Execute your code.
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.