2015-02-08 40 views
1

我需要自动化一些鼠标动作。如何自动化鼠标动作

我需要做的
mousemove1,lbuttondown1,WAIT1,mousemove1,lbuttonup1,WAIT1,
mousemove2,lbuttondown2,WAIT2,mousemove2,lbuttonup2,WAIT2,
...

的操作必须关于屏幕坐标。必须接受事件的窗口是此时的顶层窗口。

有一个包含数据的文件。
例如

500 450 1000 500 300 2000 
600 450 1000 600 300 5000 

我是怎么尝试做

#include <fstream> 
#include <vector> 
#include <windows.h> 

struct A 
{ 
    POINT point1; 
    unsigned sleep1; 
    POINT point2; 
    unsigned sleep2; 
    A() { point1.x = point1.y = sleep1 = point2.x = point2.y = sleep2 = 0; } 
}; 

void f(const A &a) 
{ 
    mouse_event(MOUSEEVENTF_LEFTDOWN, a.point1.x, a.point1.y, 0, 0); 
    mouse_event(MOUSEEVENTF_MOVE,  a.point1.x, a.point1.y, 0, 0); 
    Sleep(a.sleep1); 

    mouse_event(MOUSEEVENTF_LEFTUP, a.point2.x, a.point2.y, 0, 0); 
    mouse_event(MOUSEEVENTF_MOVE,  a.point2.x, a.point2.y, 0, 0); 
    Sleep(a.sleep2); 
} 

int main() 
{ 
    std::vector<A> as; 

    std::ifstream fin("params.txt"); 
    if (fin) { 
     A a; 
     while (fin.good()) { 
      fin >> a.point1.x; 
      fin >> a.point1.y; 
      fin >> a.sleep1; 

      fin >> a.point2.x; 
      fin >> a.point2.y; 
      fin >> a.sleep2; 

      if (fin.eof()) { 
       break; 
      } 
      as.push_back(a); 
     } 
    } 

    for (;;) { 
     for (const A &a : as) { 
      f(a); 
     } 
    } 
} 

又出事了,但我不明白是什么在哪里是一个错误。

+1

为什么不使用自动化? – 2015-02-08 13:25:53

回答

3

您的代码存在的一个问题是您使用mouse_event与屏幕坐标而不是标准化的绝对坐标。无论桌面大小如何,标准化的绝对坐标始终在左上角的(0,0)至右下角的(65535,65535)之间。

以下示例中的MouseTo函数接受屏幕坐标作为输入,然后使用dekstop窗口的大小将其转换为规范化的绝对​​坐标。此示例使用SendInput,它取代了mouse_event,但它们都使用相同的坐标。我不确定mouse_event是否可以使用MOUSEEVENTF_VIRTUALDESK标志,但是这是为了支持多监视器桌面。

如果您希望构建此示例,请从一个新的Win32控制台应用程序开始。

#include <Windows.h> 
#include <cmath> 

void MouseTo(int x, int y) { 
    RECT desktop_rect; 
    GetClientRect(GetDesktopWindow(), &desktop_rect); 
    INPUT input = {0}; 
    input.type = INPUT_MOUSE; 
    input.mi.dwFlags = 
     MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE; 
    input.mi.dx = x * 65536/desktop_rect.right; 
    input.mi.dy = y * 65536/desktop_rect.bottom; 
    SendInput(1, &input, sizeof(input)); 
} 

void MouseLButton(bool tf_down_up) { 
    INPUT input = {0}; 
    input.type = INPUT_MOUSE; 
    input.mi.dwFlags = tf_down_up ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; 
    SendInput(1, &input, sizeof(input)); 
} 

void MouseLButtonDown() { MouseLButton(true); } 
void MouseLButtonUp() { MouseLButton(false); } 

void AnimatedDrag(const POINT& from, const POINT& to) { 
    static const double iteration_dist  = 20; 
    static const DWORD iteration_delay_ms = 1; 

    const double dx = to.x - from.x; 
    const double dy = to.y - from.y; 
    const double dist = sqrt(dx*dx + dy*dy); 
    const int count = static_cast<int>(dist/iteration_dist); 

    MouseTo(from.x, from.y); 
    MouseLButtonDown(); 

    for(int i=1; i<count; ++i) { 
     const int x = from.x + static_cast<int>(dx * i/count); 
     const int y = from.y + static_cast<int>(dy * i/count); 
     MouseTo(x, y); 
     Sleep(iteration_delay_ms); 
    } 

    MouseTo(to.x, to.y); 
    MouseLButtonUp(); 
} 

int main() { 
    // minimize console window 
    ShowWindow(GetConsoleWindow(), SW_SHOWMINNOACTIVE); 
    Sleep(500); 

    // Drag whatever is at the window coordinates in "from" to "to" 
    const POINT from = {300, 100}; 
    const POINT to = {900, 600}; 
    AnimatedDrag(from, to); 
} 
+0

它看起来很有效。但光标不移动。例如,这段代码虽然光标没有移动,但在文本中选择了一些区域。发生了什么? – Ufx 2015-02-08 18:21:53

+0

当我使用Aero在Windows 7 x64下运行示例时,我看到一个移动的光标。也许动画在您的平台上真的很快发生?您可以将动画延迟调整为100而不是1.这将肯定会减慢光标的移动并使其在动画过程中更加明显。 – 2015-02-08 21:51:26

+0

我认为原因不是快速的动画,因为光标停留在它的点而不是移动到终点。但文字被选中。 – Ufx 2015-02-09 11:40:22