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

发布于:2023-09-14 ⋅ 阅读:(96) ⋅ 点赞:(0)

钩子(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.    }

本文含有隐藏内容,请 开通VIP 后查看