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# 中的可空值类型 null

    浅谈C# 中的可空值类型 null 在C#中,null代表一个空引用或不存在的对象。当我们调用一个没有赋值的对象时,就会出现空引用异常。为了避免这种情况,C#提供了可空值类型。 可空值类型 可空值类型是一种用于表示一个值类型可能为null的数据类型。比如它可以声明一个int类型的变量,并赋值为null。在可空值类型中,可以赋值为null的值类型例如 int、…

    C# 2023年6月1日
    00
  • c# 如何实现自动更新程序

    针对C#如何实现自动更新程序,一般有两种实现方式,分别是: 1.使用ClickOnce部署 ClickOnce是微软公司提供的一种快速、简单的部署技术,可以帮助开发人员轻松地完成应用程序的自动更新。其主要优点是使用简便、稳定性高、和Windows操作系统深度耦合。 其中实现步骤如下: 首先,我们需要在Visual Studio中针对该应用程序进行发布设置,定…

    C# 2023年5月15日
    00
  • C#中的枚举类型(Enum)介绍

    当我们需要定义一些具有固定值的常量时,使用枚举类型(Enum)可以更方便地进行管理和调用。在C#中,枚举类型是一种值类型,可以使用关键字enum进行定义。下面我将详细介绍C#中的枚举类型。 枚举类型的基本定义 在C#中,枚举类型可以使用以下语法进行定义: enum 枚举名 { 标识符1 = 值1, 标识符2 = 值2, … } 枚举名为定义枚举项的集合名…

    C# 2023年6月7日
    00
  • asp.net SharpZipLib的压缩与解压问题

    下面我将详细介绍关于“asp.net SharpZipLib的压缩与解压问题”的完整攻略。 什么是 SharpZipLib SharpZipLib 是 .NET 平台下使用的一个流行的压缩库,支持 Gzip、Deflate、BZip2 等多种压缩格式,并且它是在 zlib 许可证下发布的,因此免费且开源。 SharpZipLib 安装 在 Visual St…

    C# 2023年6月6日
    00
  • C#常见应用函数实例小结

    关于“C#常见应用函数实例小结”的完整攻略,可以按照以下步骤进行: 1. 确定需求 首先需要明确要实现的功能。比如,我们可以假设需要实现以下需求: 根据用户输入的字符串,判断其是否为数字; 给定一个句子,在其中查找某个子字符串,并将其替换为另一个字符串。 2. 查找相关函数 在确定了需求之后,需要查找相关的函数来实现。可以通过查阅C#官方文档、搜索引擎等方式…

    C# 2023年5月31日
    00
  • C#流程控制详解

    C#流程控制详解 前言 C#中的流程控制结构对于程序设计师是非常重要的,它可以控制代码的执行次序和执行条件,使得程序可以更好的实现我们所期望的功能。本文将讲解C#中常见的流程控制结构,包括分支语句和循环语句,并对每种结构进行详细解释和举例。 分支语句 if语句 if语句是一种最基本的分支语句,用于判断某个条件是否成立,如果条件成立执行一定的代码块,如果条件不…

    C# 2023年5月14日
    00
  • C#中对字符串进行压缩和解压的实现

    如果您需要进行大量字符串的传输或存储,可能会考虑使用压缩算法来缩小数据量,减少传输或存储成本。在C#中,可以使用System.IO.Compression命名空间提供的DeflateStream和GZipStream类来对字符串进行压缩和解压操作。 压缩字符串: 以下是基于GZipStream类实现字符串压缩的代码示例: public static byte…

    C# 2023年6月6日
    00
  • C#单例模式与多线程用法介绍

    C#单例模式与多线程用法介绍 单例模式是C#编程中最常用的面向对象设计模式之一,在多线程环境下实现单例模式要注意线程安全问题。本文将从以下几个方面进行介绍: 单例模式的概念及说明 单例模式的实现方式 多线程环境下的单例模式实现 示例代码介绍 单例模式概述 单例模式是指一个类只能被实例化一次,通过提供全局唯一的访问点,来确保该类的对象只有一个。单例模式在多线程…

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