【问题标题】:How do I create compound keyboard shortcuts in a Windows Forms application?如何在 Windows 窗体应用程序中创建复合键盘快捷键?
【发布时间】:2008-10-10 16:05:18
【问题描述】:

我想创建一个组件,让我们能够拥有与任意命令相关联的复合键盘快捷键,就像 Visual Studio IDE 和 Microsoft Office 所做的那样。

即由一系列多次击键组成的键盘快捷键,例如Ctrl + W + C。在 Visual Studio 中,这将打开类视图。当按下第一组键时 (Ctrl + W) 消息“(Ctrl + W) 被按下。等待和弦的第二个键... " 出现在状态栏中。

【问题讨论】:

  • 键盘快捷键和弦是一个多键快捷键。就像 Ctrl + W、C 一样,它会打开类视图。当按下第一组键 (CTRL+W) 时,状态条中会出现消息“(CTRL+W) 已按下。等待第二个和弦键...”。我想准确地重现这一点。
  • 我为 WPF 找到了一个实现。 insystusa.com/Products.aspx
  • 这不是和弦的相反吗?

标签: .net winforms keyboard-shortcuts


【解决方案1】:

具体回答键盘和弦的问题,我认为目前还没有现成的选项可供您使用。

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

您需要向提供商注册可能的击键。

在内部,此实例将跟踪当前状态。每当观察到表示和弦第一个键的击键时,您将更新提供者的状态并引发一个事件,以便订阅者可以设置文本:(CTRL+W) 被按下。等待和弦的第二个键...

如果下一次击键匹配潜在的次要选项,那么您就有匹配项,并且可以引发包含所输入击键详细信息的ChordPressed 事件。或者,您可能只调用在注册和弦时提供给提供者的特定回调(以避免在 ChordPressed 事件处理程序中使用 switch 语句或其他调度)。

如果在任何时候,击键与潜在的 next 选项不匹配,那么您将重置提供程序的状态。

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

我认为这个设计会达到你想要的。

【讨论】:

  • 感谢 Drew 提出的解决方案。更重要的是。感谢您没有半途而废。
  • 这里把这个接口记录下来,以后记得实现我的组件。 msdn.microsoft.com/en-us/library/…
【解决方案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;
    }
}

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      这取决于键盘快捷键的范围。如果您希望在不使用工具栏的情况下从窗体上的任何控件使用键盘快捷键,请设置

      Form.KeyPreview = true;
      

      在表格上。这将允许表单级别的 KeyPressKeyDownKeyUp 事件过滤所有按键事件,这将允许单个键盘快捷键在一个位置处理,而不是在所有用户控件中复制功能。

      MSDN: Form.KeyPreview Property

      【讨论】:

        【解决方案5】:

        除了一些答案之外,在按钮或菜单项的标题中使用和号会导致它带有下划线,并且可以通过使用 Alt + 您前面的字母来访问&符号&。

        换句话说,如果您有一个标题为 &File 的菜单项,它将在 F 下方显示下划线,并且用户可以通过单击 Alt + F.

        【讨论】: