.NET自动化测试手记(2)- 实例:点击计算器按钮
这篇文章主要介绍通过.NET结合Win32 API来实现点击计算器上一个按钮的操作。
假设已经有一个“计算器”程序在运行,操作步骤如下:
1. 添加程序集引用: WindowsBase, UIAutomationClient 和 UIAutomationTypes
2. 引用命名空间:
引用命名空间
using System.Windows;
using System.Runtime.InteropServices; //调用Win32 API
using System.Windows.Automation; //使用.NET Automation类
3. 声明对Win32 API的引用
添加Win32引用
[DllImport("User32.dll")]
public static extern bool SetForegroundWindow(int handler); //将对应句柄的窗口在屏幕最前端显示并激活
[DllImport("user32.dll")]
public static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo); //这里将实现鼠标的模拟操作
[Flags]
public enum MouseEventFlag : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
VirtualDesk = 0x4000,
Absolute = 0x8000
}
4. 查找Title为“Calculator”的窗体
查找Calculator的主窗体
AutomationElement desk = AutomationElement.RootElement;
AutomationElement eleWindow = GetWindowByName(desk, "Calculator");
根据窗体名字获取窗体元素的方法定义
public static AutomationElement GetWindowByName(AutomationElement parent, string name)
{
if (parent == null)
{
throw new Exception("Parent element is null!");
}
PropertyCondition nameProperty = new PropertyCondition(AutomationElement.NameProperty, name);
PropertyCondition typeProperty = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window);
AndCondition andCondition = new AndCondition(nameProperty, typeProperty);
return parent.FindFirst(TreeScope.Descendants | TreeScope.Element, andCondition);
}
5. 获取窗体中对应的Button(例如“3”)
AutomationElement eleButton = FindControlInWindow(eleWindow, "3");
根据名字获取窗体中对应Button的方法
public static AutomationElement FindControlInWindow(AutomationElement window, string name)
{
if (window==null)
{
throw new Exception("Target window is null!");
}
PropertyCondition nameProperty = new PropertyCondition(AutomationElement.NameProperty, name);
PropertyCondition typeProperty = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button);
AndCondition andCondition = new AndCondition(nameProperty, typeProperty);
return window.FindFirst(TreeScope.Descendants | TreeScope.Element, andCondition);
}
6. 点击Button
点击Button
InvokePattern buttonClick = (InvokePattern)eleButton.GetCurrentPattern(InvokePattern.Pattern);
buttonClick.Invoke();
到这里,一个简单的点击计算器的操作就完成了,结果如下图:
当然,还可以通过Win32 API来实现一些可视化的操作,比如
1. 在获得窗体之后可以将窗体激活并显示在屏幕最前面
添加Win32引用
[DllImport("User32.dll")]
public static extern bool SetForegroundWindow(int handler); //将对应句柄的窗口在屏幕最前端显示并激活
调用SetForegroundWindow
SetForegroundWindow(eleWindow.Current.NativeWindowHandle);
2. 实现鼠标的移动和点击
添加Win32引用
[DllImport("user32.dll")]
public static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo); //这里将实现鼠标的模拟操作
[Flags]
public enum MouseEventFlag : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
VirtualDesk = 0x4000,
Absolute = 0x8000
}
移动鼠标到Button上并点击
Cursor.Position = new System.Drawing.Point((int)eleButton.Current.BoundingRectangle.Left+(int)eleButton.Current.BoundingRectangle.Size.Width/2, (int)eleButton.Current.BoundingRectangle.Top+(int)eleButton.Current.BoundingRectangle.Size.Height/2);
mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.LeftUp, 0, 0, 0, UIntPtr.Zero);
好了,到这里要介绍的内容就已经说完了。但是还有一些操作始终解决不了:
1. 使用Win32获得“计算器”里面数字按钮的句柄
2. 使用.NET类来模拟鼠标的操作(不调用Win32)
如果有哪位朋友有这两个问题的解决方案,希望能够指点一下...