Могу ли я создать связывание ключей для последовательности ключей в WPF? - PullRequest
2 голосов
/ 02 сентября 2010

Можно ли определить привязки клавиш в WPF для последовательности нажатий клавиш, таких как сочетания клавиш в Visual Studio, например, Ctrl + R , Ctrl + A - запустить все тесты в текущем решении

Насколько я вижу, я могу связывать только отдельные комбинации клавиш, такие как Ctrl + S , используя элемент. Могу ли я связать последовательности, используя это, или мне придется вручную обрабатывать нажатия клавиш, чтобы сделать это?

Ответы [ 3 ]

4 голосов
/ 02 сентября 2010

Вам нужно создать свой собственный InputGesture, переопределив метод Matches.

Примерно так:

public class MultiInputGesture : InputGesture
{
    public MultiInputGesture()
    {
        Gestures = new InputGestureCollection();
    }

    public InputGestureCollection Gestures { get; private set; }

    private int _currentMatchIndex = 0;

    public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
    {
        if (_currentMatchIndex < Gestures.Count)
        {
            if (Gestures[_currentMatchIndex].Matches(targetElement, inputEventArgs))
            {
                _currentMatchIndex++;
                return (_currentMatchIndex == Gestures.Count);
            }
        }
        _currentMatchIndex = 0;
        return false;
    }
}

Возможно, ему нужно немного больше, например, игнорирование определенных событий (например, KeyUp события между KeyDown событиями не должны сбрасываться _currentMatchIndex), но вы получите картину ...

0 голосов
/ 05 июня 2019

Ответ @ThomasLevesque в основном правильный, но не касается повторяющихся клавиш.(Обратите внимание, что нажатие клавиши Ctrl приводит к генерации событий повторения клавиши.) Это также может быть полезно для тайм-аута, если пользователь останавливает среднюю последовательность.Вот что я использую:

public class MultiKeyInputGesture : InputGesture {
    private const int MAX_PAUSE_MILLIS = 1500;

    private InputGestureCollection mGestures = new InputGestureCollection();

    private DateTime mLastWhen = DateTime.Now;
    private int mCheckIdx;

    public MultiKeyInputGesture(KeyGesture[] keys) {
        Debug.Assert(keys.Length > 0);

        // Grab a copy of the array contents.
        foreach (KeyGesture kg in keys) {
            mGestures.Add(kg);
        }
    }

    public override bool Matches(object targetElement, InputEventArgs inputEventArgs) {
        if (!(inputEventArgs is KeyEventArgs)) {
            // does this actually happen?
            return false;
        }

        DateTime now = DateTime.Now;
        if ((now - mLastWhen).TotalMilliseconds > MAX_PAUSE_MILLIS) {
            mCheckIdx = 0;
        }
        mLastWhen = now;

        if (((KeyEventArgs)inputEventArgs).IsRepeat) {
            // ignore key-repeat noise (especially from modifiers)
            return false;
        }

        if (!mGestures[mCheckIdx].Matches(null, inputEventArgs)) {
            mCheckIdx = 0;
            return false;
        }

        mCheckIdx++;
        if (mCheckIdx == mGestures.Count) {
            mCheckIdx = 0;
            inputEventArgs.Handled = true;
            return true;
        }

        return false;
    }
}

Я использую это, определив RoutedUICommand в XAML:

<Window.Resources>
    <RoutedUICommand x:Key="MyCommand" Text="My Command"/>
</Window.Resources>

На это ссылаются из <Window.CommandBindings> и <MenuItem>по-прежнему.Затем в конструкторе окна я делаю:

RoutedUICommand ruic = (RoutedUICommand)FindResource("MyCommand");
ruic.InputGestures.Add(
    new MultiKeyInputGesture(new KeyGesture[] {
          new KeyGesture(Key.H, ModifierKeys.Control, "Ctrl+H"),
          new KeyGesture(Key.C, ModifierKeys.Control, "Ctrl+C")
    }) );

Я нашел это сообщение на форуме полезным.

Вам нужно будет добавить явный InputGestureText к любомуMenuItem, если вы не хотите попробовать взломать DisplayString в связанном сообщении на форуме.

ПРИМЕЧАНИЕ: обработчик жеста клавиши "съедает" ключ, который завершает жест.Если у вас есть более одного обработчика, и пользователь пытается использовать две многоключевые последовательности подряд (например, Ctrl + H, Ctrl + C, за которыми сразу следует Ctrl + H, Ctrl + D), второй обработчик не будет сброшенкогда Ctrl + C нажата.Вместо этого он будет сброшен, когда прибудет второй Ctrl + H, и пропустит комбо.Фактическое поведение зависит от порядка, в котором вызываются обработчики.В настоящее время я занимаюсь этим, определяя статическое событие, которое срабатывает при обнаружении совпадения, и подписывая все экземпляры на него.

0 голосов
/ 16 апреля 2013
   <KeyBinding x:Name="mykeybinding" Gesture="CTRL+P" Key="E" 
                 Command="mycommand"/>

Кажется, что с моей стороны все в порядке, мне нужно нажать Ctrl + P + E, чтобы выполнить "mycommand"

На основании http://msdn.microsoft.com/en-in/library/system.windows.input.keybinding.aspx

...