winform C#键盘钩子(Hook)拦截器,屏蔽键盘深入解析

这篇具有很好参考价值的文章主要介绍了winform C#键盘钩子(Hook)拦截器,屏蔽键盘深入解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。 
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。


运行机制
1、钩子链表和钩子子程:
每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程 序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。 一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始, 而最早安装的钩子放在最后,也就是后加入的先获得控制权。

Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。

钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。

KeyboardHook.cs 类

public class KeyboardHook
{
        private const int WH_KEYBOARD_LL = 13; //键盘 

        //键盘处理事件委托 ,当捕获键盘输入时调用定义该委托的方法. 
        private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);

        //客户端键盘处理事件 
        public delegate void ProcessKeyHandle(HookStruct param, out bool handle);

        //接收SetWindowsHookEx返回值 
        private static int _hHookValue = 0;

        //勾子程序处理事件 
        private HookHandle _KeyBoardHookProcedure;

        //Hook结构 
        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        //设置钩子 
        [DllImport("user32.dll")]
        private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId);

        //取消钩子 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        //调用下一个钩子 
        [DllImport("user32.dll")]
        private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

        //获取当前线程ID 
        [DllImport("kernel32.dll")]
        private static extern int GetCurrentThreadId();

        //Gets the main module for the associated process. 
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string name);

        private IntPtr _hookWindowPtr = IntPtr.Zero;

        //构造器 
        public KeyboardHook() { }

        //外部调用的键盘处理事件 
        private static ProcessKeyHandle _clientMethod = null;

        /// <summary> 
        /// 安装勾子 
        /// </summary> 
        /// <param name="hookProcess">外部调用的键盘处理事件</param> 
        public void InstallHook(ProcessKeyHandle clientMethod)
        {
            _clientMethod = clientMethod;

            // 安装键盘钩子 
            if (_hHookValue == 0)
            {
                _KeyBoardHookProcedure = new HookHandle(OnHookProc);

                _hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);

                _hHookValue = SetWindowsHookEx(
                WH_KEYBOARD_LL,
                _KeyBoardHookProcedure,
                _hookWindowPtr,
                0);

                //如果设置钩子失败. 
                if (_hHookValue == 0) UninstallHook();
            }
        }

        //取消钩子事件 
        public void UninstallHook()
        {
            if (_hHookValue != 0)
            {
                bool ret = UnhookWindowsHookEx(_hHookValue);
                if (ret) _hHookValue = 0;
            }
        }

        //钩子事件内部调用,调用_clientMethod方法转发到客户端应用。 
        private static int OnHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                //转换结构 
                HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));

                if (_clientMethod != null)
                {
                    bool handle = false;
                    //调用客户提供的事件处理程序。 
                    _clientMethod(hookStruct, out handle);
                    if (handle) return 1; //1:表示拦截键盘,return 退出 
                }
            }
            return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        }

}

Form窗体

  1. public partial class Form1 : Form

  2.    {

  3.       //勾子管理类 

  4.       private KeyboardHookLib _keyboardHook = null;

  5.       public frmKeyboardHook()

  6.       {

  7.          InitializeComponent();

  8.       }

  9.       private void button1_Click(object sender, EventArgs e)

  10.       {

  11.          //安装勾子 

  12.          _keyboardHook = new KeyboardHookLib();

  13.          _keyboardHook.InstallHook(this.OnKeyPress);

  14.       }

  15.       private void button2_Click(object sender, EventArgs e)

  16.       {

  17.          //取消勾子 

  18.          if (_keyboardHook != null) _keyboardHook.UninstallHook();

  19.       }

  20.       /// <summary> 

  21.       /// 客户端键盘捕捉事件. 

  22.       /// </summary> 

  23.       /// <param name="hookStruct">由Hook程序发送的按键信息</param> 

  24.       /// <param name="handle">是否拦截</param> 

  25.       public void OnKeyPress(KeyboardHookLib.HookStruct hookStruct, out bool handle)

  26.       {

  27.          handle = false; //预设不拦截任何键 

  28.          if (hookStruct.vkCode == 91) // 截获左win(开始菜单键)

  29.          {

  30.             handle = true;

  31.          }

  32.          if (hookStruct.vkCode == 92)// 截获右win

  33.          {

  34.             handle = true;

  35.          }

  36.          //截获Ctrl+Esc 

  37.          if (hookStruct.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control)

  38.          {

  39.             handle = true;

  40.          }

  41.          //截获alt+f4 

  42.          if (hookStruct.vkCode == (int)Keys.F4 && (int)Control.ModifierKeys == (int)Keys.Alt)

  43.          {

  44.             handle = true;

  45.          }

  46.          //截获alt+tab 

  47.          if (hookStruct.vkCode == (int)Keys.Tab && (int)Control.ModifierKeys == (int)Keys.Alt)

  48.          {

  49.             handle = true;

  50.          }

  51.          //截获F1 

  52.          if (hookStruct.vkCode == (int)Keys.F1)

  53.          {

  54.             handle = true;

  55.          }

  56.          //截获Ctrl+Alt+Delete 

  57.          if ((int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt + (int)Keys.Delete)

  58.          {

  59.             handle = true;

  60.          }

  61.          //如果键A~Z 

  62.          if (hookStruct.vkCode >= (int)Keys.A && hookStruct.vkCode <= (int)Keys.Z)

  63.          {

  64.             //挡掉B键 

  65.             if (hookStruct.vkCode == (int)Keys.B)

  66.             hookStruct.vkCode = (int)Keys.None; //设键为0 

  67.             handle = true;

  68.          }

  69.          Keys key = (Keys)hookStruct.vkCode;

  70.          label1.Text = "你按下:" + (key == Keys.None ? "" : key.ToString());

  71.       }

  72.    }文章来源地址https://www.toymoban.com/news/detail-788069.html

到了这里,关于winform C#键盘钩子(Hook)拦截器,屏蔽键盘深入解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VUE3 请求拦截器 响应拦截器

    1,导入axios  (使用axios进行接口的请求,页面发送http请求,很多情况我们要对请求和其响应进行特定的处理,如:判断token,设置请求头。如果请求数非常多,单独对每一个请求进行处理会变得非常麻烦,程序的优雅性也会大打折扣。所以axios为开发者提供了这样一个API:拦

    2024年02月16日
    浏览(47)
  • 自定义注解与拦截器实现不规范sql拦截(拦截器实现篇)

    最近考虑myBatis中sql语句使用规范的问题,如果漏下条件或者写一些不规范语句会对程序性能造成很大影响。最好的方法就是利用代码进行限制,通过拦截器进行sql格式的判断在自测环节就能找到问题。写了个简单情景下的demo,并通过idea插件来将myBatis的mapper方法都打上拦截器

    2024年01月22日
    浏览(43)
  • 【SpringBoot篇】Interceptor拦截器 | 拦截器和过滤器的区别

    拦截器(Interceptor)是一种软件设计模式,用于在应用程序处理请求或响应时对其进行拦截和修改。拦截器可以在整个应用程序中使用,用于执行跨越多个层的通用任务,如身份验证、授权、缓存、日志记录、性能计量等。 在Web开发中,拦截器通常用于在请求到达控制器之前

    2024年02月04日
    浏览(60)
  • WebService 客户端增加Header头、并且指定命名空间、添加拦截器(日志拦截器,自定义拦截器)、soap:Envelope 添加命名空间

    1.增加Header头 生成XML结果如下 2.添加拦截器 3.soap:Envelope 添加命名空间 生成XML结果如下

    2024年02月10日
    浏览(47)
  • 微信小程序封装request请求,包含请求拦截器,响应拦截器和请求重试功能

    在发送请求之前,先判断用户是否有token,没有就执行登陆请求,将token保存,然后再执行原来请求; 拥有token,就直接执行请求;但是用户的这个token可能是过期的,如果执行请求发现用户登陆过期,就统一返回40001,然后对40001的响应统一处理,执行登陆请求,再执行原来请

    2024年02月13日
    浏览(47)
  • 分布式项目 16 购物车系统,dubbo框架(重点是拦截器),优化userId,配合拦截器

    01.创建jt-cart项目 第一步: 第二步: 第三步: 第四步: 在pom.xml文件中添加jt-common的依赖,如图所示: 第五步: 添加插件 第六步:创建pojo实体类对象 说明:在jt-common项目下的com.jt.pojo创建Cart实体类 第七步:创建Dubbo接口 说明:在jt-common项目com.jt.service包下创建DubboCartSer

    2024年02月09日
    浏览(45)
  • MyBatis 拦截器介绍

    MyBatis 提供了一种插件 (plugin) 的功能,虽然叫做插件,但其实这是拦截器功能。那么拦截器拦截 MyBatis 中的哪些内容呢? 我们进入官网看一看: MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括: Executor

    2024年02月15日
    浏览(46)
  • Flume拦截器

    实现 Interceptor接口 方法1 是初始化: 方法2和3重载 拦截: 方法3 是关闭: 但是flume是通过内部类创建对象的

    2024年02月13日
    浏览(37)
  • springboot实现拦截器

    内容:继承 HandlerInterceptorAdapter 并实现 WebMvcConfigurer , 拦截器中的方法将preHandle-Controller-postHandle-affterCompletion的顺序执行。 注意:只有preHandle方法返回true时后面的方法才会执行。当拦截器链存在多个拦截器时,postHandle在所有拦截器内的所有拦截器返回成功时才会调用,而

    2024年02月02日
    浏览(44)
  • axios拦截器

    一般在项目中,发送http请求时会对请求和响应进行一些特定的处理:判断token,设置请求头等,如果要挨个对每个请求都做处理的话太麻烦,方便起见,axios提供了拦截器。 axios拦截器分为请求拦截器和响应拦截器: 请求拦截器 响应拦截器 也可以移除拦截器 可以自定义axi

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包