C#逼真地移动鼠标

fla*_*404 9 c# mouse

我正在演示一个软件,并希望构建一个鼠标"移动器"功能,这样我基本上可以自动化该过程.我想创建逼真的鼠标移动,但在思考过程中有一点心理障碍.我可以使用c#轻松移动鼠标,但希望它比仅出现在某个x,y,坐标然后按下按钮的光标更逼真.

我得到鼠标的当前位置,然后得到终点.计算两点之间的弧线,但是我需要计算沿该弧线的点,以便我可以在其中添加一个计时器事件,以便我可以从一个点移动到下一个点,然后重复这一点直到我到达目标...

有人想详细说明吗?

谢谢,R.

Eri*_*bes 22

我尝试了弧计算方法,结果证明是复杂的,最后看起来并不现实.JP在他的评论中表示,直线看起来更加人性化.

这是我编写的用于计算线性鼠标移动的函数.应该是不言自明的.GetCursorPosition()和SetCursorPosition(Point)是win32函数GetCursorPos和SetCursorPos的包装器.

就数学而言 - 从技术上讲,这称为线段的线性插值.

public void LinearSmoothMove(Point newPosition, int steps) {
    Point start = GetCursorPosition();
    PointF iterPoint = start;

    // Find the slope of the line segment defined by start and newPosition
    PointF slope = new PointF(newPosition.X - start.X, newPosition.Y - start.Y);

    // Divide by the number of steps
    slope.X = slope.X / steps;
    slope.Y = slope.Y / steps;

    // Move the mouse to each iterative point.
    for (int i = 0; i < steps; i++)
    {
        iterPoint = new PointF(iterPoint.X + slope.X, iterPoint.Y + slope.Y);
        SetCursorPosition(Point.Round(iterPoint));
        Thread.Sleep(MouseEventDelayMS);
    }

    // Move the mouse to the final destination.
    SetCursorPosition(newPosition);
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道有人会对数学很聪明!:) (3认同)

Cod*_*095 9

我将WindMouse前面提到的函数转换为C#,实际上非常逼真.请注意,这只是一个粗略的示例,并没有使用包装器GetCursorPosSetCursorPos.我将使用Windows输入模拟器包装器.

static class SampleMouseMove {

    static Random random = new Random();
    static int mouseSpeed = 15;

    static void Main(string[] args) {
        MoveMouse(0, 0, 0, 0);
    }

    static void MoveMouse(int x, int y, int rx, int ry) {
        Point c = new Point();
        GetCursorPos(out c);

        x += random.Next(rx);
        y += random.Next(ry);

        double randomSpeed = Math.Max((random.Next(mouseSpeed) / 2.0 + mouseSpeed) / 10.0, 0.1);

        WindMouse(c.X, c.Y, x, y, 9.0, 3.0, 10.0 / randomSpeed,
            15.0 / randomSpeed, 10.0 * randomSpeed, 10.0 * randomSpeed); 
    }

    static void WindMouse(double xs, double ys, double xe, double ye,
        double gravity, double wind, double minWait, double maxWait,
        double maxStep, double targetArea) {

        double dist, windX = 0, windY = 0, veloX = 0, veloY = 0, randomDist, veloMag, step;
        int oldX, oldY, newX = (int)Math.Round(xs), newY = (int)Math.Round(ys);

        double waitDiff = maxWait - minWait;
        double sqrt2 = Math.Sqrt(2.0);
        double sqrt3 = Math.Sqrt(3.0);
        double sqrt5 = Math.Sqrt(5.0);

        dist = Hypot(xe - xs, ye - ys);

        while (dist > 1.0) {

            wind = Math.Min(wind, dist);

            if (dist >= targetArea) {
                int w = random.Next((int)Math.Round(wind) * 2 + 1);
                windX = windX / sqrt3 + (w - wind) / sqrt5;
                windY = windY / sqrt3 + (w - wind) / sqrt5;
            }
            else {
                windX = windX / sqrt2;
                windY = windY / sqrt2;
                if (maxStep < 3)
                    maxStep = random.Next(3) + 3.0;
                else
                    maxStep = maxStep / sqrt5;
            }

            veloX += windX;
            veloY += windY;
            veloX = veloX + gravity * (xe - xs) / dist;
            veloY = veloY + gravity * (ye - ys) / dist;

            if (Hypot(veloX, veloY) > maxStep) {
                randomDist = maxStep / 2.0 + random.Next((int)Math.Round(maxStep) / 2);
                veloMag = Hypot(veloX, veloY);
                veloX = (veloX / veloMag) * randomDist;
                veloY = (veloY / veloMag) * randomDist;
            }

            oldX = (int)Math.Round(xs);
            oldY = (int)Math.Round(ys);
            xs += veloX;
            ys += veloY;
            dist = Hypot(xe - xs, ye - ys);
            newX = (int)Math.Round(xs);
            newY = (int)Math.Round(ys);

            if (oldX != newX || oldY != newY)
                SetCursorPos(newX, newY);

            step = Hypot(xs - oldX, ys - oldY);
            int wait = (int)Math.Round(waitDiff * (step / maxStep) + minWait);
            Thread.Sleep(wait);
        }

        int endX = (int)Math.Round(xe);
        int endY = (int)Math.Round(ye);
        if (endX != newX || endY != newY)
            SetCursorPos(endX, endY);
    }

    static double Hypot(double dx, double dy) {
        return Math.Sqrt(dx * dx + dy * dy);
    }

    [DllImport("user32.dll")]
    static extern bool SetCursorPos(int X, int Y);

    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(out Point p);
}
Run Code Online (Sandbox Code Playgroud)