代码之家  ›  专栏  ›  技术社区  ›  RobV

我可以为WPF中的一系列键创建KeyBinding吗?

  •  1
  • RobV  · 技术社区  · 15 年前

    是否可以在WPF中为一系列按键定义键绑定,比如visualstudio中的快捷方式。 + + A 是否运行当前解决方案中的所有测试

    据我所知,我只能绑定单键组合,如 Ctrl键 + S码 使用元素。我可以用这个绑定序列吗?或者我必须手动处理按键才能这样做?

    2 回复  |  直到 14 年前
        1
  •  4
  •   Jasper wontondon    14 年前

    你需要创造你自己的 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 ),但你明白了。。。

        2
  •  0
  •   fadden    6 年前

    @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

    <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")
        }) );
    

    我发现 this forum post

    您需要添加一个显式 InputGestureText MenuItem ,除非你想试试 DisplayString 黑客在链接的论坛帖子。

    键手势处理程序“吃掉”完成手势的键。如果您有多个处理程序,并且用户尝试在一行中使用两个多键序列(例如,Ctrl+H、Ctrl+C后跟Ctrl+H、Ctrl+D),则在按Ctrl+C时,第二个处理程序不会重置。相反,它将在第二个Ctrl+H到达时重置,并将错过组合。实际行为取决于调用处理程序的顺序。我目前正在通过定义一个静态事件来处理这个问题,该事件在找到匹配项时触发,并订阅所有实例。

    更新: 还有一件事需要注意:项目的顺序 <Window.CommandBindings> 事项。如果您有一个按Ctrl+C启动的复制处理程序,它必须出现在列表中Ctrl+H、Ctrl+C的多键手势之后。

        3
  •  -1
  •   purvin    12 年前
       <KeyBinding x:Name="mykeybinding" Gesture="CTRL+P" Key="E" 
                     Command="mycommand"/>
    

    基于 http://msdn.microsoft.com/en-in/library/system.windows.input.keybinding.aspx

    推荐文章