检查是不是在 Winforms 中按下热键
Posted
技术标签:
【中文标题】检查是不是在 Winforms 中按下热键【英文标题】:Check if hot key pressed in Winforms检查是否在 Winforms 中按下热键 【发布时间】:2021-02-25 02:14:26 【问题描述】:要获取热键Ctrl+A
,我们可以在Form1_KeyDown
中使用以下语句。
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
MessageBox.Show("Test");
要捕获Ctrl+Alt+A
,我们可以使用:
if (e.Control && e.Alt)
if (e.KeyCode == Keys.A)
// Your code goes here
问题是如何捕捉Ctrl+A+B
这样的热键?
【问题讨论】:
您的意思是Ctrl+A, CTRL+B
(CTRL+A
后跟 B
,而 CTRL
键仍被按下 - 或者,CTRL
键尚未释放)。
@Jimi 仍然按下
在 WinForms 中没有简单的方法可以做到这一点。您必须保留布尔字典并跟踪按下的键。或者,您可以导入 WPF 运行时并将Keyboard.IsKeyDown
与KeyDown
事件结合使用。你也可以求助于 Win32 API 并使用 GetKeyState
这个“热键”是否应该只在您的应用程序中有效?
【参考方案1】:
这里有一些东西可以帮助您开始使用IMessageFilter。
这将在按下 Ctrl-A-B 时触发,而不是在释放时触发。它目前还会在按住这些键时重复触发。这可以通过混合中的另一个布尔变量来改变。这绝对不是完美的……
public partial class Form1 : Form
public Form1()
InitializeComponent();
private MyFilter mf = new MyFilter();
private void Form1_Load(object sender, EventArgs e)
mf.Ctrl_A_B += Mf_Ctrl_A_B;
Application.AddMessageFilter(mf);
private void Mf_Ctrl_A_B()
Console.WriteLine("Ctrl-A-B was held down!");
public class MyFilter : IMessageFilter
private bool keyCtrl;
private bool keyA;
private bool keyB;
private const int WM_KEYDOWN = 0x100;
private const int WM_KEYUP = 0x101;
public delegate void dlg_Ctrl_A_B();
public event dlg_Ctrl_A_B Ctrl_A_B;
public bool PreFilterMessage(ref Message m)
Keys keyData;
switch (m.Msg)
case WM_KEYDOWN:
keyData = (Keys)((int)m.WParam);
switch (keyData)
case Keys.ControlKey:
keyCtrl = true;
break;
case Keys.A:
keyA = true;
break;
case Keys.B:
keyB = true;
break;
if (keyCtrl && keyA && keyB)
Ctrl_A_B?.Invoke();
break;
case WM_KEYUP:
keyData = (Keys)((int)m.WParam);
switch (keyData)
case Keys.ControlKey:
keyCtrl = false;
break;
case Keys.A:
keyA = false;
break;
case Keys.B:
keyB = false;
break;
break;
return false;
【讨论】:
Ctrl+J+E
或任何其他组合怎么样?我们应该为每个声明一个变量吗?
就是这样,或者创建某种Dictionary<Keys, bool>
,以便您可以查找和切换特定值。无论哪种方式都会变得一团糟......
嗯,我不这么认为,如果你允许的话。只需一个变量就足够了。类似于另一个答案。适用于任何Ctrl+Any+Any
。不管投票的事情,试试吧。感谢您的宝贵时间。
@dr.null Dictionary
方法将是最灵活的。如果明天他们要求 Ctrl-A-B-C,即使您的方法也需要修改。【参考方案2】:
您可以将第一个键视为附加或自定义修饰符以扩展快捷键的范围。
声明一个类变量来保存该修饰符:
private Keys KeyModifier = Keys.None;
如下处理KeyDown
事件:
private void FormWhatEver_KeyDown(object sender, KeyEventArgs e)
if (e.Control)
switch (e.KeyCode)
case Keys.B:
if (KeyModifier == Keys.A)
// Handle Ctrl+AB
else
// Handle Ctrl+B
break;
case Keys.C:
if (KeyModifier == Keys.A)
// Handle Ctrl+AC
else
// Handle Ctrl+C
break;
default:
// Otherwise set the pressed key as a key modifier.
KeyModifier = e.KeyCode;
break;
释放Control
键时重置修饰符。这对于使上述工作正常工作很重要。
private void FormWhatEver_KeyUp(object sender, KeyEventArgs e)
if (!e.Control) KeyModifier = Keys.None;
【讨论】:
以上是关于检查是不是在 Winforms 中按下热键的主要内容,如果未能解决你的问题,请参考以下文章
如何防止在WinForms TextBox中按下alt键引起的哔声?
我是不是需要在我的 iphone 应用程序中按下每个按钮时不断检查连接?