当前位置: 首页 > news >正文

C# 实现鼠标轨迹录制与回放自动化功能(附源码)

        在软件自动化测试或者重复性办公任务中,鼠标操作的自动化可以大大减少人工干预,提高工作效率。这里将详细介绍如何使用 C# 实现鼠标轨迹的录制与回放功能,代码结构清晰,具有较强的扩展性。

引用 NuGet 包

在开发这个功能时,我们需要用到第三方库来实现全局鼠标钩子监听,推荐使用以下 NuGet 包:

  • Gma.System.MouseKeyHook:用于监听全局鼠标事件,捕获鼠标移动和按键点击。
  • Newtonsoft.Json:用于将鼠标轨迹数据序列化成 JSON 格式进行保存和读取。

在 NuGet 包管理器中运行以下命令进行安装:

Install-Package Gma.System.MouseKeyHook
Install-Package Newtonsoft.Json

项目结构

整个项目的代码结构如下:

EsClearTextEdit
├─ MouseRecorder.cs      // 鼠标录制类
├─ MousePlayer.cs        // 鼠标回放类
└─ Form1.cs             // WinForms 主窗体

代码实现

1. 鼠标轨迹录制类

MouseRecorder.cs

作用

MouseRecorder 类负责监听鼠标事件,将鼠标的移动轨迹和点击动作记录下来,并按照时间间隔进行排序,最终保存成 JSON 文件。

代码解释
private List<MouseAction> actions = new List<MouseAction>();

这个列表用来存储鼠标的操作轨迹。

private IKeyboardMouseEvents _hook;

IKeyboardMouseEvents 是来自 Gma.System.MouseKeyHook 库的接口,提供全局事件监听。

public void StartRecording()
{
    _hook = Hook.GlobalEvents();
    _hook.MouseDownExt += MouseDown;
    _hook.MouseMove += MouseMove;
    lastTime = DateTime.Now;
}
  • Hook.GlobalEvents():注册全局鼠标监听。
  • MouseMove 事件监听鼠标移动。
  • MouseDownExt 事件监听鼠标点击。
  • lastTime 用来计算鼠标操作之间的时间间隔。
private void MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
    actions.Add(new MouseAction { X = e.X, Y = e.Y, Action = "Move", Time = (int)(DateTime.Now - lastTime).TotalMilliseconds });
    lastTime = DateTime.Now;
}

这个方法记录鼠标移动的位置坐标 (X, Y) 以及动作名称 Move,并计算当前动作与上一个动作之间的时间间隔。

private void MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
    actions.Add(new MouseAction { X = e.X, Y = e.Y, Action = e.Button.ToString(), Time = (int)(DateTime.Now - lastTime).TotalMilliseconds });
    lastTime = DateTime.Now;
}

这个方法记录鼠标点击的位置坐标 (X, Y) 和按键类型(LeftRight)。

public void Save(string fileName)
{
    File.WriteAllText(fileName, Newtonsoft.Json.JsonConvert.SerializeObject(actions));
}

使用 Newtonsoft.Json 将录制的轨迹序列化成 JSON 文件,方便保存和读取。

public void StopRecording()
{
    _hook.MouseMove -= MouseMove;
    _hook.MouseDownExt -= MouseDown;
    _hook.Dispose();
}

停止监听并释放资源。


2. 鼠标轨迹回放类

MousePlayer.cs

作用

MousePlayer 类负责读取保存的轨迹数据,并按照记录的轨迹模拟鼠标操作。

代码解释
[DllImport("user32.dll")]
private static extern void SetCursorPos(int X, int Y);

通过 Windows API 设置鼠标光标的位置。

[DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, IntPtr dwExtraInfo);

Windows API 发送鼠标事件。

public void Play(List<MouseAction> actions)
{
    foreach (var action in actions)
    {
        Thread.Sleep(action.Time);
        SetCursorPos(action.X, action.Y);
        if (action.Action == "Left")
        {
            mouse_event(MOUSEEVENTF_LEFTDOWN, action.X, action.Y, 0, IntPtr.Zero);
            mouse_event(MOUSEEVENTF_LEFTUP, action.X, action.Y, 0, IntPtr.Zero);
        }
    }
}

遍历录制的轨迹数据,按时间间隔模拟鼠标移动和左键点击。


3. 主窗体类

Form1.cs

代码解释
MouseRecorder recorder = new MouseRecorder();
MousePlayer player = new MousePlayer();

实例化录制类和回放类。

private void uiButton1_Click(object sender, EventArgs e)
{
    recorder.StartRecording();
    MessageBox.Show("录制开始!");
}

点击 开始录制 按钮启动鼠标轨迹录制。

private void uiButton2_Click(object sender, EventArgs e)
{
    recorder.StopRecording();
    recorder.Save("track.json");
    MessageBox.Show("保存成功!");
}

停止录制并保存轨迹。

private void uiButton3_Click(object sender, EventArgs e)
{
    var data = File.ReadAllText("track.json");
    var actions = Newtonsoft.Json.JsonConvert.DeserializeObject<List<MouseAction>>(data);
    player.Play(actions);
}

读取 JSON 文件并回放轨迹。

  private void uiButton3_Click(object sender, EventArgs e)
        {
            var data = File.ReadAllText("track.json");
            var actions = Newtonsoft.Json.JsonConvert.DeserializeObject<List<MouseAction>>(data);
            player.Play(actions);
        }

源代码:

        MousePlayer类

        

public class MousePlayer
    {
        [DllImport("user32.dll")]
        private static extern void SetCursorPos(int X, int Y);

        [DllImport("user32.dll")]
        private static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, IntPtr dwExtraInfo);

        private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
        private const uint MOUSEEVENTF_LEFTUP = 0x04;

        public void Play(List<MouseAction> actions)
        {
            foreach (var action in actions)
            {
                Thread.Sleep(action.Time);

                SetCursorPos(action.X, action.Y);

                if (action.Action == "Left")
                {
                    mouse_event(MOUSEEVENTF_LEFTDOWN, action.X, action.Y, 0, IntPtr.Zero);
                    mouse_event(MOUSEEVENTF_LEFTUP, action.X, action.Y, 0, IntPtr.Zero);
                }
            }
        }
    }

        MouseRecorder类

        

 public class MouseRecorder
    {
        private List<MouseAction> actions = new List<MouseAction>();
        private IKeyboardMouseEvents _hook;
        private DateTime lastTime;

        public void StartRecording()
        {
            _hook = Hook.GlobalEvents();
            _hook.MouseDownExt += MouseDown;
            _hook.MouseMove += MouseMove;
            lastTime = DateTime.Now;
        }

        private void MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            actions.Add(new MouseAction { X = e.X, Y = e.Y, Action = "Move", Time = (int)(DateTime.Now - lastTime).TotalMilliseconds });
            lastTime = DateTime.Now;
        }

        private void MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            actions.Add(new MouseAction { X = e.X, Y = e.Y, Action = e.Button.ToString(), Time = (int)(DateTime.Now - lastTime).TotalMilliseconds });
            lastTime = DateTime.Now;
        }

        public void Save(string fileName)
        {
            File.WriteAllText(fileName, Newtonsoft.Json.JsonConvert.SerializeObject(actions));
        }

        public void StopRecording()
        {
            _hook.MouseMove -= MouseMove;
            _hook.MouseDownExt -= MouseDown;
            _hook.Dispose();
        }
    }

    public class MouseAction
    {
        public int X { get; set; }
        public int Y { get; set; }
        public string Action { get; set; }
        public int Time { get; set; }
    }

        主窗体代码:

         

public partial class Form1 : Form
    {
        MouseRecorder recorder = new MouseRecorder();
        MousePlayer player = new MousePlayer();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
        }

        /// <summary>
        /// 开始录制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uiButton1_Click(object sender, EventArgs e)
        {
            recorder.StartRecording();
        }

        /// <summary>
        /// 停止/保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void uiButton2_Click(object sender, EventArgs e)
        {
            recorder.StopRecording();
            recorder.Save("track.json");
            MessageBox.Show("保存成功!");
        }

        /// <summary>
        /// 读取文件,并且进行自动操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uiButton3_Click(object sender, EventArgs e)
        {
            var data = File.ReadAllText("track.json");
            var actions = Newtonsoft.Json.JsonConvert.DeserializeObject<List<MouseAction>>(data);
            player.Play(actions);
        }
    }

使用场景

我们可以在以下场景中使用

  1. 软件自动化测试:代替人工点击执行测试任务。
  2. 办公自动化:批量执行重复性任务。
  3. 游戏挂机脚本:重复执行游戏操作。

本代码只实现了基础功能,后续可以通过以下几个方面进行扩展优化

  • 支持右键点击
  • 鼠标滚轮操作
  • 录制暂停与恢复
  • 自定义播放速度

通过本文的介绍,相信大家已经掌握了鼠标轨迹录制与回放功能的实现方式。该功能在自动化测试和重复性工作中具有重要应用价值。后续可以进一步优化,增加更多扩展功能,形成一个完整的自动化工具。

相关文章:

  • linux修改不可用编辑的文件(修改权限失败)
  • linux指令学习--sudo apt-get install vim
  • 【单片机项目】电源如何扩展、电源模块、电池模块如何接线
  • Codepen和tailwindcss 进行UI布局展示
  • 静态成员不依赖于特定对象的内容
  • 使用LVGL驱动三色墨水屏,Arduino
  • Android进程间通信方式之AIDL
  • Oracle SQL优化实战要点解析(11)
  • fetch为什么加了允许跨域请求mode: ‘no-cors‘,添加的多个header就丢失了?
  • Android Broadcast广播封装
  • 博客系统自动化测试_测试报告
  • OceanBase-obcp-v3考试资料梳理
  • LLMs之Agent:Manus(一款通用人工智能代理)的简介、安装和使用方法、案例应用之详细攻略
  • Redis—01—分布式系统
  • 使用 Docker 部署 RabbitMQ 并实现数据持久化
  • Kubernetes 的正式安装
  • 【数分】Numpy入门及进阶(四)
  • 数据集路径出错.yaml‘ images not found , missing path
  • 【Java线程基础操作详解】
  • SpringBoot3—场景整合:AOT
  • 新时代,新方志:2025上海地方志论坛暨理论研讨会举办
  • 视频丨歼-10CE首次实战大放异彩
  • 阳光保险拟设立私募证券投资基金,总规模200亿元
  • 张家界一铁路致17人身亡,又有15岁女孩殒命,已开始加装护栏
  • 上交所五方面落实募资新规:强化关键少数责任和股东权利保障
  • 特朗普访问卡塔尔,两国签署多项合作协议