如何在Windows窗体应用程序中创建复合键盘快捷方式?

时间:2021-11-19 23:52:58

I want to create a component that allows us to have compound keyboard shortcuts associated with an arbitrary command, like the Visual Studio IDE and Microsoft Office do.

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

That is, keyboard shortcuts consisting of a sequence of multiple keystrokes, such as Ctrl + W + C. In Visual Studio this opens the class-view. When the first set of the keys is pressed (Ctrl + W) the message "(Ctrl + W) was pressed. Waiting for the second key of the chord..." appears in the status bar.

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

5 个解决方案

#1


12  

In answer to the question of keyboard chords specifically, I do not believe there is a ready-made option available to you at this point.

在具体回答键盘和弦的问题时,我不相信现在有一个现成的选项供你使用。

However, it should be simple enough to model. I would create a single class, perhaps KeyboardChordProvider. It will need to know about keyboard events at the form level. As stated elsewhere, the Form.KeyPreview property must be true. It may be enough for this provider to subscribe to the Form.KeyPress event. You could do all of this in the provider's constructor if you passed in the form.

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

You would need to register the potential keystrokes with the provider.

您需要向提供商注册潜在的击键。

Internally this instance will track the current state. Whenever a keystroke is observed that represents the first key of the chord, you would update the provider's state and raise an event so that a subscriber could set text: (CTRL+W) was pressed. Waiting for second key of chord...

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

If the next keystroke matches a potential secondary option, then you have a match and could raise a ChordPressed event containing the details of the strokes entered. Alternatively, you might just call a particular callback that was given to the provider at the time the chord was registered (to avoid having a switch statement or some other dispatch in the ChordPressed event handler).

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

If, at any time, a keystroke does not match a potential next option, then you would reset the state of the provider.

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

Internal to the provider you might model the possible keystrokes using a tree structure. The current state of the provider is just a particular tree node. At the beginning, the root node would be active. If a child matches a keystroke then it becomes the current node in anticipation of the next stroke. If the child was a leaf node, then an entire chord has matched and you would raise ChordPressed event (passing the chain of strokes that got you to that point) or invoke the callback stored in the leaf. Whenever no keystroke matches a child, reset back to making the root node active.

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

I think this design would achieve what you want.

我认为这种设计可以达到你想要的效果。

#2


2  

Menu controls have property named ShortCut where you can assign a value. When you press that shortcut key, that menu item will be invoked. Use that property for the commands that has a corresponding menu.

菜单控件具有名为ShortCut的属性,您可以在其中指定值。按下该快捷键时,将调用该菜单项。将该属性用于具有相应菜单的命令。

If you need shortcuts that won't be available on the menus, then you'll have to handle that your self via the KeyUp or KeyDown events, either on the form or the control. A KeyEventArgs object will be passed to your handler, and you can check which key is pressed, and whether the Ctrl, Alt or Shift keys were also pressed.

如果您需要在菜单上无法使用的快捷方式,那么您必须通过表单或控件上的KeyUp或KeyDown事件处理您的自己。 KeyEventArgs对象将传递给您的处理程序,您可以检查按下了哪个键,以及是否还按下了Ctrl,Alt或Shift键。

Sample code from MSDN:

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


0  

Use the form's OnKeyPressed event and check if the desired key combination was pressed in the eventArgs argument

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

#4


0  

It depends on the scope of the keyboard shortcut. If you want a keyboard shortcut to be used from any control on the Form without using a toolbar, set

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

Form.KeyPreview = true;

on the form. This will allow all keypress events to get filtered by the KeyPress, KeyDown and KeyUp events at the form level which will allow a single keyboard shortcut to be handled in one location instead of duplicating the functionality in all user controls.

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

MSDN: Form.KeyPreview Property

MSDN:Form.KeyPreview属性

#5


0  

In addition to some of the answers, using an ampersand in the caption of a button, or menu item, will cause it to be underlined, and accessible by using Alt + the letter you preceded by the ampersand &.

除了一些答案之外,在按钮或菜单项的标题中使用&符号将使其加下划线,并且可以使用Alt +前面带有&符号的字母进行访问。

In other words, if you have a menu item captioned &File it will display with an underline under the F and the user can trigger the menu by clicking Alt + F.

换句话说,如果您有一个菜单项标题和文件,它将在F下显示下划线,用户可以通过单击Alt + F来触发菜单。

#1


12  

In answer to the question of keyboard chords specifically, I do not believe there is a ready-made option available to you at this point.

在具体回答键盘和弦的问题时,我不相信现在有一个现成的选项供你使用。

However, it should be simple enough to model. I would create a single class, perhaps KeyboardChordProvider. It will need to know about keyboard events at the form level. As stated elsewhere, the Form.KeyPreview property must be true. It may be enough for this provider to subscribe to the Form.KeyPress event. You could do all of this in the provider's constructor if you passed in the form.

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

You would need to register the potential keystrokes with the provider.

您需要向提供商注册潜在的击键。

Internally this instance will track the current state. Whenever a keystroke is observed that represents the first key of the chord, you would update the provider's state and raise an event so that a subscriber could set text: (CTRL+W) was pressed. Waiting for second key of chord...

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

If the next keystroke matches a potential secondary option, then you have a match and could raise a ChordPressed event containing the details of the strokes entered. Alternatively, you might just call a particular callback that was given to the provider at the time the chord was registered (to avoid having a switch statement or some other dispatch in the ChordPressed event handler).

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

If, at any time, a keystroke does not match a potential next option, then you would reset the state of the provider.

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

Internal to the provider you might model the possible keystrokes using a tree structure. The current state of the provider is just a particular tree node. At the beginning, the root node would be active. If a child matches a keystroke then it becomes the current node in anticipation of the next stroke. If the child was a leaf node, then an entire chord has matched and you would raise ChordPressed event (passing the chain of strokes that got you to that point) or invoke the callback stored in the leaf. Whenever no keystroke matches a child, reset back to making the root node active.

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

I think this design would achieve what you want.

我认为这种设计可以达到你想要的效果。

#2


2  

Menu controls have property named ShortCut where you can assign a value. When you press that shortcut key, that menu item will be invoked. Use that property for the commands that has a corresponding menu.

菜单控件具有名为ShortCut的属性,您可以在其中指定值。按下该快捷键时,将调用该菜单项。将该属性用于具有相应菜单的命令。

If you need shortcuts that won't be available on the menus, then you'll have to handle that your self via the KeyUp or KeyDown events, either on the form or the control. A KeyEventArgs object will be passed to your handler, and you can check which key is pressed, and whether the Ctrl, Alt or Shift keys were also pressed.

如果您需要在菜单上无法使用的快捷方式,那么您必须通过表单或控件上的KeyUp或KeyDown事件处理您的自己。 KeyEventArgs对象将传递给您的处理程序,您可以检查按下了哪个键,以及是否还按下了Ctrl,Alt或Shift键。

Sample code from MSDN:

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


0  

Use the form's OnKeyPressed event and check if the desired key combination was pressed in the eventArgs argument

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

#4


0  

It depends on the scope of the keyboard shortcut. If you want a keyboard shortcut to be used from any control on the Form without using a toolbar, set

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

Form.KeyPreview = true;

on the form. This will allow all keypress events to get filtered by the KeyPress, KeyDown and KeyUp events at the form level which will allow a single keyboard shortcut to be handled in one location instead of duplicating the functionality in all user controls.

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

MSDN: Form.KeyPreview Property

MSDN:Form.KeyPreview属性

#5


0  

In addition to some of the answers, using an ampersand in the caption of a button, or menu item, will cause it to be underlined, and accessible by using Alt + the letter you preceded by the ampersand &.

除了一些答案之外,在按钮或菜单项的标题中使用&符号将使其加下划线,并且可以使用Alt +前面带有&符号的字母进行访问。

In other words, if you have a menu item captioned &File it will display with an underline under the F and the user can trigger the menu by clicking Alt + F.

换句话说,如果您有一个菜单项标题和文件,它将在F下显示下划线,用户可以通过单击Alt + F来触发菜单。