不同於上一篇的WinAPI方法,這次讓我們來看另一個更簡單、有效的鍵鼠模擬方案,即通過COM組件AutoItX實現鍵鼠模擬。
AutoIt
AutoIt是一個免費軟件,它使用一種類似BASIC的腳本語言,對Windows圖形界面進行自動操控。它的網址是http://www.autoitscript.com。
本次我們不討論它的腳本語言,而是在C#中使用其COM組件來完成鍵鼠模擬的工作,在開始之前,先歸納一下下AutoIt官網上介紹的主要功能:
- 模擬鍵盤、鼠標操作。
- 與Windows的標准控件進行交互。
- 操控Windows窗口和進程。
- 支持腳本編程,並能將腳本編譯成獨立的EXE文件。
- 支持COM組件。
了解了AutoIt,讓我們繼續拿上海拍牌程序(NetBidClient)作為實驗對象,用C#調用AutoItX組件進行拍牌出價的操作。
目標
本次我們的實驗目標是讓計算機在拍牌的第二階段自動出價,幫我們在最低可成交價的基礎上加價900元出價。具體一點的目標如下:
- 點“+300”按鈕(模擬鼠標輸入方式)。
- 讀取價格輸入框(TextBox)中的值,在此基礎上加價600元寫回價格框(發送消息方式)。
- 點“自動查詢公開信息”復選框(控制標准控件)。
- 點“出價”按鈕,打開驗證碼窗口。
准備工作
這個工具類似VS中的Spy++, 只是設計得更適合AutoIt腳本使用,界面如下圖:
綠圈中的十字准星用法和Spy++中的一樣,拖到控件上就能捕獲控件信息(只能是標准控件)。
紅線標注的部分是我們常用的信息,可能是你調用AutoItX函數時需要傳入的參數,或者是用來計算坐標等,如Advanced Mode 屬性值 [CLASS:TNoPasteEdit; INSTANCE:2]
用於控件在窗體中的唯一標識。
新建工程、添加引用
新建一個WinForm工程,並為工程添加AutoItX的COM組件引用如下圖:
接下來,需要設置一下工程屬性,因為AutoItX是32位的組件,所以我們的工程也得是32位的,在資源管理器窗口中鼠標右鍵選中工程,依次工程->屬性->生成->目標平台->x86
。
在代碼中添加using引用指令,就可以使用它的豐富功能了。
using AutoItX3Lib;
AutoItX3 _V3 = null;
_V3 = new AutoItX3(); //實例化
使用參數設置
通過調用AutoItSetOption函數可以對AutoIt實例進行參數設置,這些參數內容可在AutoIt的幫助文檔中找到,主要是些關於坐標系統、操作延時、窗口信息查詢的匹配模式等等內容, 你可以根據實際情況選擇設置,不設也沒有問題,它們有默認值,看兩個例子:
// 匹配窗體標題時,只要含有指定的字符串即可
// default=1 是開頭部分與指定的字符串匹配
// 也可以用高級模式 = 4, 還能通過正則表達式匹配標題
_V3.AutoItSetOption("WinTitleMatchMode", 2);
//設置鼠標點擊的延時,連續點2次鼠標時的時間間隔(ms),默認是 10ms
_V3.AutoItSetOption("MouseClickDelay", 20);
模擬鼠標鍵盤輸入
在AutoItX中有一些以Mouse*開頭的函數用於模擬鼠標輸入,如 MouseClick,MouseDown,MouseUp,MouseMove,MouseWheel,MouseClickDrag
,這些函數的調用大同小異,現在我們以MouseClick為例進行說明:
MouseClick ( "button" [, x, y [, clicks = 1 [, speed = 10]]] )
- button: 指鼠標鍵(如 left,right,middle... 具體參見幫助)
- x,y: 指鼠標點擊的坐標, 這里是屏幕坐標。
- clicks: 點擊的次數
- speed: 鼠標移動的速度 (1-100,1最快),若為0 則立刻到位。
本實驗的第1步和第4步都是靠鼠標模擬點擊來實現的,那兩個按鈕都不是標准控件,我們無法靠發送消息觸發它們。
//獲得窗口的屏幕坐標加上"+300"按鈕的相對位置,可得需要點擊的位置
int scrX = _V3.WinGetPosX(_WinTitle) + 650;
int scrY = _V3.WinGetPosY(_WinTitle) + 380;
//立刻移動到(scrX,scrY)處, 點擊鼠標左鍵一次
_V3.MouseClick("LEFT", scrX, scrY, 1,0);
再來看看,鍵盤輸入是如何模擬的,直接上例子:
//首先需要讓光標移動到需要輸入的地方
_V3.MouseClick("LEFT", scrX, scrY, 1);
//如果輸入的地方是標准控件,還可直接使用ControlFocus達到目的
_V3.ControlFocus(_WinTitle, "", "[CLASS:TNoPasteEdit; INSTANCE:2]");
//用Send函數發送字符
//^a 表示 Ctrl+a組合鍵,全選TextBox的內容
// {DEL} 按下刪除鍵
//80000 輸入80000
_V3.Send("^a{DEL}80000");
操控標准控件
AutoItX中以Control*開頭的函數多是關於標准控件的,所謂標准控件,也就是那些可以用AutoIt Window Info工具捕捉到的控件。
下面看個例子,實驗第2步出價文本框的設置以及第3步“自動查詢公開信息”CheckBox操作:
//Step 2. 讀取出價TextBox中的內容, ControlGetText 的參數值都是通過AutoIt Window Info工具抓取的
string pricestr = _V3.ControlGetText(_WinTitle, "", "[CLASS:TNoPasteEdit; INSTANCE:2]");
int price = 0;
if (Int32.TryParse(pricestr, out price))
{
//出價+600后,寫入出價TextBox中
_V3.ControlSetText(_WinTitle, "", "[CLASS:TNoPasteEdit; INSTANCE:2]", (price + 600).ToString());
}
//Step 3. Uncheck “自動查詢公開信息” 復選框
_V3.ControlCommand(_WinTitle,"","[CLASS:TCheckBox; INSTANCE:1]","UnCheck","");
操控窗口
在自動界面操作中,常需要判斷窗口的狀態,來決定下一步的動作。如,在實驗第4步中點擊出價按鈕之后,我們需要知道是否成功打開驗證碼窗口,然后才能提取驗證碼進行識別。
//等待驗證碼窗口激活,最長等待10秒 即timeout = 10s
//驗證碼窗口的Title和主窗口相同,為了區別這里使用了窗口的[CLASS:]
if (0 != _V3.WinWaitActive("[CLASS:TImageCodeForm]", "", 10))
{
//判斷狀態 驗證碼窗口是否可見
if ((_V3.WinGetState("[CLASS:TImageCodeForm]", "") & 2) == 2)
{
MessageBox.Show("驗證碼窗口打開了");
//TODO: 抓取、識別驗證碼
}
}
結束語
最后提醒一下,發布您的程序時,如果目標機上沒有安裝AutoIt,您需要運行regsvr32 AutoItX3.dll
注冊一下組件(需要管理員權限,AutoItX3.dll 在安裝目錄下找)。
好了,希望您能喜歡AutoItX組件,繼續探索它的功能,開發一些有趣的應用。
附件:
SimuAutoIt.zip 本文例子程序