C#实现鼠标钩子可以用来监视和控制鼠标事件,比如截取特定的鼠标事件、拦截在系统中发生的鼠标消息等。这里提供完整攻略,具体过程如下:
准备工作
在开始实现之前,需要准备以下工作:
- 安装Visual Studio,该IDE提供C#开发环境。选择安装.NET桌面开发工作负载,并安装所需的组件。
- 创建一个新的C#控制台应用程序项目。
- 添加一个引用System.Windows.Forms.dll,该DLL提供了Windows窗体应用程序程序集。可通过以下方法添加引用:右键单击项目->添加 引用->框架->选中System.Windows.Forms.dll->单击“确定”按钮。
实现过程
- 声明回调代理函数Delegate
首先,在命名空间顶部,先声明回调代理函数Delegate。
csharp
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
- 导入Windows API引用
为了访问Windows处理程序指针,需要导入以下Windows API引用:
```csharp
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
```
- 定义必要变量
C#实现鼠标钩子需要一些必要的变量,如HHOOK类型的变量、类型的枚举值以及系统级鼠标事件编码。这里定义以下两个变量:
csharp
private const int WH_MOUSE_LL = 14;
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
- 实现回调函数
实现回调函数HookCallback,该函数接收一个标准的鼠标消息结构体。
csharp
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
// 鼠标左键按下事件发生时
MessageBox.Show("Left button down");
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
- 实现启动/停止鼠标钩子函数
这个方法用于启动或停止鼠标钩子。当你想要捕获鼠标事件时,使用StartHook函数,反之使用StopHook函数。
```csharp
private static void StartHook()
{
_hookID = SetHook(_proc);
}
private static void StopHook()
{
UnhookWindowsHookEx(_hookID);
}
// 辅助方法
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
```
示例说明
接下来举两个示例说明如何使用C#实现鼠标钩子:
示例一
在此示例中,我们将捕获鼠标左键单击事件,并向用户显示消息框。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MouseHookDemo
{
class Program
{
private const int WH_MOUSE_LL = 14;
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
// 鼠标左键按下事件发生时
MessageBox.Show("Left button down");
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private static IntPtr GetModuleHandle(string lpModuleName)
{
IntPtr hModule = GetModuleHandleW(lpModuleName);
if (hModule == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return hModule;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandleW(string lpModuleName);
static void Main(string[] args)
{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
}
internal enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
}
示例二
在此示例中,我们将记录鼠标移动输入事件的坐标,并将其显示在控制台上。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace MouseHookDemo
{
class Program
{
private const int WH_MOUSE_LL = 14;
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
{
// 鼠标移动事件发生时
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine($"X:{hookStruct.pt.x}; Y:{hookStruct.pt.y}");
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private static IntPtr GetModuleHandle(string lpModuleName)
{
IntPtr hModule = GetModuleHandleW(lpModuleName);
if (hModule == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return hModule;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandleW(string lpModuleName);
static void Main(string[] args)
{
_hookID = SetHook(_proc);
Console.WriteLine("Mouse move input events are being monitored.");
Console.ReadLine();
UnhookWindowsHookEx(_hookID);
}
}
internal enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
internal struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
internal struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
}
以上为C#实现鼠标钩子的攻略以及2个示例说明。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#实现的鼠标钩子 - Python技术站