方法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);
     }
 }

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐