赞
踩
应用程序有自己的截获方式,那么操作系统呢,也有自己的截获方式,那就是使用钩子技术。(这里以windows系统为例)
windows应用是通过windows消息机制去做驱动的,那么什么是消息机制呢,就是你电脑中所有的操作,都可以被操作系统捕获,然后操作系统把捕获的消息推送到消息队列。然后对应的应用程序去从消息队列中获得响应。
那么钩子是用来干嘛的呢?
如上图:
应用程序的所有IO操作,我们操作系统是可以捕获到的。钩子作用就是,再操作系统准备把数据推送到消息队列的时候,进行截断。然后处理想处理的东西。
自己在C#中定义一个类,用来做钩子操作。
/// <summary>
/// 装载钩子
/// </summary>
/// <param name="idHook">钩子类型(比如 鼠标 键盘 等)</param>
/// <param name="lpfn">钩子函数(截获后想如何操作) </param>
/// <param name="hInstance">模块ID(当前模块实例ID 也可理解为进程ID NULL表示当前应用程序自己)</param>
/// <param name="threadId">线程id</param>
/// <returns></returns>
//装置钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
因为SetWindowsHookEx
为非托管函数,所以需要DllImport
进行dll引用和extern
进行标识。
解释SetWindowsHookEx
函数:
它就相当于创建钩子的入口,需要创建什么样的钩子,对应传值就可以呢。
SetWindowsHookEx微软地址
那么具体如何装载了:看代码。
static int hMouseHook = 0; //鼠标钩子句柄 //鼠标常量 public const int WH_MOUSE_LL = 14; //mouse hook constant //钩子处理函数 public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); HookProc MouseHookProcedure; //声明鼠标钩子事件类型. public void Start() { //安装鼠标钩子 if (hMouseHook == 0) { //生成一个HookProc的实例. MouseHookProcedure = new HookProc(MouseHookProc); using (System.Diagnostics.Process curProcess = System.Diagnostics.Process.GetCurrentProcess()) using (System.Diagnostics.ProcessModule curModule = curProcess.MainModule) hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProcedure, GetModuleHandle(curModule.ModuleName), 0); //如果装置失败停止钩子 if (hMouseHook == 0) { Stop(); throw new Exception("SetWindowsHookEx failed."); } } }
注释:
1.WH_MOUSE_LL
为装载类型,比如它表示的是装载的监视鼠标的钩子。也可以装载其他类型,比如键盘等,具体其他类型可以去官方查找。官网
2.MouseHookProcedure
为钩子会的的函数,也就是你需要操作的业务逻辑。
3.hMouseHook
作用是接收钩子函数操作后的值。如果函数成功,则返回值是挂钩过程的句柄。如果函数失败,则返回值为 NULL
。hMouseHook
将会作为CallNextHookEx
函数的第一个值。CallNextHookEx
作用就是将截断的操作续上。
private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam) { **看到这了给你些福利:C#接单交流群452760896** //如果正常运行并且用户要监听鼠标的消息 if ((nCode >= 0) && (OnMouseActivity != null)) { MouseButtons button = MouseButtons.None; int clickCount = 0; switch (wParam) { case WM_LBUTTONDOWN: button = MouseButtons.Left; clickCount = 1; break; case WM_LBUTTONUP: button = MouseButtons.Left; clickCount = 1; //从回调函数中得到鼠标的信息 MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct)); MouseEventArgs e = new MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, 0); //发送ctrl+c SendCtrl_C(0); OnMouseActivity(this, e); //释放 SendCtrl_C(2); break; case WM_LBUTTONDBLCLK: button = MouseButtons.Left; clickCount = 2; break; case WM_RBUTTONDOWN: button = MouseButtons.Right; clickCount = 1; break; case WM_RBUTTONUP: button = MouseButtons.Right; clickCount = 1; break; case WM_RBUTTONDBLCLK: button = MouseButtons.Right; clickCount = 2; break; } } //将挂钩信息传递到当前挂钩链中的下一个挂钩过程。 挂钩过程可以在处理挂钩信息之前或之后调用此函数。 return CallNextHookEx(hMouseHook, nCode, wParam, lParam); }
注释:
1.如果MouseHookProc
不返回CallNextHookEx
而返回1 那么你注册的是什么类型钩子,什么就会失效(屏蔽)。
public void Stop()
{
bool retMouse = true;
if (hMouseHook != 0)
{
retMouse = UnhookWindowsHookEx(hMouseHook);
hMouseHook = 0;
}
//如果卸下钩子失败
if (!(retMouse)) throw new Exception("UnhookWindowsHookEx failed.");
}
下面给出鼠标钩子类的所有代码:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows.Forms; namespace Translate { /// <summary> /// 监控鼠标钩子 /// </summary> public class MouseHook { private const int WM_MOUSEMOVE = 0x200; private const int WM_LBUTTONDOWN = 0x201; private const int WM_RBUTTONDOWN = 0x204; private const int WM_MBUTTONDOWN = 0x207; private const int WM_LBUTTONUP = 0x202; private const int WM_RBUTTONUP = 0x205; private const int WM_MBUTTONUP = 0x208; private const int WM_LBUTTONDBLCLK = 0x203; private const int WM_RBUTTONDBLCLK = 0x206; private const int WM_MBUTTONDBLCLK = 0x209; //全局的事件 public event MouseEventHandler OnMouseActivity; static int hMouseHook = 0; //鼠标钩子句柄 //鼠标常量 public const int WH_MOUSE_LL = 14; //mouse hook constant HookProc MouseHookProcedure; //声明鼠标钩子事件类型. //声明一个Point的封送类型 [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; } [DllImport("user32.dll")] public static extern void keybd_event(int bVk, byte bScan, int dwFlags, int dwExtraInfo); //用于发送鼠标热键操作 /// <summary> /// 获取模块名 /// </summary> /// <param name="lpModuleName"></param> /// <returns></returns> [DllImport("kernel32.dll")] public static extern IntPtr GetModuleHandle(string lpModuleName); /// <summary> /// 装载钩子 /// </summary> /// <param name="idHook">钩子类型(比如 鼠标 键盘 等)</param> /// <param name="lpfn">钩子函数(截获后想如何操作)</param> /// <param name="hInstance">模块ID(当前模块实例ID 也可理解为进程ID NULL表示当前应用程序自己) Null表示当前进行</param> /// <param name="threadId">线程id 设为0 表示全局 局部的请获取当前的线程 </param> /// <returns></returns> //装置钩子的函数 [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, Int32 wParam, IntPtr lParam); //钩子处理函数 /// <summary> /// /// </summary> /// <param name="nCode">如何处理当前消息(有几种状态值)</param> /// <param name="wParam">(指定消息是否由当前进程发送。如果消息是由当前进程发送的,则它不是零;否则为NULL)附加消息</param> /// <param name="lParam">截获下来的附加信息(指向包含消息详细信息的CWPRETSTRUCT结构的指针)</param> /// <returns></returns> public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); /// <summary> /// 墨认的构造函数构造当前类的实例. /// </summary> public MouseHook() { } //析构函数. ~MouseHook() { Stop(); } public void Start() { //安装鼠标钩子 if (hMouseHook == 0) { //生成一个HookProc的实例. MouseHookProcedure = new HookProc(MouseHookProc); //获取当前进程 using (System.Diagnostics.Process curProcess = System.Diagnostics.Process.GetCurrentProcess()) //获取当前进程的模块 using (System.Diagnostics.ProcessModule curModule = curProcess.MainModule) //配置全局钩子 全局钩子模块必须动态获取 hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProcedure, GetModuleHandle(curModule.ModuleName), 0); //如果装置失败停止钩子 if (hMouseHook == 0) { Stop(); throw new Exception("SetWindowsHookEx failed."); } } } public void Stop() { bool retMouse = true; if (hMouseHook != 0) { retMouse = UnhookWindowsHookEx(hMouseHook); hMouseHook = 0; } //如果卸下钩子失败 if (!(retMouse)) throw new Exception("UnhookWindowsHookEx failed."); } private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam) { //如果正常运行并且用户要监听鼠标的消息 if ((nCode >= 0) && (OnMouseActivity != null)) { MouseButtons button = MouseButtons.None; int clickCount = 0; switch (wParam) { case WM_LBUTTONDOWN: button = MouseButtons.Left; clickCount = 1; break; case WM_LBUTTONUP: button = MouseButtons.Left; clickCount = 1; //从回调函数中得到鼠标的信息 MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct)); MouseEventArgs e = new MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, 0); //发送ctrl+c SendCtrl_C(0); OnMouseActivity(this, e); //释放 SendCtrl_C(2); break; case WM_LBUTTONDBLCLK: button = MouseButtons.Left; clickCount = 2; break; case WM_RBUTTONDOWN: button = MouseButtons.Right; clickCount = 1; break; case WM_RBUTTONUP: button = MouseButtons.Right; clickCount = 1; break; case WM_RBUTTONDBLCLK: button = MouseButtons.Right; clickCount = 2; break; } } return CallNextHookEx(hMouseHook, nCode, wParam, lParam); } /// <summary> /// 发送 和 释放 /// </summary> /// <param name="dwFlags"> //这里为整数类型 0为按下,2为释放</param> private void SendCtrl_C(int dwFlags) { keybd_event(Convert.ToInt32(System.Windows.Forms.Keys.ControlKey), 0, dwFlags, 0); keybd_event(Convert.ToInt32(System.Windows.Forms.Keys.C), 0, dwFlags, 0); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。