如何在Windows Forms应用程序中创建复合键盘快捷键?

15

我想创建一个组件,允许我们使用一个任意命令关联复合键盘快捷键,就像Visual Studio IDE和Microsoft Office一样。

也就是说,这些键盘快捷键由多个按键序列组成,比如Ctrl+W+C。在Visual Studio中,这会打开类视图。当按下第一组键(Ctrl+W)时,状态栏会显示消息“(Ctrl + W)已按下。等待弦的第二个键...”。


1
键盘快捷键是多键快捷键。例如 Ctrl + W,C,可以打开类视图。当按下第一组键(CTRL + W)时,在状态栏中会出现消息“(CTRL+W) was pressed. Waiting for second key of chord...”(已按下(CTRL+W),等待第二个键...)。我想完全复制这个功能。 - JJS
我在WPF中找到了这个的实现。http://insystusa.com/Products.aspx - JJS
这不是和弦的相反吗? - Mechanical snail
5个回答

14

针对键盘弦的问题,我认为目前还没有现成的选项可供选择。

但是,建模应该很简单。我会创建一个单独的类,可能称为KeyboardChordProvider。它需要了解表单级别的键盘事件。如其他地方所述,Form.KeyPreview属性必须为true。对于这个提供程序,仅订阅Form.KeyPress事件可能就足够了。如果传入表单,则可以在提供程序的构造函数中完成所有这些操作。

您需要向提供程序注册潜在的按键。

内部实例将跟踪当前状态。每当观察到表示弦的第一个按键时,您将更新提供程序的状态并引发事件,以便订阅者可以设置文本:(CTRL+W) was pressed. Waiting for second key of chord...

如果下一个按键与潜在的次要选项匹配,则表示匹配成功,并且可以引发包含输入的击键详细信息的ChordPressed事件。或者,您可能只需调用在注册弦时给提供程序的特定回调(以避免在ChordPressed事件处理程序中使用switch语句或其他分派)。

如果任何时候,按键不匹配潜在的下一个选项,则您将重置提供程序的状态。

在提供程序的内部,您可以使用树结构对可能的按键进行建模。提供程序的当前状态只是特定的树节点。一开始,根节点将处于活动状态。如果子节点与击键匹配,则它成为当前节点,以期望下一个击键。如果子节点是叶节点,则表示已匹配整个弦,您将引发ChordPressed事件(传递到达该点的击键链)或调用存储在叶节点中的回调。每当没有按键与子节点匹配时,请重置为使根节点处于活动状态。

我认为这个设计会实现你想要的效果。


1
感谢您提出的解决方案,Drew。更重要的是,感谢您没有半途而废地回复。 - JJS
在这里记录此接口,以便我稍后实现我的组件。http://msdn.microsoft.com/zh-cn/library/system.windows.forms.imessagefilter.aspx - JJS

2
菜单控件有一个名为ShortCut的属性,您可以在其中分配一个值。当您按下该快捷键时,将调用该菜单项。对于具有相应菜单的命令,请使用该属性。
如果您需要在菜单上不可用的快捷方式,则必须通过KeyUpKeyDown事件自己处理,无论是在窗体还是控件上。KeyEventArgs对象将传递给您的处理程序,并且您可以检查按下了哪个键以及是否还按下了Ctrl、Alt或Shift键。
来自MSDN的示例代码:
// Handle the KeyDown event to determine the type of character entered into the control.
private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    // Initialize the flag to false.
    nonNumberEntered = false;

    // Determine whether the keystroke is a number from the top of the keyboard.
    if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
    {
        // Determine whether the keystroke is a number from the keypad.
        if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
        {
            // Determine whether the keystroke is a backspace.
            if(e.KeyCode != Keys.Back)
            {
                // A non-numerical keystroke was pressed.
                // Set the flag to true and evaluate in KeyPress event.
                nonNumberEntered = true;
            }
        }
    }
    //If shift key was pressed, it's not a number.
    if (Control.ModifierKeys == Keys.Shift) {
        nonNumberEntered = true;
    }
}

0
使用表单的OnKeyPressed事件,并检查在eventArgs参数中是否按下所需的键组合。

0
除了一些答案外,如果在按钮或菜单项的标题中使用“&”符号,将导致它被加下划线,并可通过使用Alt + 在符号之前添加的字母来访问&。换句话说,如果你有一个标题为&File的菜单项,它将显示一个带有F下划线的选项,并且用户可以通过点击Alt + F来触发该菜单。

0

这取决于键盘快捷方式的范围。如果您希望在表单上的任何控件中使用键盘快捷方式而不使用工具栏,请设置

Form.KeyPreview = true;

在表单上设置 KeyPreview 属性。这将允许所有按键事件通过表单级别的 KeyPressKeyDownKeyUp 事件进行过滤,从而使单个键盘快捷键可以在一个位置处理,而不必在所有用户控件中重复功能。

MSDN: Form.KeyPreview Property


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接