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. 游戲掛機腳本:重復執行游戲操作。

本代碼只實現了基礎功能,后續可以通過以下幾個方面進行擴展優化

  • 支持右鍵點擊
  • 鼠標滾輪操作
  • 錄制暫停與恢復
  • 自定義播放速度

通過本文的介紹,相信大家已經掌握了鼠標軌跡錄制與回放功能的實現方式。該功能在自動化測試和重復性工作中具有重要應用價值。后續可以進一步優化,增加更多擴展功能,形成一個完整的自動化工具。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71533.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71533.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71533.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Nacos 核心功能實戰筆記(超詳細)

Nacos 核心功能實戰筆記 一、Nacos 簡介 1. 是什么&#xff1f; 全稱&#xff1a;Nacos Naming and Configuration Service定位&#xff1a;阿里巴巴開源的 動態服務發現、配置管理、服務管理平臺核心功能&#xff1a;服務注冊與發現 統一配置管理 服務健康監測適用場景&…

安裝remixd,在VScode創建hardhat

在終端&#xff0c;以管理員身份&#xff0c;cmd 需要科學上網 npm install -g remix-project/remixd 在vscode插件中&#xff0c;安裝solidity插件&#xff0c;是暗灰色那款 1.將nodeJs的版本升級至18以上 2.在vscode打開一個新的文件&#xff0c;在終端輸入 npx hardhat 3.…

unity pico開發 四 物體交互 抓取 交互層級

文章目錄 手部設置物體交互物體抓取添加抓取抓取三種類型抓取點偏移抓取事件抓取時不讓物體吸附到手部 射線抓取交互層級 手部設置 為手部&#xff08;LeftHandController&#xff09;添加XRDirInteractor腳本 并添加一個球形碰撞盒&#xff0c;勾選isTrigger,調整大小為0.1 …

CyberRT(apollo) 定時器模塊簡述及bug分析

timer 模塊 timer的定義&#xff0c;cyberrt中timer模塊用于設置定時器任務&#xff0c;字面意思&#xff0c;設置設置定時周期及出發頻次&#xff08;周期 or oneshot)&#xff0c;到達指定時間時間觸發callback time wheel 時鐘節拍輪&#xff0c;常見的定時器設計&#x…

java八股文之消息中間件

1.RabbitMQ如何保證消息不丟失 開啟生產者確認機制&#xff0c;確保生產者的消息能到達隊列開啟持久化功能&#xff0c;確保消息未消費前在隊列中不會丟失&#xff08;交換機&#xff0c;隊列&#xff0c;消息都需要開啟持久化功能&#xff09;開啟消費者確認機制為auto,由spr…

Win7重裝不翻車!ISO鏡像安全下載渠道+BIOS設置避雷手冊

一、寫在前面&#xff1a;為什么你需要這份教程&#xff1f; 當電腦頻繁藍屏、系統崩潰甚至無法開機時&#xff0c;重裝系統可能是最后的救命稻草。但市面上的教程往往存在三大痛點&#xff1a; ?? 鏡像來源不明導致系統被植入后門 ?? 啟動盤制作失敗反復折騰 ?? 操作失…

大學至今的反思與總結

現在是2025年的3月5日&#xff0c;我大三下學期。 自大學伊始&#xff0c;我便以考研作為自己的目標&#xff0c;有時還會做自己考研上岸頭部985,211&#xff0c;offer如潮水般涌來的美夢。 但是我卻忽略了一點&#xff0c;即便我早早下定了決心去考研&#xff0c;但并沒有早…

SpringBoot 全局異常處理

文章目錄 異常處理全局異常處理(推薦)局部異常處理高級技巧設置返回狀態碼處理404異常異常處理 全局異常處理(推薦) 創建一個全局異常處理類,使用 @RestControllerAdvice 注解標記。 在方法上使用 @ExceptionHandler 聲明當前方法可處理的異常類型。當系統發生異常時,…

【四.RAG技術與應用】【11.阿里云百煉應用(上):RAG在云端的實踐】

一、為什么需要RAG?大模型的“知識困境”與破局之道 大模型雖然“博學”,但它的知識庫存在兩個致命短板: 缺乏私有知識:比如企業內部的產品手冊、客戶數據、行業報告等;知識更新滯后:大模型的訓練數據往往停留在某個時間點,無法實時獲取最新信息(比如今天的股票行情或…

使用wifi連接手機adb進行調試|不使用數據線adb調試手機|找應用錯誤日志和操作日志

手機在開發者選項里要開啟無線調試 在手機設置中查看WiFi的IP地址 設置 -> WLAN -> 已連接的WiFi -> IP地址 使用手機的IP地址連接 adb connect 192.168.1.12:xxxxx 檢查連接狀態 adb devices 斷開特定設備 adb disconnect 192.168.x.x:xxxxx 斷開所有設備 …

mapbox高階,結合threejs(threebox)添加三維球體

????? 主頁: gis分享者 ????? 感謝各位大佬 點贊?? 收藏? 留言?? 加關注?! ????? 收錄于專欄:mapbox 從入門到精通 文章目錄 一、??前言1.1 ??mapboxgl.Map 地圖對象1.2 ??mapboxgl.Map style屬性1.3 ??threebox Sphere靜態對象二、??使用t…

游戲引擎學習第140天

回顧并為今天的內容做準備 目前代碼的進展到了聲音混音的部分。昨天我詳細解釋了聲音的處理方式&#xff0c;聲音在技術上是一個非常特別的存在&#xff0c;但在游戲中進行聲音混音的需求其實相對簡單明了&#xff0c;所以今天的任務應該不會太具挑戰性。 今天我們會編寫一個…

golang并發編程如何學習

《掌握 Golang 并發編程的通關秘籍》 在當今的編程世界中&#xff0c;Golang 并發編程正以其獨特的魅力和強大的能力吸引著眾多開發者。然而&#xff0c;對于許多小伙伴來說&#xff0c;如何學好這門技術卻成了一個頭疼的問題。別擔心&#xff0c;今天就讓我來為大家揭開 Gola…

SpringMVC學習(controller層加載控制與(業務、功能)bean加載控制、Web容器初始化配置類)(3)

目錄 一、SpringMVC、Spring的bean加載控制。 &#xff08;1&#xff09;實際開發的包結構層次。 &#xff08;2&#xff09;如何"精準"控制兩個容器分別加載各自bean。(分析) <1>SpringMVC相關bean加載控制。(方法) <2>Spring相關bean加載控制。(方法) …

fastapi+mysql實現增刪改查

說明&#xff1a; 我計劃用python的fastapi框架&#xff0c;實現操作MySQL數據庫的表&#xff0c;實現增刪改查的操作&#xff0c;并且在postman里面測試 step1: 安裝數據庫依賴 pip install fastapi uvicorn pymysqlstep2:C:\Users\Administrator\PycharmProjects\FastAPIPro…

Linux系統之配置HAProxy負載均衡服務器

Linux系統之配置HAProxy負載均衡服務器 前言一、HAProxy介紹1.1 HAProxy簡介1.2 主要特點1.3 使用場景二、本次實踐介紹2.1 本次實踐簡介2.2 本次實踐環境規劃三、部署兩臺web服務器3.1 運行兩個Docker容器3.2 編輯測試文件3.3 訪問測試四、安裝HAProxy4.1 更新系統軟件源4.2 安…

CS144 Lab Checkpoint 2: the TCP receiver

Overview TCPReceiver 從對等的sender接收消息&#xff0c;使用 receive() 方法&#xff0c;然后調用 Reassembler() 方法&#xff0c;后者寫入 ByteStream 中 然后應用程序從 ByteSteam 中讀取。 同時&#xff0c;TCPReceiver 還會通過 send() 方法給sender發送消息&#xff…

Spring Boot 3.x 核心注解詳解與最佳實踐

Spring Boot 3.x 核心注解詳解與最佳實踐 前言 隨著Spring Boot 3.x的正式發布&#xff0c;這個基于Spring Framework 6的里程碑版本帶來了諸多新特性。本文將深入剖析Spring Boot 3.x的核心注解體系&#xff0c;結合代碼示例講解其作用及使用場景&#xff0c;助您快速掌握新…

PHP之常量

在你有別的編程語言的基礎下&#xff0c;你想學習PHP&#xff0c;可能要了解的一些關于常量的信息。 PHP中的常量不用指定數據類型&#xff0c;可以使用兩次方法定義。 使用const //定義常量 const B 2; echo B . PHP_EOL;使用define define("A", 1); echo A . P…

計算機網絡——子網掩碼

一、子網掩碼是什么&#xff1f;它長什么樣&#xff1f; 子網掩碼的定義 子網掩碼是一個32位的二進制數字&#xff0c;與IP地址“配對使用”&#xff0c;用于標識IP地址中哪部分屬于網絡地址&#xff0c;哪部分屬于主機地址。 示例&#xff1a;IP地址 192.168.1.10&#xff0c;…