自动化测试核心部分之一就是要模拟用户的输入,主要有三个方面:
模拟键盘输入
键盘输入其实就是调用系统的API函数:
VOID keybd_event( BYTE bVk, BYTE bScan, DWORD dwFlags, DWORD dwExtraInfo); |
有了这个函数,只要我们知道你想模拟的键的Virtual Code,你就可以模拟敲键了,具体的Virtual Code可以查阅MSDN手册。这其中有一点点小问题,那就是对PC来说,Virtual Code很容易一一确定,但是在Windows Mobile来说,就不那么显而易见了,比如说那两个软件分别是VK_F1和VK_F2,而那个Center键则是VK_RETURN。当时我就是琢磨了不少时间才确定这些虚拟码,最简洁的办法就是自己写一个程序捕捉一下这些键到底是啥,不要瞎猜,嘿嘿~
模拟文本输入
上面说的模拟键盘输入确实可以模拟输入一些ASCI码值,比如你要输入英文,那绝对没有问题,只需一个一个的发送Virtual Code就行了,但是如果要输入Unicode比如中文什么的,那就不行了,因为keybd_event中的bVk参数本身就是BYTE类型的,应该不可能传送Unicode,所以只能用另外一个办法,就是向你想输入的窗口发送WM_CHAR消息,所以问题就是我们如何得到目标窗口的句柄。由于所测App 与我们的自动化测试程序不在同一个线程,所以我们没法直接找到那些窗口,这里我采用了另外一种方法,因为通常情况下目标窗口都是当前的Focused的窗口,所以只要我们能用GetFocus这个API那就可以得到句柄了,但是不同线程之间是没有共享Input Status的,所以我们首先要通过AttachThreadInput这个API来把测试程序所在的Thread attach到Focused窗口所在的Thread,然后再调用GetFocus就可以达到我们的目的了。下面是一段C代码:
// Get the fore ground window. HWND foreWindow = GetForegroundWindow(); // Get the id of the thread the foreground window belongs to. DWORD focusedThreadID = GetWindowThreadProcessId(foreWindow, NULL); // Get the current thread id, our test program. DWORD currentThreadID = GetCurrentThreadId(); // Attach our test thread to the thread the focused window belongs to. AttachThreadInput(currentThreadID, focusedThreadID, TRUE); // Get the handle of the focused window. HWND focusedWindow = GetFocus(); // Now you can send the wide char to the focused window. const wchar_t text = L'捕';SendMessage(focusedWindow, WM_CHAR, LPARAM(text), NULL); |
需要说明的是,在Windows Mobile上面你不能这么做,因为WinMobile不支持AttachThreadInput这个函数。于是我找到了另外一个API:
BOOL WINAPI GetForegroundInfo( GET_FOREGROUND_INFO* pgfi); |
通过这个函数可以得到一个GET_FOREGROUND_INFO结构体,里面包含了很多有用的信息。
typedef struct tagGetForegroundInfo { HWND hwndActive; HWND hwndFocus; HWND hwndMenu; HWND hwndKeyboardDest; DWORD fdwConversion; DWORD fdwSentence; BOOL fOpen; DWORD dwCompStrLen; HKL KeyboardLayoutHandle; }GET_FOREGROUND_INFO; |