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

    }

運行結果:

 

 鼠標在窗口移動的時候,顯示鼠標當前的坐標位置(在整個顯示屏幕中的坐標)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM