2009-05-27 9 views
8

私はソフトウェアをデモしており、マウスの移動機能を構築して基本的にプロセスを自動化できるようにしたいと考えています。私は現実的なマウスの動きを作りたいと思っていますが、思考過程で精神的なブロックが少しあります。私はC#で簡単にマウスを動かすことができますが、特定のx、y、座標に現れるカーソルだけでなく、ボタンを押しているより少し現実的であることを望みます。C#マウスを現実に動かす

私はマウスの現在の位置を取得し、次に終点を取得します。 2つの点の間の円弧を計算しますが、その円弧に沿って点を計算する必要があります。そこで、ある点から次の点に移動できるようにタイマーイベントを追加してから、ターゲットに到達するまでこれを繰り返します...

誰も手直ししたいですか?

おかげで、R.

+1

マウスをポイントAからポイントBまで弧で移動しますか?私はまっすぐに行くようです。それはあなたの人生をもっと楽にするでしょう。 :) –

+0

だから、何が問題なのですか?あなたのアイデアを精緻化しますか? – JerSchneid

+0

JP:ルーラーで作業しない限り、すべてのマウスの軌跡は本当に直線ですか? :) 私は、コードを使用して現実的な方法でマウスを動かす方法を考えています。私はグーグルでコードベースを探していますが、実際には行われていないことです。 – flavour404

答えて

17

私はアーク計算方法を試しましたが、それほど複雑ではなく、結局は現実的に見えませんでした。 JPがコメントで示唆しているように、ストレートラインはもっと人間に見えます。

これは、線形マウスの動きを計算するために書いた関数です。かなり自明でなければならない。 GetCursorPosition()およびSetCursorPosition(Point)は、Win32関数GetCursorPosおよびSetCursorPosのラッパーです。

技術的には、技術的にはこれは線分のLinear Interpolationと呼ばれています。ここで

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

私は誰かが数学で賢いだろうと知っていた! :) –

+0

うれしい私は失望しませんでした。 =) –

+0

エリック、私はこの最後の夜に返信したと思ったが、明らかに私は思ったよりも疲れていた。ありがとう、それは素晴らしい答えと私にはっきりと私に使用できるもの、b)私が拡大できるものを与えます。素晴らしい答え。私はあなたがアークについて言ったことに気づくでしょう。 – flavour404

1

通常の方法では、私が思うに、物理的に自分自身の手で実際のマウスを移動することです:ソフトウェアは、それらの(本当の)動きをキャプチャし、それらを再生しています。

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; 

SCARで書かれたいくつかの方法があります。それらを変換するC#はあまりにも難しくはありません、これらは非常に現実的です。

+0

ありがとう、ありがとうございます。面白いモニカ! :) – flavour404

+0

私はminE()関数が何をしているのか考え出すことを試みてきましたか? – flavour404

+0

@flavour404 - 'minE()' 2つの変数--Math.Min() 'またはそれに類するもののうち小さい方を返します。ソース:http://forums.freddy1990.com/index.php?topic=4214.0 –

8

前述のWindMouse関数をC#に変換していますが、実際はかなり現実的です。これは単なるサンプルであり、GetCursorPosSetCursorPosのラッパーは使用しないことに注意してください。私は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); 
}