方法1:使用winform 的Control里的keydown,和keyup,监控并检测键值。
添加一个textbox,设置readonly为true,绑定鼠标单击事件
private void textBox1_MouseClick(object sender, MouseEventArgs e)
{
this.KeyPreview = true; // 确保Form能捕获键盘事件
this.KeyDown += new KeyEventHandler(MainForm_KeyDown);
this.KeyUp += new KeyEventHandler(MainForm_KeyUp);
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if(!textBox1.Focused) return ;
string combination = "";
if (e.Control) ctrlDown = true;
if (e.Alt) altDown = true;
if (e.Shift) shiftDown = true;
if (ctrlDown) combination += "Ctrl+";
if (altDown) combination += "Alt+";
if (shiftDown) combination += "Shift+";
if ((e.KeyCode == Keys.ControlKey) | (e.KeyCode == Keys.Menu) | (e.KeyCode == Keys.ShiftKey))
{ combination = combination.Remove(combination.Length - 1, 1); }
else
{ combination += Enum.GetName(typeof(Keys), e.KeyCode); }
textBox1.Text = combination;
}
private void MainForm_KeyUp(object sender, KeyEventArgs e)
{
if (!textBox1.Focused) return;
if (e.KeyCode == Keys.ControlKey) ctrlDown = false;
if (e.KeyCode == Keys.Menu) altDown = false;
if (e.KeyCode == Keys.ShiftKey) shiftDown = false;
}
每按一个键就会触发MainForm_KeyDown相应,同时按多个按键也是依次触发,运气好的情况下e.KeyData里面会包含同时按下的组合键的所有键值,但不稳定,还是配合MainForm_KeyUp依次检查有哪些按键被按下更可靠。
主要检测ctrl、alt、shift三个键有没有被按下,设立三个键对应的bool值,当这三个键触发keydown时,bool就为true,当这三个键触发keyup时,bool就为false;若bool为true,就输出对应的键值(如"Ctrl+"),再检测最后一次触发keydown时具体的按键代码,若为ctrl、alt、shift三者中的一个,那输出字符串就减一,去掉“+”,否则就输出对应的按键代码。
方法2:仅使用winform 的Control里的keydown,用Control.ModifierKeys查询(ctrl+alt+shift)有无被按下。
添加一个textbox,设置readonly为true,绑定鼠标单击事件
private void textBox1_MouseClick(object sender, MouseEventArgs e)
{
this.KeyPreview = true; // 确保Form能捕获键盘事件
this.KeyDown += new KeyEventHandler(MainForm_KeyDown);
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (!textBox1.Focused) return;
string combination = "";
if ((Control.ModifierKeys & Keys.Control) == Keys.Control) combination += "Ctrl+";
if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt) combination += "Alt+";
if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) combination += "Shift+";
if ((e.KeyCode == Keys.ControlKey) | (e.KeyCode == Keys.Menu) | (e.KeyCode == Keys.ShiftKey))
{ combination = combination.Remove(combination.Length - 1, 1); }
else
{ combination += Enum.GetName(typeof(Keys), e.KeyCode); }
textBox1.Text = combination;
}
以上方式要求按键顺序,即其它按键在(ctrl+alt+shift)之后再按,不然其它按键不会显示。
当窗体最小化、隐藏、或是失去焦点时,keydown就不起作用了,需要用其它方法检测组合键,并响应。可以使用Windows的钩子(Hook)机制,但是感觉比较麻烦还会影响全局键盘,就自建一个while循环,实时检测按键状态,(ctrl+alt+shift)三建可仍以通过Control.ModifierKeys查询,并对比快捷热键内是否包含该按键 (防止出现快捷键是ctrl+a时按ctrl+alt+a也会响应),其它按键通过GetKeyState方式抓取;
[DllImport("user32.dll")]
private static extern short GetKeyState(int nVirtKey);
private void DoWork()
{
while (_isRunning)
{
Application.DoEvents();
string combination = "Ctrl+Alt+A";// 要检测的快捷热键
string[] parts = combination.Split('+');
for (int counter = parts.Length - 1; counter >= 0; counter--)
{
string part = parts[counter].ToString();
if (part == "") break;
if ((combination.Contains("Ctrl")) ^ ((Control.ModifierKeys & Keys.Control) == Keys.Control)) break;
if ((combination.Contains("Shift")) ^ ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)) break;
if ((combination.Contains("Alt")) ^ ((Control.ModifierKeys & Keys.Alt) == Keys.Alt)) break;
if ((part != "Ctrl") && (part != "Shift") && (part != "Alt"))
{
Keys keyCode = (Keys)Enum.Parse(typeof(Keys), part);
int virtualKey = (int)keyCode;// 转换为虚拟键码
bool KeyDown = (GetKeyState(virtualKey) & 0x8000) == 0x8000;
if (!KeyDown) break;
}
if (counter == 0)
{
MessageBox.Show("快捷热键:"+combination+" 被按了");
}
}
Thread.Sleep(100);
}
}