C#模擬鼠標點擊,模擬鼠標雙擊,模擬鼠標恒定速度移動,可以看到軌跡
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;namespace WpfAppYolo11_test1.Tool
{/// <summary>/// 模擬鼠標點擊/// </summary>public class MyMouseClick{/// <summary>/// 當鼠標移動時觸發/// </summary>public static event EventHandler OnMoveMouse;// 定義鼠標事件標志枚舉[Flags]public enum MouseEventFlags : uint{Move = 0x0001,LeftDown = 0x0002,LeftUp = 0x0004,RightDown = 0x0008,RightUp = 0x0010,MiddleDown = 0x0020,MiddleUp = 0x0040,XDown = 0x0080,XUp = 0x0100,Wheel = 0x0800,VirtualDesk = 0x4000,Absolute = 0x8000}/// <summary>/// 移動鼠標到一個坐標/// </summary>/// <param name="X"></param>/// <param name="Y"></param>/// <returns></returns> [DllImport("user32.dll")]public static extern bool SetCursorPos(int X, int Y);// 導入user32.dll中的mouse_event函數[DllImport("user32.dll")]public static extern void mouse_event(MouseEventFlags flags, int dx, int dy, uint data, UIntPtr extraInfo);/// <summary>/// 當前鼠標位置/// </summary>/// <param name="lpPoint"></param>/// <returns></returns> [DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]public static extern bool GetCursorPos(out POINT lpPoint);/// <summary>/// 導入模擬鍵盤的方法/// </summary>/// <param name="bVk" >按鍵的虛擬鍵值</param>/// <param name= "bScan" >掃描碼,一般不用設置,用0代替就行</param>/// <param name= "dwFlags" >選項標志:0:表示按下,2:表示松開</param>/// <param name= "dwExtraInfo">一般設置為0</param>[DllImport("user32.dll")]public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);// 定義POINT結構體[StructLayout(LayoutKind.Sequential)]public struct POINT{public int X;public int Y;}/// <summary>/// 點擊鼠標左鍵/// </summary>/// <param name="x">坐標x</param>/// <param name="y">坐標y</param>public static void MouseLeftClick(int x, int y){//移動鼠標到一個坐標SetCursorPos(x, y);mouse_event(MouseEventFlags.LeftDown, 0, 0, 0, UIntPtr.Zero);mouse_event(MouseEventFlags.LeftUp, 0, 0, 0, UIntPtr.Zero);}/// <summary>/// 點擊鼠標左鍵/// </summary>/// <param name="point"></param>public static void MouseLeftClick(POINT point){//移動鼠標到一個坐標SetCursorPos(point.X, point.Y);mouse_event(MouseEventFlags.LeftDown, 0, 0, 0, UIntPtr.Zero);mouse_event(MouseEventFlags.LeftUp, 0, 0, 0, UIntPtr.Zero);}/// <summary>/// 雙擊鼠標左鍵/// </summary>/// <param name="x"></param>/// <param name="y"></param>public static void MouseDoubleLeftClick(int x, int y){MouseLeftClick(x, y);MouseLeftClick(x, y);}/// <summary>/// 雙擊鼠標左鍵/// </summary>/// <param name="x"></param>/// <param name="y"></param>public static void MouseDoubleLeftClick(POINT pOINT){MouseLeftClick(pOINT.X, pOINT.Y);MouseLeftClick(pOINT.X, pOINT.Y);}/// <summary>/// 移動鼠標從一個點到另一個點,有移動軌跡/// </summary>/// <param name="startPoint">開始坐標</param>/// <param name="endPoint">停止坐標</param> /// <param name="delay">每步歇息耗時毫秒</param>public static void MoveMouseSmoothly(POINT startPoint, POINT endPoint, int delay = 5){int currentX = startPoint.X;int currentY = startPoint.Y;int step = 40;int deltaX = (endPoint.X - startPoint.X) / step;int deltaY = (endPoint.Y - startPoint.Y) / step;OnMoveMouse?.Invoke(new POINT() { X = deltaX, Y = deltaY }, new EventArgs());int index = 0;Task.Run(() =>{try{while (index <= step){OnMoveMouse?.Invoke(new POINT() { X = currentX, Y = currentY }, new EventArgs());SetCursorPos(currentX, currentY);currentX += deltaX;currentY += deltaY;index++;Thread.Sleep(delay);}SetCursorPos(endPoint.X, endPoint.Y);}catch (Exception){}});}/// <summary>/// 計算兩點之間的距離/// </summary>/// <param name="x1"></param>/// <param name="y1"></param>/// <param name="x2"></param>/// <param name="y2"></param>/// <returns></returns>public static double CalculateDistance(int x1, int y1, int x2, int y2){var num1 = Math.Abs(x2 - x1);var num2 = Math.Abs(y2 - y1);return Math.Sqrt(Math.Pow(num1, 2) + Math.Pow(num2, 2));}/// <summary>/// 以恒定速度移動鼠標,可以看軌跡/// </summary>/// <param name="startX"></param>/// <param name="startY"></param>/// <param name="endX"></param>/// <param name="endY"></param>/// <param name="speedPixelsPerSecond">移動速度,多少像素/5毫秒</param>/// <param name="cancellationToken"></param>/// <returns></returns>public static void MoveMouseAtConstantSpeedAsync(int startX, int startY, int endX, int endY, double speedPixelsPerSecond = 10, CancellationToken cancellationToken = default){double distance = CalculateDistance(startX, startY, endX, endY);//移動總步數,毫秒double steps = distance / speedPixelsPerSecond; int currentX = startX;int currentY = startY;//每步移動的像素double x_move = (endX - startX) / steps;double y_move = (endY - startY) / steps;for (int i = 0; i < steps; i++){//if (cancellationToken.IsCancellationRequested)//{// Console.WriteLine("Mouse movement cancelled.");// return;//}currentX += (int)x_move;currentY += (int)y_move;SetCursorPos(currentX, currentY);Task.Delay(5).Wait();}//SetCursorPos(endX, endY);}/// <summary>/// (推薦)以恒定速度移動鼠標,可以看軌跡/// </summary>/// <param name="startX">開始坐標x</param>/// <param name="startY">開始坐標y</param>/// <param name="endX">終點坐標x</param>/// <param name="endY">終點坐標y</param>/// <param name="speedPixelsPerSecond">移動速度,多少像素/5毫秒</param>/// <param name="cancellationToken"></param>/// <returns></returns>public static void MoveMouseAtConstantSpeedAsync2(int startX, int startY, int endX, int endY, double speedPixelsPerSecond = 20, CancellationToken cancellationToken = default){int currentX = startX;int currentY = startY;while (true){ //當前鼠標位置POINT startPoint;GetCursorPos(out startPoint);double distance = CalculateDistance(startPoint.X, startPoint.Y, endX, endY);//移動總步數,毫秒double steps = distance / speedPixelsPerSecond; 移動總共多少步//double stepsX = Math.Abs(endX - startPoint.X) / speedPixelsPerSecond;//double stepsY = Math.Abs(endY - startPoint.Y) / speedPixelsPerSecond;//每步移動像素double xMove= (endX - startPoint.X)/ steps;double yMove= (endY - startPoint.Y) / steps;currentX += (int)xMove;currentY += (int)yMove;SetCursorPos(currentX, currentY);if (currentX == endX && currentY == endY|| (Math.Abs(currentX - endX) <= 8 && Math.Abs(currentY - endY) <= 8)){break;}Task.Delay(5).Wait();}SetCursorPos(endX, endY);}}
}