2009-05-27 15 views
8

Estoy demondo una pieza de software y quiero construir una función de "mover" el mouse para poder básicamente automatizar el proceso. Quiero crear movimientos de mouse realistas pero estoy teniendo un poco de bloqueo mental en el proceso de pensamiento. Puedo mover un mouse fácilmente con C# pero quiero que sea un poco más realista que solo el cursor que aparece en ciertas coordenadas x, y, y luego presionar un botón.C# moviendo el mouse de forma realista

Obtengo la posición actual del mouse y luego obtengo el punto final. Calcule un arco entre los dos puntos, pero luego necesito calcular los puntos a lo largo de ese arco para poder agregar un evento de temporizador para poder moverme de un punto al siguiente, y luego repetir esto hasta que llegue al objetivo ...

¿Alguien quiere elaborar?

Gracias, R.

+1

Mueve el mouse del punto A al punto B en un arco? Me parece ir en línea recta. Eso haría tu vida mucho más fácil. :) –

+0

Entonces, ¿cuál es la pregunta? Elabora tu idea? – JerSchneid

+0

JP: a menos que trabajes con una regla, ¿son todos tus rastros de ratón realmente rectas? :) Estoy pensando en formas de hacer que el mouse se mueva de forma realista usando el código. Busqué en Google, buscando una base de código, pero es algo que realmente no está hecho. – flavour404

Respuesta

17

Probé el método de cálculo de arco, resultó ser muy complejo y, al final, no parecía realista. Las líneas rectas se ven mucho más humanas, como JP sugiere en su comentario.

Esta es una función que escribí para calcular un movimiento lineal del mouse. Debería ser bastante autoexplicativo. GetCursorPosition() y SetCursorPosition (Point) son envoltorios alrededor de las funciones win32 GetCursorPos y SetCursorPos.

En cuanto a las matemáticas, técnicamente, esto se llama Linear Interpolation de un segmento de línea.

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); 
} 
+2

¡Sabía que alguien sería inteligente con las matemáticas! :) –

+0

Me alegro de que no me decepcionó. =) –

+0

Erik, pensé que respondí a esto anoche, pero obviamente estaba más cansado de lo que pensaba. Gracias, es una gran respuesta y definitivamente me da a) algo que puedo usar, b) algo que puedo ampliar. Gran respuesta. Tendré en cuenta lo que dijiste sobre el arco. – flavour404

1

Una forma habitual, creo, es mover físicamente el ratón real con su propia mano, y tener el software de captura de esos movimientos (reales), y reproducirlas.

3
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; 

Éstos son algunos de los métodos escritos en el SCAR. Convertirlos C# no debería ser demasiado difícil, estos son bastante realistas.

+0

Gracias a alguien, voy a echar un vistazo. ¡Apodo interesante! :) – flavour404

+0

He estado tratando de averiguar qué hace la función minE(), ¿alguna idea? – flavour404

+0

@ flavour404 - 'minE()' Devuelve la menor de dos variables: 'Math.Min()' o similar. Fuente: http://forums.freddy1990.com/index.php?topic=4214.0 –

8

Convertí la función WindMouse mencionada anteriormente en C# y en realidad es bastante realista. Tenga en cuenta que esto es solo una muestra aproximada y no utiliza wrappers para GetCursorPos y SetCursorPos. Voy a utilizar los contenedores Windows Input Simulator.

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); 
} 
Cuestiones relacionadas