鼠标钩子程序

  终于把我这个鼠标钩子程序实现了,刚开始我把句柄赋值赋错了,也就是SetWindowsHookEx(int idHook, HookProc lpfn,IntPtr hInstance, int threadId)的第三个参数,现在找好了,程序运行一切正常。

  钩子(Hook),是windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理windows消息或特定事件。
  钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

  我这里实现了一个简单的鼠标钩子程序,用于监视鼠标,把获取的鼠标坐标显示在wpf应用窗口。

  第一步:声明API函数

        [DllImport("kernel32.dll")]

        public static extern IntPtr GetModuleHandle(string name);

        //安装钩子

        [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(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

  使用钩子,需要使用WindowsAPI函数,所以要先声明这些API函数。声明一下API函数,以后就可以直接调用了。

  第二步:声明、定义

        public delegate int HookProc(int nCode, int wParam, IntPtr lParam);

       public HookProc MyProcedure;

        //获取模块句柄

        IntPtr intp = GetModuleHandle(null);

        //定义钩子句柄

        public static int hHook = 0;

        //定义钩子类型

        public const int WH_MOUSE_LL = 14;

  钩子必须使用标准的钩子子程,钩子子程就是一段方法,就是处理上面提到的把获取的鼠标坐标显示在wpf应用窗口操作。

  钩子子程必须按照HookProc(int nCode, int wParam, IntPtr lParam)这种结构定义,三个参数会得到关于消息的数据。

  GetModuleHandle获取一个应用程序或动态链接库的模块句柄,参数null将返回自身应用程序句柄。

  当使用SetWindowsHookEx函数安装钩子成功后会返回钩子子程的句柄,hHook变量记录返回的句柄,如果hHook不为0则说明钩子安装成功。

  WH_MOUSE_LL参数用于截获整个系统的鼠标事件。

  第三步:安装钩子、卸载钩子、写钩子子程

        private void button1_Click(object sender, RoutedEventArgs e)

        {

         if(hHook==0)

           {

               IntPtr intp = GetModuleHandle("user32.dll");

               MyProcedure = new HookProc(this.MouseHookProc);

               //这里挂节钩子

               hHook = SetWindowsHookEx(WH_MOUSE_LL, MyProcedure, intp, 0);

               if (hHook == 0)

               {

                   MessageBox.Show("SetWindowsHookEx Failed");

                   return;

               }

               button1.Content = "卸载钩子";

           }

           else

           {

               bool ret = UnhookWindowsHookEx(hHook);

               if(ret == false )

               {

                   MessageBox.Show("UnhookWindowsHookEx Failed");

                   return;

               }

               hHook = 0;

               button1.Content = "安装钩子";

           }

        }

        public int MouseHookProc(int nCode, int wParam, IntPtr lParam)

        {

            POINT MyPOINT = (POINT)Marshal.PtrToStructure(lParam, typeof(POINT));

            if (nCode < 0)

            {

                return CallNextHookEx((IntPtr)hHook, nCode, (IntPtr)wParam, lParam);

            }

            else

            {

                String strCaption = "x = " + MyPOINT.x.ToString("d") + "  y = " + MyPOINT.y.ToString("d");

                text1.Text = strCaption;

                return CallNextHookEx((IntPtr)hHook, nCode, (IntPtr)wParam, lParam);

            }

       }

    }

    [StructLayout(LayoutKind.Sequential)]

    public class POINT

    {

        public int x;

        public int y;

    }

  SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId)函数将钩子加入到钩子链表中,说明一下四个参数:

  idHook 钩子类型,即确定钩子监听何种消息。

  lpfn 钩子子程的地址指针。如果threadId参数为0 或是一个由别的进程创建的线程的标识,lpfn必须指向dll中的钩子子程。 除此以外,lpfn可以指向当前进程的一段钩子子程代码。钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。

  hInstance应用程序实例的句柄。

  趣味验证:

  这个程序可以显示鼠标在任何位置的坐标,拖动鼠标时,程序会实时刷新显示鼠标的坐标。鲁大师测试我的电脑分辨率是1280x800,现在我们来验证下,运行我上面的程序,鼠标指向电脑屏幕左上角和右下角,分别显示如图:

鼠标钩子程序

鼠标钩子程序

  代码清单:

    public partial class MainWindow : Window

    {

        [DllImport("kernel32.dll")]

        public static extern IntPtr GetModuleHandle(string name);

        //安装钩子

        [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(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);



        public delegate int HookProc(int nCode, int wParam, IntPtr lParam);

        public HookProc MyProcedure;

        //获取模块句柄

        IntPtr intp = GetModuleHandle(null);

        //定义钩子句柄

        public static int hHook = 0;

        //定义钩子类型

        public const int WH_MOUSE_LL = 14;



        public MainWindow()

        {

            InitializeComponent();

        }



        private void button1_Click(object sender, RoutedEventArgs e)

        {

         if(hHook==0)

         {

               MyProcedure = new HookProc(this.MouseHookProc);

               //这里挂节钩子

               hHook = SetWindowsHookEx(WH_MOUSE_LL, MyProcedure, intp, 0);

               if (hHook == 0)

               {

                   MessageBox.Show("SetWindowsHookEx Failed");

                   return;

               }

               button1.Content = "卸载钩子";

           }

           else

           {

               bool ret = UnhookWindowsHookEx(hHook);

               if(ret == false )

               {

                   MessageBox.Show("UnhookWindowsHookEx Failed");

                   return;

               }

               hHook = 0;

               button1.Content = "安装钩子";

           }

        }

        public int MouseHookProc(int nCode, int wParam, IntPtr lParam)

        {

            POINT MyPOINT = (POINT)Marshal.PtrToStructure(lParam, typeof(POINT));

            if (nCode < 0)

            {

                return CallNextHookEx((IntPtr)hHook, nCode, (IntPtr)wParam, lParam);

            }

            else

            {

                String strCaption = "x = " + MyPOINT.x.ToString("d") + "  y = " + MyPOINT.y.ToString("d");

                text1.Text = strCaption;

                return CallNextHookEx((IntPtr)hHook, nCode, (IntPtr)wParam, lParam);

            }

       }

    }

    [StructLayout(LayoutKind.Sequential)]

    public class POINT

    {

        public int x;

        public int y;

    }
View Code

 

2013-06-02

你可能感兴趣的:(程序)