接着上一篇的话题,因为要为 win32 程序写 UI 测试,自已也摸索出来一个大致的框架。在这里做一个小结:
以下代码都发表在公有领域(http://zh.wikipedia.org/zh-cn/Public_domain),你可以自由地使用它们。
1. 首先,你需要创建进程:
创建进程后,PROCESS_INFORMATION 结构体中就有了进程 id 和主线程 id 。
2. 获得主窗口句柄
主要通过 EnumWindows 来实现,如果窗口 title 是固定的,那么也可以用 FindWindowEx 。我这里由于 title 和 class name 都未知,用了一种比较搓的办法:先通过线程 id 随便找一个窗口,再用 GetParent 获取最顶层的窗口
当然,如果你提前就知道窗口的 class name ,就可以直接在回调函数中指定这个条件。
顺便说一下如何在 MFC 程序中指定 class name :让你的 CMainFrame 继承来自 CWnd 的 PreCreateWindow 函数,这个函数将在 MFC 调用 CreateWindow 之前调用:
另外,可以通过 VS 自带的 spy++ 查看桌面上所有窗口的 class name 。
3. 模拟点菜单
hWnd 是你的窗口句柄,CM_PROJECTPURCHASES 是对应的菜单 ID 。注意要 Sleep 足够的时间。
还要注意 PostMessage 和 SendMessage 的区别:SendMessage 必须要等相应程序处理完消息之后才返回,而 PostMessage 是异步的,立即返回。所以 PostMessage 需要 Sleep,而 SendMessage 则不需要。
4. 获得最表面的窗口
与 GetFocus() 不同,这个直接获得直观上最表层的那个窗口(比如点了菜单后弹出来的一个窗口),相当 imba 。而 GetFocus() 得到的句柄可能会是一个编辑框控件。
5. 关闭窗口
然后就是 GetDlgItem() 之流了,再加上上篇文章介绍的模拟按键,基本上能搞定大部分的自动化 UI 测试任务。