详细讲解在C#中如何使用鼠标钩子

2025-10-22 23:45:25

1、使用钩子之前,必须创建钩子,使用函数SetWindowsHookEx,函数原型如下:

HHOOK WINAPI SetWindowsHookEx(

__in int idHook,  \\钩子类型

__in HOOKPROC lpfn,  \\回调函数地址

__in HINSTANCE hMod,  \\实例句柄,钩子所在的实例的句柄

__in DWORD dwThreadId);  \\线程ID,钩子所监视的线程的线程ID

函数说明:

1、钩子的类型:分两种,全局钩子和局部钩子。全局钩子可以抓取其他进程的消息,分为抓取其他进程中某一特定线程的消息和抓取所有进程的消息两种。而局部钩子只抓取当前进程的消息。

2、 回调函数。当抓取到消息时,操作系统将自动调用该函数处理消息。在C#中要使用委托。

3、实例句柄,对于线程序钩子,参数传NULL;对于系统钩子:参数为钩子DLL的句柄。

4、线程ID:对于全局钩子,该参数为NULL。

2、钩子函数是回调函数。当钩子捕获到指定的消息后,系统将会自动调用该函数进行处理。注意:钩子函数应当“短小精悍”,不能占用太多的时间,最好是只用来捕获和传递消息,对消息的处理应放在其他地方。函数原型如下:LRESULT WINAPI MyHookProc( int    nCode ,    // 指定是否需要处理该消息 WPARAM wParam,    // 附加消息wParam

 LPARAM  lParam    // 附加消息lParam

 ) 

注意:在C#中应当使用委托,而且应带在钩子函数的结尾调用CallNextHookEx函数处理下一条消息,函数原型如下:

LRESULT CallNextHookEx( HHOOK   hhk,   // 钩子句柄 int    nCode,  // nCode WPARAM  wParam,   // 附加消息wParam

 LPARAM  lParam   // 附加消息lParam

)

3、使用完钩子后一定要卸载钩子,否则可能会导致BUG,甚至导致死机。使用函数UnhookWin_

dowsHookEx()卸载钩子即可。函数原形如下:

BOOL UnhookWindowsHookEx(

HHOOK  hhk    // 要卸载的钩子句柄。 )

1、启动VS,创建C# WinForm项目,如下:

详细讲解在C#中如何使用鼠标钩子

2、主窗口Form1布局,如下:

详细讲解在C#中如何使用鼠标钩子

3、添加新建类Win32Api,该类封装Api函数,代码如下:

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

    }

4、添加新建类MouseHook,该类封装对鼠标钩子的操作,代码如下:

    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;

    }

5、然后,在Form1中添加代码,如下:

 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();

        }

    }

6、完成后,调试运行,结果如下:

详细讲解在C#中如何使用鼠标钩子

详细讲解在C#中如何使用鼠标钩子

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢