c#检测并显示组合按键(ctrl+alt+shift)快捷热键,在窗体隐藏或失去焦点时检测(全局)组合热键(非钩子(Hook)机制)

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

C#如何在后台捕捉按键 [此问题的推荐答案] API别忘了 using System.Runtime.InteropServices; [DllImport("user32.dll")] public static extern UInt32 RegisterHotKey(IntPtr hWnd, UInt32 id, UInt32 fsModifiers, UInt32 vk); //API public Form1() { InitializeComponent(); RegisterHotKey(this.Handle, 247696411, 0, (UInt32)Keys.F10); //注册热键 } //重写消息循环 protected override void WndProc(ref Message m) { const int WM_HOTKEY = 0x0312; // m.WParam.ToInt32() 要和 注册热键的第2个参数一样 if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 247696411) //判断热键 { //写上你的代码 } base.WndProc(ref m); } 写上代码后 只要 在程序运行按F10就可以触发热键更改按键可以在 注册改 RegisterHotKey(this.Handle, 247696411, 0, (UInt32)Keys.***); http://baike.baidu.com/view/1080084.html?tp=0_10 这里有RegisterHotKey 的介绍 RegisterHotKey 函数功能:该函数定义一个系统范围的热键。 函数原型:BOOL RegisterHotKey(HWND hWnd,intid,UINT fsModifiers,UINT vk); 参数: hWnd:接收热键产生WM_HOTKEY消息的窗口句柄。若该参数NULL,传递给调用线程的WM_HOTKEY消息必须在消息循环中中进行处理。 id:定义热键的标识符。调用线程中的其他热键不能使用同样的标识符。应用功能程序必须定义一个0X0000-0xBFFF范围的值。一个共享的动态链接库(DLL)必须定义一个0xC000-0xFFFF范围的值伯GlobalAddAtom函数返回该范围)。为了避免与其他动态链接库定义的热键冲突,一个DLL必须使用GlobalAddAtom函数获得热键的标识符。 fsModifoers:定义为了产生WM_HOTKEY消息而必须与由nVirtKey参数定义的键一起按下的键。该参数可以是如下值的组合: MOD_ALT:按下的可以是任一Alt键。MOD_CONTROL:按下的可以是任一Ctrl键。 MOD_SHIFT:按下的可以是任一Shift键。 MOD_WIN:按下的可以是任一Windows按键。这些键可以用Microsoft Windows日志记录下来。 vk:定义热键的虚拟键码。 返回值:若函数调用成功,返回一个O值。若函数调用失败,则返回值为0。若要获得更多的错误信息,可以调用GetLastError函数。 本贴来自ZDNetChina中文社区 http://bbs.zdnet.com.cn ,本贴地址:http://bbs.zdnet.com.cn/viewthread.php?tid=93775 RegisterHotKey   函数功能:该函数定义一个系统范围的热键。   函数原型:BOOL RegisterHotKey(HWND hWnd,intid,UINT fsModifiers,UINT vk);   参数:   hWnd:接收热键产生WM_HOTKEY消息的窗口句柄。若该参数NULL,传递给调用线程的WM_HOTKEY消息必须在消息循环中中进行处理。   id:定义热键的标识符。调用线程中的其他热键不能使用同样的标识符。应用功能程序必须定义一个0X0000-0xBFFF范围的值。一个共享的动态链接库(DLL)必须定义一个0xC000-0xFFFF范围的值伯GlobalAddAtom函数返回该范围)。为了避免与其他动态链接库定义的热键冲突,一个DLL必须使用GlobalAddAtom函数获得热键的标识符。   fsModifoers:定义为了产生WM_HOTKEY消息而必须与由nVirtKey参数定义的键一起按下的键。该参数可以是如下值的组合:   MOD_ALT:按下的可以是任一Alt键。MOD_CONTROL:按下的可以是任一Ctrl键。   MOD_SHIFT:按下的可以是任一Shift键。   MOD_WIN:按下的可以是任一Windows按键。这些键可以用Microsoft Windows日志记录下来。   vk:定义热键的虚拟键码。   返回值:若函数调用成功,返回一个O值。若函数调用失败,则返回值为0。若要获得更多的错误信息,可以调用GetLastError函数。   备注:当某键被接下,系统在所有的热键中寻找匹配者。一旦找到一个匹配的热键,系统将把WM_HOTKEY消息传递给登记了该热键的线程的消息队列。该消息被传送到队列头部,因此它将在下一轮消息循环中被移去。该函数不能将热键同其他线程创建的窗口关联起来。   若为一热键定义的击键己被其他热键所定义,则RegisterHotKey函数调用失败。   若hWnd参数标识的窗口已用与id参数定义的相同的标识符登记了一个热键,则参数fsModifiers和vk的新值将替代这些参数先前定义的值。   Windows CE:Windows CE 2.0以上版本对于参数fsModifiers支持一个附加的标志位。叫做MOD_KEYUP。   若设置MOD_KEYUP位,则当发生键被按下或被弹起的事件,窗口将发送WM_HOTKEY消息。   RegisterHotKey可以被用来在线程之间登记热键。   速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:不支持;头文件:winuser.h;库文件:user32.lib
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值