您的位置:首页 > 编程语言 > C#

windows操作系统 C#编写鼠标钩子

2014-10-22 11:13 225 查看
要做一个东西,由于捕获不到相应的事件,而这个东西又要用鼠标操作,所以找了下质料可以用鼠标钩子实现。自己也没用过鼠标钩子,看了别人的例子,实践到项目中就解决问题了。把代码记录下来以备以后用和更深入的学习。


class MouseHook
    {
        //枚举定义
public enum WH_Codes : int
{
/// <summary>
/// 底层鼠标钩子
/// </summary>
WH_MOUSE_LL = 14
}

public enum WM_MOUSE : int
{
/// <summary>
/// 鼠标开始
/// </summary>
WM_MOUSEFIRST = 0x200,

/// <summary>
/// 鼠标移动
/// </summary>
WM_MOUSEMOVE = 0x200,

/// <summary>
/// 左键按下
/// </summary>
WM_LBUTTONDOWN = 0x201,

/// <summary>
/// 左键释放
/// </summary>
WM_LBUTTONUP = 0x202,

/// <summary>
/// 左键双击
/// </summary>
WM_LBUTTONDBLCLK = 0x203,

/// <summary>
/// 右键按下
/// </summary>
WM_RBUTTONDOWN = 0x204,

/// <summary>
/// 右键释放
/// </summary>
WM_RBUTTONUP = 0x205,

/// <summary>
/// 右键双击
/// </summary>
WM_RBUTTONDBLCLK = 0x206,

/// <summary>
/// 中键按下
/// </summary>
WM_MBUTTONDOWN = 0x207,

/// <summary>
/// 中键释放
/// </summary>
WM_MBUTTONUP = 0x208,

/// <summary>
/// 中键双击
/// </summary>
WM_MBUTTONDBLCLK = 0x209,

/// <summary>
/// 滚轮滚动
/// </summary>
/// <remarks>WINNT4.0以上才支持此消息</remarks>
WM_MOUSEWHEEL = 0x020A
}

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
/// <summary>
/// 鼠标钩子事件结构定义
/// </summary>
/// <remarks>详细说明请参考MSDN中关于 MSLLHOOKSTRUCT 的说明</remarks>
[StructLayout(LayoutKind.Sequential)]
public struct MouseHookStruct
{
public POINT Point;
public UInt32 MouseData;
public UInt32 Flags;
public UInt32 Time;
public UInt32 ExtraInfo;
}

#region DLL导入
/// <summary>
/// 安装钩子
/// </summary>
/// <param name="idHook"></param>
/// <param name="lpfn"></param>
/// <param name="hInstance"></param>
/// <param name="threadId"></param>
/// <returns></returns>
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SetWindowsHookEx(WH_Codes idHook, HookProc lpfn,
IntPtr pInstance, int threadId);

/// <summary>
/// 卸载钩子
/// </summary>
/// <param name="idHook"></param>
/// <returns></returns>
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);

/// <summary>
/// 传递钩子
/// </summary>
/// <param name="idHook"></param>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(IntPtr pHookHandle, int nCode,
Int32 wParam, IntPtr lParam);

#endregion DLL导入

//鼠标钩子句柄
private IntPtr m_pMouseHook = IntPtr.Zero;
/// <summary>
/// 钩子委托声明
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
/// <summary>
/// 鼠标钩子委托实例
/// </summary>
/// <remarks>
/// 不要试图省略此变量,否则将会导致
/// 激活 CallbackOnCollectedDelegate 托管调试助手 (MDA)。
/// 详细请参见MSDN中关于 CallbackOnCollectedDelegate 的描述
/// </remarks>
private HookProc m_MouseHookProcedure;

#region 事件定义

/// <summary>
/// 鼠标移动事件
/// </summary>
/// <remarks>当鼠标移动或者滚轮滚动时触发</remarks>
public event MouseEventHandler OnMouseMove;

/// <summary>
/// 鼠标按下事件
/// </summary>
public event MouseEventHandler OnMouseDown;

/// <summary>
/// 按键释放事件
/// </summary>
public event MouseEventHandler OnMouseUp;

#endregion

#region 私有方法
/// <summary>
/// 鼠标钩子处理函数
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if ((nCode >= 0) && (this.OnMouseMove != null)
&& (wParam == (int)WM_MOUSE.WM_MOUSEMOVE ||wParam == (int)WM_MOUSE.WM_MOUSEWHEEL))
{
//MouseHookStruct MouseInfo = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
this.OnMouseMove(null,null);
}
if ((nCode >= 0) && (this.OnMouseDown != null)&&(wParam==(int)WM_MOUSE.WM_LBUTTONDOWN||wParam==(int)WM_MOUSE.WM_RBUTTONDOWN))
{
MouseButtons button = MouseButtons.None;
switch (wParam)
{
case (int)WM_MOUSE.WM_LBUTTONDOWN:
//case WM_LBUTTONUP:
//case WM_LBUTTONDBLCLK:
button = MouseButtons.Left;
break;
case (int)WM_MOUSE.WM_RBUTTONDOWN:
//case WM_RBUTTONUP:
//case WM_RBUTTONDBLCLK:
button = MouseButtons.Right;
break;
}
MouseEventArgs e = new MouseEventArgs(
button,
0,
0,
0,
0
);
this.OnMouseDown(null, e);
}
if ((nCode >= 0) && (this.OnMouseDown != null)
&& (wParam == (int)WM_MOUSE.WM_LBUTTONUP || wParam == (int)WM_MOUSE.WM_RBUTTONUP))
{
MouseButtons button = MouseButtons.None;
switch (wParam)
{
case (int)WM_MOUSE.WM_LBUTTONUP:
//case WM_LBUTTONUP:
//case WM_LBUTTONDBLCLK:
button = MouseButtons.Left;
break;
case (int)WM_MOUSE.WM_RBUTTONUP:
//case WM_RBUTTONUP:
//case WM_RBUTTONDBLCLK:
button = MouseButtons.Right;
break;
}
MouseEventArgs e = new MouseEventArgs(
button,
0,
0,
0,
0
);
this.OnMouseUp(null, e);
}
return CallNextHookEx(this.m_pMouseHook, nCode, wParam, lParam);
}
#endregion

#region 公共方法
/// <summary>
/// 安装钩子
/// </summary>
/// <returns></returns>
public bool InstallHook()
{

IntPtr pInstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().ManifestModule);
//pInstance = (IntPtr)4194304;
// IntPtr pInstanc2 = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly());
// Assembly.GetExecutingAssembly().GetModules()[0]
// 假如没有安装鼠标钩子
if (this.m_pMouseHook == IntPtr.Zero)
{
this.m_MouseHookProcedure = new HookProc(this.MouseHookProc);
this.m_pMouseHook = SetWindowsHookEx(WH_Codes.WH_MOUSE_LL, this.m_MouseHookProcedure, pInstance, 0);
if (this.m_pMouseHook == IntPtr.Zero)
{
this.UnInstallHook();
return false;
}
}
return true;
}

/// <summary>
/// 卸载钩子
/// </summary>
/// <returns></returns>
public bool UnInstallHook()
{
bool result = true;
if (this.m_pMouseHook != IntPtr.Zero)
{
result = (UnhookWindowsHookEx(this.m_pMouseHook) && result);
this.m_pMouseHook = IntPtr.Zero;
}
return result;
}

#endregion

}


用该封装的类,首先注册钩子,然后添加相应的鼠标事件。其中鼠标事件什么时候调用和传递的参数都是在鼠标处理函数MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)里面完成,本例中由于鼠标处理不需要参数,仅需要获取按下的是左键还是又见,所以原本定义的MouseEventArg参数类其他属性都赋值为0。而鼠标处理函数MouseHookProc的调用则是在鼠标钩子注册方法里面调用的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: