钩子函数(线程钩子C#)

该例子实现的效果是:拦截键盘的输入,如果输入的是B键或者是b键,就弹出消息框来表示一下拦截到了

步骤:

1 新建Winform应用程序,工程命名为HookDemo,把默认生成的窗体名称改为HookTest

2 新建一个类,名为Hook

编写代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;  //引入的命名空间
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;            //引入的命名空间

namespace HookDemo
{
    internal enum HookType { 
        Keyboard=2   //键盘钩子类型
    }

    //定义委托,该委托的参数是固定这样写
    internal delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);

    public class Hook
    {
        //记录下一个Hook编号
        static IntPtr _nextHookPtr;

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

        //卸载钩子
        [DllImport("User32.dll")]
        internal extern static void UnhookWindowsHookEx(IntPtr handle);

        //安装钩子
        [DllImport("User32.dll")]
        internal extern static IntPtr SetWindowsHookEx(int idHook,[MarshalAs(UnmanagedType.FunctionPtr)]HookProc Ipfn,IntPtr hanstance,int threadID);


        //获取下一个钩子
        [DllImport("User32.dll")]
        internal extern static IntPtr CallNextHookEx(IntPtr handle,int code,IntPtr wparam,IntPtr Iparam);



        //委托回调的方法
        IntPtr MyHookProc(int code,IntPtr wparam,IntPtr Iparam) {

            if (code < 0)
            {
                //让后面的程序处理该消息
                return CallNextHookEx(_nextHookPtr, code, wparam, Iparam);
            }

            //用户输入的是b或者B
            if (wparam.ToInt32() == 98 || wparam.ToInt32() == 66)
            {
                //设置文本输入框为a
                MessageBox.Show("我拦截到B或者b");
                //该消息结束
                return (IntPtr)1;
            }

            else
            {
                //让后面的程序处理该消息
                return IntPtr.Zero;
            }
            
        }





        /// <summary>
        /// 从外部调用设置钩子
        /// </summary>
        public void SetHook() {
            //已经设置过钩子了,不能重复设置
            if(_nextHookPtr!=IntPtr.Zero){
                return;
            }

            //设置钩子委托回调函数(委托方法注册)
            HookProc myhookProc = new HookProc(MyHookProc);
        
            //把该钩子加到Hook链中
            _nextHookPtr = SetWindowsHookEx((int)HookType.Keyboard,myhookProc,IntPtr.Zero,GetCurrentThreadId());
        }


        /// <summary>
        /// 从外部调用卸载钩子
        /// </summary>
        public void UnHook() { 
            if(_nextHookPtr!=IntPtr.Zero){
                //从Hook链中取消
                UnhookWindowsHookEx(_nextHookPtr);
            }

            _nextHookPtr = IntPtr.Zero;
        }
    }
}

3 找到默认生成的窗体,并找到该窗体的FormClosing事件函数,如下图:

4  编写默认窗体下的类HookTest如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HookDemo
{
    public partial class HookTest : Form
    {
        Hook hook = new Hook();
        public HookTest()
        {
            InitializeComponent();
            //设置钩子
            hook.SetHook();
        }

        
        //页面关闭事件函数
        private void HookTest_FormClosing(object sender, FormClosingEventArgs e)
        {
            //卸载钩子
            hook.UnHook();
        }
    }
}

5 运行程序,并按键盘的B键,输出如下图:

扫描二维码关注公众号,回复: 9282871 查看本文章
发布了66 篇原创文章 · 获赞 48 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/zxy13826134783/article/details/90273523