目录

C模拟鼠标点击,模拟鼠标双击,模拟鼠标恒定速度移动,可以看到轨迹

目录

C#模拟鼠标点击,模拟鼠标双击,模拟鼠标恒定速度移动,可以看到轨迹

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;

        [DllImport("User32.dll", EntryPoint = "GetDC")]
        private extern static IntPtr GetDC(IntPtr hWnd);


        [DllImport("gdi32.dll")]
        public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

        const int DESKTOPVERTRES = 117;
        const int DESKTOPHORZRES = 118;

        /// <summary>
        /// 获取屏幕的尺寸, 
        /// 屏幕宽度
        /// </summary>
        readonly static int width = GetDeviceCaps(GetDC(IntPtr.Zero), DESKTOPHORZRES);

        /// <summary>
        ///  屏幕高度
        /// </summary>
        readonly static int height = GetDeviceCaps(GetDC(IntPtr.Zero), DESKTOPVERTRES);


        /// <summary>
        /// 操作鼠标,模拟操作
        /// </summary>
        /// <param name="dwFlags"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="dwData"></param>
        /// <param name="dwExtraInfo"></param>
        /// <returns></returns>
        [System.Runtime.InteropServices.DllImport("user32")]
        public static extern int mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

        /// <summary>
        /// 鼠标瞬移到一个坐标;绝对坐标,有悬浮提示效果;
        /// </summary>
        /// <param name="point">到达的坐标点</param>
        public static void MouseMove(POINT point)
        {
            //移动鼠标到某个点,绝对坐标
            mouse_event(MOUSEEVENTF_absolute | MOUSEEVENTF_move,
                point.X * 65536 / width,
                point.Y * 65536 / height
                , 0, 0);
        }

        /// <summary>
        /// 移动鼠标
        /// </summary>
        public const int MOUSEEVENTF_move = 0x0001;

        //模拟鼠标左键按下 
        public const int MOUSEEVENTF_LEFTDOWN = 0x0002;

        //模拟鼠标左键抬起 
        public const int MOUSEEVENTF_LEFTUP = 0x0004;

        //模拟鼠标右键按下 
        public const int MOUSEEVENTF_RIGHTDOWN = 0x0008;

        //模拟鼠标右键抬起 
        public const int MOUSEEVENTF_rightup = 0x0010;

        //模拟鼠标中键按下 
        public const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;

        //模拟鼠标中键抬起 
        public const int MOUSEEVENTF_MIDDLEUP = 0x0040;

        //标示是否采用绝对坐标 
        public const int MOUSEEVENTF_absolute = 0x8000;

        //模拟鼠标滚轮滚动操作,必须配合dwData参数
        public const int MOUSEEVENTF_wheel = 0x0800;




        // 定义鼠标事件标志枚举
        [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; // in seconds

            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"></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 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);
        }

        /// <summary>
        /// (推荐)以恒定速度移动鼠标,可以看轨迹;鼠标悬浮可以看到提示;
        /// </summary>
        /// <param name="startX"></param>
        /// <param name="startY"></param>
        /// <param name="endX"></param>
        /// <param name="endY"></param>
        /// <param name="speedPixelsPerSecond"></param>
        /// <param name="cancellationToken"></param>
        public static void MoveMouseAtConstantSpeed3(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;

                MouseMove(new POINT() { X = currentX, Y = currentY });

                if (currentX == endX && currentY == endY
                    || (
                            Math.Abs(currentX - endX) <= speedPixelsPerSecond*1 
                            && Math.Abs(currentY - endY) <= speedPixelsPerSecond * 1
                        )
                    )
                {
                    break;
                }

                Task.Delay(5).Wait();
            }
            MouseMove(new POINT() { X = endX, Y = endY });
        }

    }
}