2009-05-27 22 views
8

Sto demoando un pezzo di software e voglio costruire una funzione di 'mover' del mouse in modo da poter sostanzialmente automatizzare il processo. Voglio creare movimenti realistici del mouse ma sto avendo un po 'di blocco mentale nel processo di pensiero. Posso spostare facilmente un mouse con C# ma voglio che sia un po 'più realistico del semplice cursore che appare a una certa x, y, coordinate e quindi premendo un pulsante.C# che muove il mouse in modo realistico

Ottengo la posizione corrente del mouse e quindi ottenere il punto finale. Calcola un arco tra i due punti, ma poi ho bisogno di calcolare punti lungo quell'arco in modo da poter aggiungere un evento timer in modo che possa passare da un punto a quello successivo, e poi ripetere fino a raggiungere l'obiettivo ...

Qualcuno vuole elaborare?

Grazie, R.

+1

Si sposta il mouse dal punto A al punto B in un arco? Mi sembra di andare dritto. Ciò renderà la tua vita molto più facile. :) –

+0

Quindi, qual è la domanda? Elaborare la tua idea? – JerSchneid

+0

JP: a meno che non si lavori con un righello, tutti i percorsi del mouse sono allineati? :) Sto solo pensando a come far muovere il mouse in modo realistico usando il codice. Ho cercato su Google, cercando una base di codice ma è qualcosa che non è davvero fatto. – flavour404

risposta

17

Ho provato il metodo di calcolo dell'arco, risultando molto complesso e, alla fine, non sembrava realistico. Le linee rette appaiono molto più umane, come suggerisce JP nel suo commento.

Questa è una funzione che ho scritto per calcolare un movimento del mouse lineare. Dovrebbe essere abbastanza auto-esplicativo. GetCursorPosition() e SetCursorPosition (Point) sono wrapper attorno alle funzioni win32 GetCursorPos e SetCursorPos.

Per quanto riguarda la matematica - tecnicamente, questo è chiamato Linear Interpolation di un segmento di linea.

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

Sapevo che qualcuno sarebbe stato furbo con la matematica! :) –

+0

Felice di non aver deluso. =) –

+0

Erik, pensavo di aver risposto a quest'ultima notte, ma ovviamente ero più stanco di quanto pensassi. Grazie, è un'ottima risposta e sicuramente mi dà qualcosa) qualcosa che posso usare, b) qualcosa su cui posso espandermi. Bella risposta. Terrò a mente quello che hai detto sull'arco. – flavour404

1

Un modo di consueto, a mio avviso, è quello di spostare fisicamente il mouse vero e proprio con la propria mano: e hanno il software di cattura quei movimenti (reali), e riprodurle.

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; 

Ecco alcuni metodi scritti in SCAR. Convertirli in C# non dovrebbe essere troppo difficile, sono abbastanza realistici.

+0

Grazie a qualcuno, darò un'occhiata. Moniker interessante! :) – flavour404

+0

Ho cercato di capire cosa fa la funzione minE(), qualche idea? – flavour404

+0

@ flavour404 - 'minE()' Restituisce il più piccolo di due variabili - 'Math.Min()' o simile. Fonte: http://forums.freddy1990.com/index.php?topic=4214.0 –

8

Ho convertito la funzione WindMouse menzionata in precedenza in C# ed è in realtà piuttosto realistico. Si noti che questo è solo un campione approssimativo e non utilizza wrapper per GetCursorPos e SetCursorPos. Utilizzerò i wrapper 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); 
} 
Problemi correlati