2009-05-27 92 views
8

我正在演示一款软件,并希望构建一个鼠标'移动器'功能,以便我可以基本上自动化该过程。我想创造逼真的鼠标动作,但在思维过程中有一点心理障碍。我可以很容易地用c#移动鼠标,但希望它比仅出现在特定x,y坐标处然后按下按钮的光标要逼真一些。C#在现实中移动鼠标

我得到鼠标的当前位置,然后得到终点。计算这两个点之间的弧,但是我需要计算沿着该弧的点,以便我可以添加一个定时器事件,以便我可以从一个点移动到另一个点,然后重复此操作直到达到目标...

有人想详细说明吗?

感谢,R.

+1

您将鼠标从A点移动到B点的弧中?我似乎走了一条直线。这会让你的生活变得更轻松。 :) – 2009-05-27 02:20:03

+0

那么,问题是什么?详细说明你的想法? – JerSchneid 2009-05-27 02:22:30

+0

JP:除非你使用标尺工作,你所有的鼠标线都是直线吗? :) 我只是想方法使鼠标使用代码的现实方式移动。我搜索了一下,寻找代码库,但这是没有做到的。 – flavour404 2009-05-27 19:58:55

回答

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); 
} 
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#不应该太难,这些都很现实。

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