2009-05-27 6 views
8

Je suis en train de démonter un logiciel et je veux créer une fonction de «souris» pour pouvoir automatiser le processus. Je veux créer des mouvements de souris réalistes mais j'ai un peu de blocage mental dans le processus de pensée. Je peux déplacer une souris facilement avec C# mais je veux que ce soit un peu plus réaliste que juste le curseur apparaissant à une certaine x, y, coordonnées, puis en appuyant sur un bouton.C# bouger la souris de façon réaliste

Je reçois la position actuelle de la souris, puis le point final. Calculer un arc entre les deux points, mais ensuite j'ai besoin de calculer des points le long de cet arc de sorte que je puisse ajouter un événement de minuterie pour que je puisse passer d'un point à un autre, puis répéter ceci jusqu'à la cible ...

Quelqu'un veut-il élaborer?

Merci, R.

+1

Vous déplacez votre souris du point A au point B dans un arc? Je semble aller en ligne droite. Cela rendrait votre vie beaucoup plus facile. :) –

+0

Alors, quelle est la question? Elaborer sur votre idée? – JerSchneid

+0

JP: à moins que vous ne travailliez avec une règle, tous vos chemins de souris sont-ils vraiment des lignes droites? :) Je ne fais que penser aux moyens de faire bouger la souris de manière réaliste en utilisant du code. J'ai cherché sur google, mais ce n'est pas vraiment fait. – flavour404

Répondre

17

J'ai essayé la méthode de calcul d'arc, s'est avéré être loin de complexe et, à la fin, il n'a pas semblé réaliste. Les lignes droites semblent beaucoup plus humaines, comme JP le suggère dans son commentaire.

C'est une fonction que j'ai écrite pour calculer un mouvement linéaire de la souris. Devrait être assez explicite. GetCursorPosition() et SetCursorPosition (Point) sont des wrappers autour des fonctions win32 GetCursorPos et SetCursorPos.

En ce qui concerne les mathématiques - techniquement, cela s'appelle Linear Interpolation d'un segment de ligne.

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

Je savais que quelqu'un serait intelligent avec les maths! :) –

+0

Je suis content de ne pas avoir été déçu. =) –

+0

Erik, je pensais avoir répondu à cela hier soir mais visiblement j'étais plus fatigué que je ne le pensais. Merci, c'est une bonne réponse et ça me donne définitivement a) quelque chose que je peux utiliser, b) quelque chose que je peux développer. Très bonne réponse. Je vais garder à l'esprit ce que vous avez dit à propos de l'arc. – flavour404

1

Une manière habituelle, je pense, est de déplacer physiquement la souris réel avec votre propre main et ont la capture du logiciel ces mouvements (réels), et les rejouer.

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; 

Voici quelques méthodes écrites dans SCAR. Les convertir C# ne devrait pas être trop dur, ceux-ci sont assez réalistes.

+0

Merci à quelqu'un, je vais jeter un coup d'oeil. Moniker intéressant! :) – flavour404

+0

J'ai essayé de comprendre ce que fait la fonction minE(), une idée? – flavour404

+0

@ flavour404 - 'minE()' Renvoie la plus petite des deux variables - 'Math.Min()' ou similaire. Source: http://forums.freddy1990.com/index.php?topic=4214.0 –

8

J'ai converti la fonction WindMouse mentionnée précédemment en C# et c'est en fait assez réaliste. Notez que ceci est juste un échantillon approximatif et n'utilise pas les wrappers pour GetCursorPos et SetCursorPos. Je vais utiliser les wrappers 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); 
} 
Questions connexes