我正在演示一款软件,并希望构建一个鼠标'移动器'功能,以便我可以基本上自动化该过程。我想创造逼真的鼠标动作,但在思维过程中有一点心理障碍。我可以很容易地用c#移动鼠标,但希望它比仅出现在特定x,y坐标处然后按下按钮的光标要逼真一些。C#在现实中移动鼠标
我得到鼠标的当前位置,然后得到终点。计算这两个点之间的弧,但是我需要计算沿着该弧的点,以便我可以添加一个定时器事件,以便我可以从一个点移动到另一个点,然后重复此操作直到达到目标...
有人想详细说明吗?
感谢,R.
我正在演示一款软件,并希望构建一个鼠标'移动器'功能,以便我可以基本上自动化该过程。我想创造逼真的鼠标动作,但在思维过程中有一点心理障碍。我可以很容易地用c#移动鼠标,但希望它比仅出现在特定x,y坐标处然后按下按钮的光标要逼真一些。C#在现实中移动鼠标
我得到鼠标的当前位置,然后得到终点。计算这两个点之间的弧,但是我需要计算沿着该弧的点,以便我可以添加一个定时器事件,以便我可以从一个点移动到另一个点,然后重复此操作直到达到目标...
有人想详细说明吗?
感谢,R.
我试过了弧计算方法,结果很复杂,最后看起来不太现实。正如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);
}
平常的方式,我想,是物理上与自己的手移动鼠标实:并有软件捕获的(真正的)动作,并对其进行重放。
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#不应该太难,这些都很现实。
我将前面提到的WindMouse
函数转换成了C#,它实际上很现实。请注意,这只是一个粗略的示例,并且不使用包装GetCursorPos
和SetCursorPos
。我将使用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);
}
您将鼠标从A点移动到B点的弧中?我似乎走了一条直线。这会让你的生活变得更轻松。 :) – 2009-05-27 02:20:03
那么,问题是什么?详细说明你的想法? – JerSchneid 2009-05-27 02:22:30
JP:除非你使用标尺工作,你所有的鼠标线都是直线吗? :) 我只是想方法使鼠标使用代码的现实方式移动。我搜索了一下,寻找代码库,但这是没有做到的。 – flavour404 2009-05-27 19:58:55