• C# 钩子函数使用


    1. 什么是钩子

    hook(钩子)是windows提供的一种消息处理机制平台,是指在程序正常运行中接受信息之前预先启动的函数,用来检查和修改传给该程序的信息,(钩子)实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出, 在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递(return)。

    2. 钩子函数的声明

    C#是.NET Framework平台的相伴语言,用它本身的类库和编译器提供的方法是无法实现全局钩子的。但实际上对于非托管代码的调用在C#中是成立的,钩子函数存在于user32.dll中,使用DllImport属性可以引用非托管代码类库中的方法。

    钩子函数的安装:

      //安装钩子
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    
            public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

    钩子函数卸载:

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

    钩子函数使用:

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

    3.钩子函数的使用

    首先声明一个委托:

            //委托+事件(把钩到的消息封装为事件,由调用者处理)
    
            public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
    
            public event MouseMoveHandler MouseMoveEvent;

    定义一个鼠标钩子类:

        public class MouseHook
        {
    
            private Point point;
    
            private Point Point
            {
    
                get { return point; }
    
                set
                {
                    if (point != value)
                    {
                        point = value;
                        if (MouseMoveEvent != null)
                        {
                            var e = new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0);
                            MouseMoveEvent(this, e);
                        }
                    }
                }
            }
    
            private int hHook;
    
            public const int WH_MOUSE_LL = 14;
    
            public Win32Api.HookProc hProc;
    
            public MouseHook() { this.Point = new Point(); }
    
            public int SetHook()
            {
    
                hProc = new Win32Api.HookProc(MouseHookProc);
    
                hHook = Win32Api.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
    
                return hHook;
    
            }
    
            public void UnHook()
            {
    
                Win32Api.UnhookWindowsHookEx(hHook);
    
            }
    
            private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
    
                Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));
    
                if (nCode < 0)
                {
    
                    return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
    
                }
    
                else
                {
    
                    this.Point = new Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
    
                    return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
    
                }
    
            }
    
            //委托+事件(把钩到的消息封装为事件,由调用者处理)
    
            public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
    
            public event MouseMoveHandler MouseMoveEvent;
    
        }

    调用钩子:

       public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            MouseHook mh;
    
            private void Form1_Load(object sender, EventArgs e)
            {
    
                mh = new MouseHook();
    
                mh.SetHook();
    
                mh.MouseMoveEvent += mh_MouseMoveEvent;
    
            }
    
            void mh_MouseMoveEvent(object sender, MouseEventArgs e)
            {
    
                int x = e.Location.X;
    
                int y = e.Location.Y;
    
                label1.Text = string.Format("当前鼠标位置为:({0},{1})", x, y);
    
            }
    
            private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
    
                mh.UnHook();
            }
        }

    Win32Api 导入类:

    需要引入 using System.Runtime.InteropServices; 命名空间

    public class Win32Api
        {
    
            [StructLayout(LayoutKind.Sequential)]
            public class POINT
            {
                public int x;
    
                public int y;
    
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public class MouseHookStruct
            {
    
                public POINT pt;
    
                public int hwnd;
    
                public int wHitTestCode;
    
                public int dwExtraInfo;
    
            }
    
            public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
    
            //安装钩子
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    
            public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
    
            //卸载钩子
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    
            public static extern bool UnhookWindowsHookEx(int idHook);
    
            //调用下一个钩子
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    
            public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
    
        }

    运行结果:

     鼠标在窗口移动的时候,显示鼠标当前的坐标位置(在整个显示屏幕中的坐标)。

  • 相关阅读:
    ArcEngine 一些实现代码(转载)
    关于GIS支持的地理数据源的命名空间
    SpringBoot-Web配置
    RedisGeo
    JedisCluster
    Java并发编程:Lock
    java并发编程:线程变量-ThreadLocal类
    java并发编程:线程池-Executors
    解决Mybatis配置ORM映射 时分秒都为0
    Kafka的存储机制以及可靠性
  • 原文地址:https://www.cnblogs.com/runningRain/p/13066101.html
Copyright © 2020-2023  润新知