WPF UI 自动化






4.50/5 (45投票s)
本文演示了如何创建一个简单的 Windows UI 自动化应用程序。
引言
概述
Microsoft UI 自动化是 Microsoft Windows 的新辅助功能框架,适用于支持 Windows Presentation Foundation (WPF) 的所有操作系统。UI 自动化提供对桌面大多数用户界面 (UI) 元素的程序化访问。
本文演示了如何使用 UI 自动化来控制一个简单的应用程序。基本原理是,控制器应用程序将搜索正在运行的测试应用程序,如果找到该应用程序,我们将搜索 UI 元素层级,然后发送模拟数据。
适用于
- Microsoft® .NET Framework 3.0
- Microsoft® Windows Presentation Foundation - WPF
- Microsoft® UI Automation Framework
UI 自动化框架
该框架的核心思想是它提供了对 Win 应用程序中可见的用户界面元素层级的访问。可以想象层级的根元素是桌面,所有正在运行的应用程序都是根的第一级节点(子节点),依此类推,每个可见窗体都可以细化到其控件,控件再到其子控件,等等。此树中的每个节点都称为 UI 元素。
该框架通过提供对这些 UI 元素及其属性的访问来帮助我们。该框架支持的主要功能有:
- 搜索支持,允许您查找所需的用户界面组件。
- 过滤元素的树形结构;例如,在查询元素层级时,我们可以仅获取启用的控件。
- 允许您与 UI 元素进行交互;例如,您可以从您的应用程序中以编程方式点击(一个包含在不同应用程序中的)按钮。
- 订阅事件;这有助于我们监视 UI 元素并处理外部事件。
UI 自动化 API
System.Windows.Automation
是 UI 自动化框架的主要命名空间,它提供了与 UI 元素(也称为 AutomationElement
)交互的支持。AutomationElement
是框架中的主要类,对应一个用户界面组件(窗口、列表、按钮等)。此命名空间的主要功能与搜索 AutomationElement
对象、与不同控件模式交互或订阅 UI 自动化事件相关。
AutomationElement
包含一个名为 RootElement
的属性,它包含对桌面对应 UI 元素的引用,该引用实际上返回一个 AutomationElement
。
关于搜索支持,AutomationElement
类包含 FindFirst()
和 FindAll()
方法。
public AutomationElement FindFirst(TreeScope scope, Condition condition)
我们可以使用 FindFirst
方法来搜索与传入的条件匹配的特定 AutomationElement
。为了调用此方法,我们需要传递搜索范围(TreeScope
枚举的实例),例如搜索子项的第一级,或搜索所有后代。除了 scope
参数,我们还必须传递用于识别所需 AutomationElement
的条件。我们将以扩展 Condition abstract
类的类的实例作为条件。这样,我们可以使用 PropertyCondition
(用于测试属性是否具有特定值),但也有:AndCondition
、NotCondition
或 OrCondition
类。
public AutomationElementCollection FindAll(TreeScope scope, Condition condition);
与 FindFirst
类似,FindAll()
允许我们使用上述参数查询 UI 自动化树,但返回一个 AutomationElement
集合,该集合通过了搜索条件。
基于上述细节,我们可以编写一行简单的代码,该代码将搜索根元素的所有后代,查找名称等于“Notepad”的 UI 元素。
AutomationElement appElement = AutomationElement.RootElement.FindFirst
(TreeScope.Descendants,new PropertyCondition(AutomationElement.NameProperty, "Notepad"))
实现
为了使用 UI 自动化 API,我们需要添加对以下程序集的引用:
- UIAutomationClient.dll
- UIAutomationTypes.dll
对于这个简单的实现,我使用了基类 AutomationElement
,正如我之前所说,它保留了桌面应用程序中 UI 元素的引用。关键在于,我们需要从桌面元素(即根元素 AutomationElement.RootElement
)开始,然后在 RootElement
的所有子对象中搜索标题为“UI Automation Test Window”的测试应用程序。在获得测试应用程序的 AutomationElement
的有效引用后,我们就可以与其中包含的各种控件进行交互了。这样,控制器应用程序将为两个 TextBox
控件设置一些值。
AutomationElement rootElement = AutomationElement.RootElement;
if (rootElement != null)
{
Automation.Condition condition = new PropertyCondition
(AutomationElement.NameProperty, "UI Automation Test Window");
AutomationElement appElement = rootElement.FindFirst(TreeScope.Children, condition);
if (appElement != null)
{
AutomationElement txtElementA = GetTextElement(appElement, "txtA");
if (txtElementA != null)
{
ValuePattern valuePatternA =
txtElementA.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
valuePatternA.SetValue("10");
}
AutomationElement txtElementB = GetTextElement(appElement, "txtB");
if (txtElementA != null)
{
ValuePattern valuePatternB =
txtElementB.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
valuePatternB.SetValue("5");
}
}
以下是 GetTextElement
函数:
private AutomationElement GetTextElement(AutomationElement parentElement, string value)
{
Automation.Condition condition =
new PropertyCondition(AutomationElement.AutomationIdProperty, value);
AutomationElement txtElement = parentElement.FindFirst
(TreeScope.Descendants, condition);
return txtElement;
}
如上面的代码所示,我们正在使用一个控件模式 ValuePattern
。UIA (UI Automation) 使用控件模式来表示常用控件。控件模式通过提供方法、事件和属性来定义控件中可用的特定功能。控件模式中声明的方法允许 UIA 客户端操作控件,例如 ValuePattern.SetValue()
方法。除了表示存储 string
值的控件的 ValuePattern
,作为另一个控件模式的示例,我们可以考虑 Invoke 模式控件 InvokePattern
,它表示可调用的控件,例如按钮。为了使用控件模式,我们需要查询对象以查看支持哪些接口,并且只有在获得有效的控件模式后,我们才能通过使用其方法、事件和属性与其进行交互。以下列表显示了最常见的控件模式:
SelectionPattern
- 用于支持选择的控件,例如ListBox
、ComboBox
TextPattern
- 用于编辑控件ValuePattern
- 用于在不支持多个值的控件上获取
/设置
值InvokePattern
- 用于可调用控件ScrollPattern
- 用于带有滚动条的控件RangeValuePattern
- 用于具有值范围的控件
下面的示例显示了如何使用 InvokePattern
;换句话说,它将点击 parentElement
中包含的按钮。
{
Automation.Condition condition = new PropertyCondition
(AutomationElement.AutomationIdProperty, "Button1");
AutomationElement btnElement = parentElement.FindFirst
(TreeScope.Descendants, condition);
InvokePattern btnPattern =
btnElement.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
btnPattern.Invoke();
}
结论
UI 自动化是一个强大的辅助功能框架,它允许您控制其他应用程序。它可以用于开发自动化 UI 测试/调试应用程序等。
关于这个主题,还有更多内容即将推出。
历史
- 2009 年 2 月 4 日:初始发布
- 2009 年 2 月 5 日:文章更新
- 2009 年 2 月 19 日:文章文本更新