2015-02-08 97 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