• 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;

            ///

     
            /// 安装勾子 
            ///
     
            /// 外部调用的键盘处理事件 
            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.       ///

       

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

    22.       ///  

    23.       /// 由Hook程序发送的按键信息 

    24.       /// 是否拦截 

    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.    }

  • 相关阅读:
    vue 的报告页面,生成pdf,使用html2canvas , 下载pdf格式文件。多页分页下载
    【rust】12、编译为 linux x86 目标
    win10本地python第三方库安装成功,但是pycharm项目无法使用解决方案
    事务 还有这些用法,之前都不知道
    2311rust,到50版本更新
    分布式事务-TCC
    K8S中POD的控制器
    EXSI 实用指南 2024 -编译环境 Mac OS 安装篇(一)
    RPA能和什么技术结合?
    Oracle ADG的基本概念
  • 原文地址:https://blog.csdn.net/lijingguang/article/details/132740977