我想创建一个组件,允许我们使用一个任意命令关联复合键盘快捷键,就像Visual Studio IDE和Microsoft Office一样。
也就是说,这些键盘快捷键由多个按键序列组成,比如Ctrl+W+C。在Visual Studio中,这会打开类视图。当按下第一组键(Ctrl+W)时,状态栏会显示消息“(Ctrl + W)已按下。等待弦的第二个键...”。
我想创建一个组件,允许我们使用一个任意命令关联复合键盘快捷键,就像Visual Studio IDE和Microsoft Office一样。
也就是说,这些键盘快捷键由多个按键序列组成,比如Ctrl+W+C。在Visual Studio中,这会打开类视图。当按下第一组键(Ctrl+W)时,状态栏会显示消息“(Ctrl + W)已按下。等待弦的第二个键...”。
针对键盘弦的问题,我认为目前还没有现成的选项可供选择。
但是,建模应该很简单。我会创建一个单独的类,可能称为KeyboardChordProvider
。它需要了解表单级别的键盘事件。如其他地方所述,Form.KeyPreview
属性必须为true
。对于这个提供程序,仅订阅Form.KeyPress
事件可能就足够了。如果传入表单,则可以在提供程序的构造函数中完成所有这些操作。
您需要向提供程序注册潜在的按键。
内部实例将跟踪当前状态。每当观察到表示弦的第一个按键时,您将更新提供程序的状态并引发事件,以便订阅者可以设置文本:(CTRL+W) was pressed. Waiting for second key of chord...
如果下一个按键与潜在的次要选项匹配,则表示匹配成功,并且可以引发包含输入的击键详细信息的ChordPressed
事件。或者,您可能只需调用在注册弦时给提供程序的特定回调(以避免在ChordPressed
事件处理程序中使用switch语句或其他分派)。
如果任何时候,按键不匹配潜在的下一个选项,则您将重置提供程序的状态。
在提供程序的内部,您可以使用树结构对可能的按键进行建模。提供程序的当前状态只是特定的树节点。一开始,根节点将处于活动状态。如果子节点与击键匹配,则它成为当前节点,以期望下一个击键。如果子节点是叶节点,则表示已匹配整个弦,您将引发ChordPressed
事件(传递到达该点的击键链)或调用存储在叶节点中的回调。每当没有按键与子节点匹配时,请重置为使根节点处于活动状态。
我认为这个设计会实现你想要的效果。
// 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;
}
}
这取决于键盘快捷方式的范围。如果您希望在表单上的任何控件中使用键盘快捷方式而不使用工具栏,请设置
Form.KeyPreview = true;
在表单上设置 KeyPreview
属性。这将允许所有按键事件通过表单级别的 KeyPress、KeyDown 和 KeyUp 事件进行过滤,从而使单个键盘快捷键可以在一个位置处理,而不必在所有用户控件中重复功能。