前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >键盘钩子之完美得到单键或多组合键的信息

键盘钩子之完美得到单键或多组合键的信息

作者头像
Shunnet
发布2021-06-11 15:28:26
1.3K0
发布2021-06-11 15:28:26
举报

【先看代码】

代码语言:javascript
复制
    class KeyboardHook
    {
        #region 私有变量
        private IntPtr m_pKeyboardHook = IntPtr.Zero;/// 键盘钩子句柄
        private delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);/// 钩子委托声明
        private HookProc m_KeyboardHookProcedure;/// 键盘钩子委托实例
        public const int idHook = 13;/// 底层的钩子变量
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr pInstance, int threadId);/// 安装钩子
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]/// 卸载钩子
        private static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string name);
        /// 传递钩子
        /// <param name="pHookHandle">是您自己的钩子函数的句柄。用该句柄可以遍历钩子链</param>
        /// <param name="nCode">把传入的参数简单传给CallNextHookEx即可</param>
        /// <param name="wParam">把传入的参数简单传给CallNextHookEx即可</param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx(IntPtr pHookHandle, int nCode, Int32 wParam, IntPtr lParam);
        [StructLayout(LayoutKind.Sequential)]
        private struct KeyMSG
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        protected const int WM_QUERYENDSESSION = 0x0011;
        protected const int WM_KEYDOWN = 0x100;
        protected const int WM_KEYUP = 0x101;
        protected const int WM_SYSKEYDOWN = 0x104;
        protected const int WM_SYSKEYUP = 0x105;
        protected const byte VK_SHIFT = 0x10;
        protected const byte VK_CAPITAL = 0x14;
        protected const byte VK_NUMLOCK = 0x90;
        protected const byte VK_LSHIFT = 0xA0;
        protected const byte VK_RSHIFT = 0xA1;
        protected const int VK_LWIN = 91;
        protected const int VK_RWIN = 92;
        protected const byte VK_LCONTROL = 0xA2;
        protected const byte VK_RCONTROL = 0x3;
        protected const byte VK_LALT = 0xA4;
        protected const byte VK_RALT = 0xA5;
        protected const byte LLKHF_ALTDOWN = 0x20;
        private static int pp = 0;//热键的返回值
        private static bool isInstall = false;//是否安装钩子,true为安装
        #endregion

        #region 事件的声明
        /// <summary>
        /// 返回数据委托
        /// </summary>
        /// <param name="Key"></param>
        public delegate void _RetKey(string Key);
        /// <summary>
        /// 返回按下的键盘数据
        /// </summary>
        public _RetKey RteKey;
        #endregion

        #region 方法
        /// <summary>
        /// 钩子捕获消息后,对消息进行处理
        /// </summary>
        /// <param nCode="int">标识,键盘是否操作</param> 
        /// <param wParam="int">键盘的操作值</param>
        /// <param lParam="IntPtr">指针</param>
        private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode > -1)
            {
                KeyMSG keyboardHookStruct = (KeyMSG)Marshal.PtrToStructure(lParam, typeof(KeyMSG));//获取钩子的相关信息
                KeyEventArgs e = new KeyEventArgs((Keys)(keyboardHookStruct.vkCode));//获取KeyEventArgs事件的相磁信息
                switch (wParam)
                {
                    case WM_KEYDOWN://键盘按下操作
                    case WM_SYSKEYDOWN:
                        Shun_KeyDown(e);//调用该事件
                        break;
                    case WM_KEYUP://键盘松开操作
                    case WM_SYSKEYUP:
                        Shun_KeyUp(e);//调用该事件
                        break;
                }
            }
            return pp;//是否屏蔽当前热键,1为屏蔽,2为执行
        }
        /// <summary>
        /// 按下的键码集合
        /// </summary>
        Dictionary<string, int> keyValuePairs = new Dictionary<string, int>();
        /// <summary>
        /// 按下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Shun_KeyDown(KeyEventArgs e)
        {
            if (!keyValuePairs.ContainsKey(e.KeyData.ToString()))
            {
                if (e.KeyData == Keys.LShiftKey || e.KeyData == Keys.RShiftKey)
                {
                    if (!keyValuePairs.ContainsKey(Keys.Shift.ToString()))
                    {
                        keyValuePairs.Add(Keys.Shift.ToString(), (int)Keys.Shift);
                    }
                }
                else if (e.KeyData == Keys.LControlKey || e.KeyData == Keys.RControlKey)
                {
                    if (!keyValuePairs.ContainsKey(Keys.Control.ToString()))
                    {
                        keyValuePairs.Add(Keys.Control.ToString(), (int)Keys.Control);
                    }
                }
                else if (e.KeyData == Keys.LMenu || e.KeyData == Keys.RMenu)
                {
                    if (!keyValuePairs.ContainsKey(Keys.Alt.ToString()))
                    {
                        keyValuePairs.Add(Keys.Alt.ToString(), (int)Keys.Alt);
                    }
                }
                else
                {
                    keyValuePairs.Add(e.KeyData.ToString(), e.KeyValue);
                }
            }
        }
        /// <summary>
        /// 松开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Shun_KeyUp(KeyEventArgs e)
        {
            List<string> ListData = new List<string>();
            string RetKeyCode = string.Empty;
            var DicSort = from objDic in keyValuePairs orderby objDic.Value descending select objDic;  //倒叙
            //var DicSort = from objDic in keyValuePairs orderby objDic.Value select objDic;  //升序
            foreach (KeyValuePair<string, int> Data in DicSort)
            {
                RetKeyCode += Data.Key + " + ";
                ListData.Add(Data.Key);
            }
            for (int i = 0; i < ListData.Count; i++)
            {
                keyValuePairs.Remove(ListData[i]);
            }
            if (!RetKeyCode.Equals(""))
            {
                RteKey(RetKeyCode.Substring(0, RetKeyCode.Length - 3));
            }
        }
        #endregion
        
        #region 安装、卸载钩子
        /// <summary>
        /// 安装钩子
        /// </summary>
        /// <returns>是否安装成功</returns>
        public bool Start()
        {
            if (this.m_pKeyboardHook == IntPtr.Zero)//如果键盘的句柄为空
            {
                this.m_KeyboardHookProcedure = new HookProc(KeyboardHookProc);//声明一个托管钩子
                this.m_pKeyboardHook = SetWindowsHookEx(idHook, m_KeyboardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);//安装钩子
                if (this.m_pKeyboardHook == IntPtr.Zero)//如果安装失败
                {
                    this.Stop();//卸载钩子
                    return false;
                }
            }
            isInstall = true;//安装了钩子
            return true;
        }
        /// <summary>
        /// 卸载钩子
        /// </summary>
        /// <returns>是否卸载成功</returns>
        public bool Stop()
        {
            if (isInstall == false)//如果没有安装钩子
            {
                return true;
            }
            bool result = true;
            if (this.m_pKeyboardHook != IntPtr.Zero)//如果安装了钩子
            {
                result = (UnhookWindowsHookEx(this.m_pKeyboardHook) && result);//卸载钩子
                this.m_pKeyboardHook = IntPtr.Zero;//清空键盘的钩子句柄
            }
            return result;
        }
        #endregion 公共方法
    }

【实现流程】

代码语言:javascript
复制
        KeyboardHook keyboardHook = new KeyboardHook();
        //开始
        private void button1_Click(object sender, EventArgs e)
        {
            keyboardHook.Start();  //绑定钩子
            keyboardHook.RteKey += Info;  //绑定事件
            button2.Enabled = true;
            button1.Enabled = false;
        }
        /// <summary>
        ///数据返回
        /// </summary>
        /// <param name="Key"></param>
        public void Info(string Key)
        {
            textBox1.Text += Key+"\r\n";
        }
        //关闭
        private void button2_Click(object sender, EventArgs e)
        {
            keyboardHook.Stop();  //拆卸钩子
            button1.Enabled = true;
            button2.Enabled = false;
        }

【运行结果】

简简单单,记得点赞分享哦    

本文作者:[博主]大顺

本文链接:https://shunnet.top/fYVZ7j

版权声明:转载注明出处,谢谢

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档