C#实现的鼠标钩子

C#实现鼠标钩子可以用来监视和控制鼠标事件,比如截取特定的鼠标事件、拦截在系统中发生的鼠标消息等。这里提供完整攻略,具体过程如下:

准备工作

在开始实现之前,需要准备以下工作:

  1. 安装Visual Studio,该IDE提供C#开发环境。选择安装.NET桌面开发工作负载,并安装所需的组件。
  2. 创建一个新的C#控制台应用程序项目。
  3. 添加一个引用System.Windows.Forms.dll,该DLL提供了Windows窗体应用程序程序集。可通过以下方法添加引用:右键单击项目->添加 引用->框架->选中System.Windows.Forms.dll->单击“确定”按钮。

实现过程

  1. 声明回调代理函数Delegate

首先,在命名空间顶部,先声明回调代理函数Delegate。
csharp
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

  1. 导入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);
```

  1. 定义必要变量

C#实现鼠标钩子需要一些必要的变量,如HHOOK类型的变量、类型的枚举值以及系统级鼠标事件编码。这里定义以下两个变量:
csharp
private const int WH_MOUSE_LL = 14;
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;

  1. 实现回调函数

实现回调函数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);
}

  1. 实现启动/停止鼠标钩子函数

这个方法用于启动或停止鼠标钩子。当你想要捕获鼠标事件时,使用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技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • C# 开发step步骤条控件详解

    下面是关于C#开发步骤条控件的详细攻略。 1. 概述 步骤条控件可以帮助用户更加清晰地了解当前操作处于哪一步,以及距离完成还有多少步。在C#开发中,我们可以使用自定义控件来实现步骤条的功能。 本篇攻略将会介绍如何使用C#开发步骤条控件,包括控件设计、属性设置、事件处理等。 2. 控件设计 2.1 创建新控件 在Visual Studio中,我们可以通过以下步…

    C# 2023年6月3日
    00
  • C#处理Access中事务的方法

    下面是详细的”C#处理Access中事务的方法”攻略: 一、事务概述 如果在数据库事务中的一个或多个命令失败了,那么整个事务都应该被撤回。为此,可以使用事务将数据的修改为原子性操作。 Access数据库的事务原理和所有关系型数据库一样,都是基于ACID的: 原子性(Atomicity):要么全部成功,要么全部失败,没有中间状态,回滚(Rollback)整个事…

    C# 2023年5月31日
    00
  • C#集合本质之链表的用法详解

    C#集合本质之链表的用法详解 什么是链表 链表是一种常见的数据结构,它由一些节点组成,每个节点存储着数据和指向下一个节点的地址。链表的优点在于可以动态添加、删除节点,数据的操作效率较高。 在C#中,链表是一种集合类,实现了ICollection和IEnumerable接口,提供了许多常见的操作方法。 链表的构造 在使用链表之前,需要使用LinkedList&…

    C# 2023年5月31日
    00
  • C#注释的一些使用方法浅谈

    C#注释的一些使用方法浅谈 简介 注释是一种解释源代码的方法,在C#中,注释可以分为两种类型:单行注释和多行注释。 单行注释 在代码行的后面以双斜杠 // 开头,这一行的内容就被视作注释,注释可以在同一行代码的下方,说明这一行代码的作用。 示例: int a = 1; // 定义变量a,赋值为1 多行注释 多行注释又称块注释,可以用用 /* 和 */ 包围一…

    C# 2023年5月15日
    00
  • C# Console.WriteLine()方法: 将指定字符串和行结束符写入标准输出流

    作用: Console.WriteLine()是C#中标准输出的方法,用于将指定的数据写入控制台。它可以输出各种类型的值,如字符串、数字、布尔值以及其他对象等等。 使用方法: 方法语法如下: Console.WriteLine(); Console.WriteLine(string value); Console.WriteLine(string forma…

    C# 2023年4月19日
    00
  • C#中foreach实现原理详解

    C#中foreach实现原理详解 在C#语言中,foreach可以用于遍历数组、集合和自定义类型等可迭代对象。本文将详细介绍foreach的实现原理,让读者更深入地了解该语法的运行机制。 foreach语法 foreach语法的基本形式如下: foreach (var variable in expression) { // code block } 其中,…

    C# 2023年6月7日
    00
  • C# cefSharep控件的使用详情

    C# cefSharp 控件的使用详情 什么是 cefSharp 控件 cefSharp 控件是一种基于 C# 的浏览器嵌入控件,它是一个基于 Chromium 的项目,可以通过 cefSharp 控件在 Windows 窗体应用程序中嵌入 HTML 内容和 JavaScript 脚本,并为这些内容提供浏览器的一般功能。 安装 cefSharp 控件 使用 …

    C# 2023年6月1日
    00
  • C#创建缩略图操作类实例

    下面我将详细讲解“C# 创建缩略图操作类实例”的完整攻略。 1. 前提准备 在使用 C# 创建缩略图操作类实例之前,需要先掌握以下知识和准备工作。- 需要安装 .NET Framework 环境;- 需要掌握基础的 C# 编程知识;- 需要了解 System.Drawing 命名空间。 2. 创建缩略图操作类 以下是创建缩略图操作类的代码示例: using …

    C# 2023年6月7日
    00
合作推广
合作推广
分享本页
返回顶部