C# moving the mouse around realistically

后端 未结 5 1273
孤街浪徒
孤街浪徒 2020-12-02 21:44

I am demoing a piece of software and want to build a mouse \'mover\' function so that I can basically automate the process. I want to create realistic mouse movements but a

相关标签:
5条回答
  • 2020-12-02 21:59

    I converted the WindMouse function mentioned earlier into C# and it is actually pretty realistic. Note that this is just a rough sample and does not use wrappers for GetCursorPos and SetCursorPos. I will be using the Windows Input Simulator wrappers.

    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);
    }
    
    0 讨论(0)
  • 2020-12-02 22:04

    A usual way, I think, is to physically move the real mouse with your own hand: and have the software capture those (real) movements, and replay them.

    0 讨论(0)
  • 2020-12-02 22:10
    procedure WindMouse(xs, ys, xe, ye, gravity, wind, minWait, maxWait, maxStep, targetArea: extended);
    var
      veloX, veloY, windX, windY, veloMag, dist, randomDist, lastDist, step: extended;
      lastX, lastY: integer;
      sqrt2, sqrt3, sqrt5: extended;
    begin
      sqrt2:= sqrt(2);
      sqrt3:= sqrt(3);
      sqrt5:= sqrt(5);
      while hypot(xs - xe, ys - ye) > 1 do
      begin
        dist:= hypot(xs - xe, ys - ye);
        wind:= minE(wind, dist);
        if dist >= targetArea then
        begin
          windX:= windX / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
          windY:= windY / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
        end else
        begin
          windX:= windX / sqrt2;
          windY:= windY / sqrt2;
          if (maxStep < 3) then
          begin
            maxStep:= random(3) + 3.0;
          end else
          begin
            maxStep:= maxStep / sqrt5;
          end;
        end;
        veloX:= veloX + windX;
        veloY:= veloY + windY;
        veloX:= veloX + gravity * (xe - xs) / dist;
        veloY:= veloY + gravity * (ye - ys) / dist;
        if hypot(veloX, veloY) > maxStep then
        begin
          randomDist:= maxStep / 2.0 + random(round(maxStep) / 2);
          veloMag:= sqrt(veloX * veloX + veloY * veloY);
          veloX:= (veloX / veloMag) * randomDist;
          veloY:= (veloY / veloMag) * randomDist;
        end;
        lastX:= Round(xs);
        lastY:= Round(ys);
        xs:= xs + veloX;
        ys:= ys + veloY;
        if (lastX <> Round(xs)) or (lastY <> Round(ys)) then
          MoveMouse(Round(xs), Round(ys));
        step:= hypot(xs - lastX, ys - lastY);
        wait(round((maxWait - minWait) * (step / maxStep) + minWait));
        lastdist:= dist;
      end;
      if (Round(xe) <> Round(xs)) or (Round(ye) <> Round(ys)) then
        MoveMouse(Round(xe), Round(ye));
    end;
    
    {*******************************************************************************
    procedure MMouse(x, y, rx, ry: integer);
    By: Benland100
    Description: Moves the mouse.
    *******************************************************************************}
    //Randomness is just added to the x,y. Might want to change that.
    procedure MMouse(x, y, rx, ry: integer);
    var
      cx, cy: integer;
      randSpeed: extended;
    begin
      randSpeed:= (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
      if randSpeed = 0.0 then
        randSpeed := 0.1;
      getMousePos(cx,cy);
      X := x + random(rx);
      Y := y + random(ry);
      WindMouse(cx,cy,x,y,9.0,3.0,10.0/randSpeed,15.0/randSpeed,10.0*randSpeed,10.0*randSpeed);
    end;
    

    Here are some methods written in SCAR. Converting them C# shouldn't be too hard, these are quite realistic.

    0 讨论(0)
  • 2020-12-02 22:12

    I tried the arc calculation method, turned out to be far to complex and, in the end, it didn't look realistic. Straight lines look much more human, as JP suggests in his comment.

    This is a function I wrote to calculate a linear mouse movement. Should be pretty self-explanatory. GetCursorPosition() and SetCursorPosition(Point) are wrappers around the win32 functions GetCursorPos and SetCursorPos.

    As far as the math goes - technically, this is called Linear Interpolation of a line segment.

    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);
    }
    
    0 讨论(0)
  • 2020-12-02 22:23

    You can try this.

    public static class Mouse
    {
        private const float MOUSE_SMOOTH = 200f;
    
        public static void MoveTo(int targetX, int targetY)
        {
            var targetPosition = new Point(targetX, targetY);
            var curPos = Cursor.Position;
    
            var diffX = targetPosition.X - curPos.X;
            var diffY = targetPosition.Y - curPos.Y;
    
            for (int i = 0; i <= MOUSE_SMOOTH; i++)
            {
                float x = curPos.X + (diffX / MOUSE_SMOOTH * i);
                float y = curPos.Y + (diffY / MOUSE_SMOOTH * i);
                Cursor.Position = new Point((int)x, (int)y);
                Thread.Sleep(1);
            }
    
            if (Cursor.Position != targetPosition)
            {
                MoveTo(targetPosition.X, targetPosition.Y);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题