我正在寻找实现常见 Windows 键盘快捷键的最佳方法(例如 Ctrl+F、Ctrl+N kbd>) 在我用 C# 编写的 Windows Forms 应用程序中。
该应用程序有一个主窗体,它承载许多子窗体(一次一个)。当用户按 Ctrl+F 时,我想显示一个自定义搜索表单。搜索表单将取决于应用程序中当前打开的子表单。
我正在考虑在 ChildForm_KeyDown 事件中使用类似的东西:
if (e.KeyCode == Keys.F && Control.ModifierKeys == Keys.Control)
// Show search form
但这不起作用。当您按下某个键时,该事件甚至不会触发。解决办法是什么?
您可能忘记将表单的 KeyPreview 属性设置为 True。覆盖 ProcessCmdKey() 方法是通用解决方案:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == (Keys.Control | Keys.F)) {
MessageBox.Show("What the Ctrl+F?");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
在您的主窗体上
将 KeyPreview 设置为 True 使用以下代码添加 KeyDown 事件处理程序 private void MainForm_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.KeyCode == Keys.N) { SearchForm searchForm = new SearchForm(); searchForm.Show(); } }
最好的方法是使用菜单助记符,即在主窗体中设置菜单条目,并为其分配所需的键盘快捷键。然后其他一切都在内部处理,您所要做的就是实现在该菜单条目的 Click
事件处理程序中执行的适当操作。
menu mnemonics
真实样本?
你甚至可以试试这个例子:
public class MDIParent : System.Windows.Forms.Form
{
public bool NextTab()
{
// some code
}
public bool PreviousTab()
{
// some code
}
protected override bool ProcessCmdKey(ref Message message, Keys keys)
{
switch (keys)
{
case Keys.Control | Keys.Tab:
{
NextTab();
return true;
}
case Keys.Control | Keys.Shift | Keys.Tab:
{
PreviousTab();
return true;
}
}
return base.ProcessCmdKey(ref message, keys);
}
}
public class mySecondForm : System.Windows.Forms.Form
{
// some code...
}
如果您有一个菜单,那么更改 ToolStripMenuItem
的 ShortcutKeys
属性应该可以解决问题。
如果没有,您可以创建一个并将其 visible
属性设置为 false。
在主表单中,您必须:
确保将 KeyPreview 设置为 true(默认为 TRUE)
添加 MainForm_KeyDown(..) - 通过它您可以在此处设置您想要的任何快捷方式。
另外,我在谷歌上找到了这个,我想把这个分享给那些仍在寻找答案的人。 (对于全球)
我认为你必须使用 user32.dll
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
{
/* Note that the three lines below are not needed if you only want to register one hotkey.
* The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); // The key of the hotkey that was pressed.
KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF); // The modifier of the hotkey that was pressed.
int id = m.WParam.ToInt32(); // The id of the hotkey that was pressed.
MessageBox.Show("Hotkey has been pressed!");
// do something
}
}
进一步阅读此http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/
Hans's answer 对于新手来说可能会更容易一些,所以这是我的版本。
您无需使用 KeyPreview
,将其设置为 false
。要使用下面的代码,只需将其粘贴到您的 form1_load
下方并使用 F5 运行即可查看它是否有效:
protected override void OnKeyPress(KeyPressEventArgs ex)
{
string xo = ex.KeyChar.ToString();
if (xo == "q") //You pressed "q" key on the keyboard
{
Form2 f2 = new Form2();
f2.Show();
}
}
在 WinForm 中,我们总是可以通过以下方式获取 Control Key 状态:
bool IsCtrlPressed = (Control.ModifierKeys & Keys.Control) != 0;
Hans' answer. 的 VB.NET 版本
(Visual Studio 中有一个 ProcessCmdKey 函数模板。)
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If (keyData = (Keys.Control Or Keys.F)) Then
' call your sub here, like
SearchDialog()
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class
KeyPreview
是必不可少的。例如,当需要按下快捷键来禁止输入但仍然允许触发单独的MenuStrip
事件时。ProcessCmdKey
方法会强制重复事件触发逻辑。