2009-05-27 9 views
8

Ich Demo ein Stück Software und möchte eine Mouse 'Mover' Funktion zu bauen, so dass ich den Prozess im Grunde automatisieren kann. Ich möchte realistische Mausbewegungen erzeugen, habe aber im Denkprozess eine gewisse mentale Blockade. Ich kann eine Maus leicht mit C# bewegen, aber ich möchte, dass sie etwas realistischer ist als nur der Cursor, der an einer bestimmten x, y, Koordinaten erscheint und dann einen Knopf drückt.C# bewegte die Maus realistisch

Ich bekomme die aktuelle Position der Maus und dann den Endpunkt. Berechne einen Bogen zwischen den beiden Punkten, aber dann muss ich Punkte entlang des Bogens berechnen, damit ich ein Timer-Ereignis hinzufügen kann, so dass ich von einem Punkt zum nächsten fahren kann, und wiederhole es dann, bis ich zum Ziel komme ...

Jeder möchte etwas ausarbeiten?

Danke, R.

+1

Sie bewegen Ihre Maus von Punkt A nach Punkt B in einem Bogen? Ich scheine in einer geraden Linie zu gehen. Das würde dein Leben viel einfacher machen. :) –

+0

Also, was ist die Frage? Auf Ihre Idee eingehen? – JerSchneid

+0

JP: Wenn du nicht mit einem Lineal arbeitest sind all deine Mausspuren wirklich gerade? :) Ich denke nur an Möglichkeiten, die Maus in realistischer Weise mit Code zu bewegen. Ich habe gegoogelt, auf der Suche nach einer Codebasis, aber es ist etwas, das nicht wirklich gemacht wird. – flavour404

Antwort

17

Ich versuchte die Arc-Berechnung-Methode, erwies sich als weit zu komplex und am Ende sah es nicht realistisch aus. Gerade Linien sehen viel menschlicher aus, wie JP in seinem Kommentar vorschlägt.

Dies ist eine Funktion, die ich geschrieben habe, um eine lineare Mausbewegung zu berechnen. Sollte ziemlich selbsterklärend sein. GetCursorPosition() und SetCursorPosition (Point) sind Wrapper um die Win32-Funktionen GetCursorPos und SetCursorPos.

Soweit die Mathematik geht - technisch heißt das Linear Interpolation eines Liniensegments.

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

Ich wusste, jemand wäre schlau mit der Mathematik! :) –

+0

Ich bin froh, dass ich nicht enttäuscht habe. =) –

+0

Erik, ich dachte, ich hätte letzte Nacht geantwortet, aber offensichtlich war ich mehr müde als ich dachte. Danke, es ist eine großartige Antwort und definitiv gibt mir a) etwas, das ich verwenden kann, b) etwas, das ich erweitern kann. Gute Antwort. Ich werde bedenken, was Sie über den Bogen gesagt haben. – flavour404

1

Eine übliche Art und Weise, wie ich glaube, ist physisch die reale Maus mit der eigenen Hand zu bewegen: und haben die Software Capture diese (real) Bewegungen, und sie wiederholen.

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; 

Hier sind einige in SCAR geschrieben Methoden. Konvertieren sie C# sollte nicht zu schwer sein, das sind ziemlich realistisch.

+0

Danke jemand, ich werde es mir ansehen. Interessanter Spitzname! :) – flavour404

+0

Ich habe versucht, herauszufinden, was die minE() - Funktion, irgendeine Idee? – flavour404

+0

@ flavour404 - 'minE()' Gibt die kleinere von zwei Variablen zurück - 'Math.Min()' oder ähnlich. Quelle: http://forums.freddy1990.com/index.php?topic=4214.0 –

8

Ich konvertierte die zuvor erwähnte WindMouse Funktion in C# und es ist eigentlich ziemlich realistisch. Beachten Sie, dass dies nur ein grobes Beispiel ist und keine Wrapper für GetCursorPos und SetCursorPos verwendet werden. Ich werde die Windows Input Simulator Wrapper verwenden.

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