C#逼真地移动鼠标

我正在演示一个软件,并希望构建一个鼠标“移动器”function,以便我基本上可以自动化该过程。 我想创建逼真的鼠标移动,但在思考过程中有一点心理障碍。 我可以使用c#轻松移动鼠标,但希望它比仅出现在某个x,y,坐标处然后按下按钮的光标更逼真。

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

有人想详细说明吗?

谢谢,R。

我尝试了弧计算方法,原来是复杂的,最后,它看起来并不现实。 JP在他的评论中表示,直线看起来更加人性化。

这是我编写的用于计算线性鼠标移动的函数。 应该是不言自明的。 GetCursorPosition()和SetCursorPosition(Point)是win32函数GetCursorPos和SetCursorPos的包装器。

就数学而言 – 从技术上讲,这称为线段的线性插值 。

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

我将WindMouse提到的WindMouse函数转换为C#,它实际上非常逼真。 请注意,这只是一个粗略的示例,并且不使用GetCursorPosSetCursorPos包装器。 我将使用Windows输入模拟器包装器。

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

我认为通常的方法是用自己的手动物移动真正的鼠标:让软件捕获那些(真实的)动作,然后重放它们。