UI 自动化和 Microsoft Active Accessibility
备注
本文档适用于想要使用 System.Windows.Automation 命名空间中定义的托管 UI 自动化类的 .NET Framework 开发人员。 有关 UI 自动化的最新信息,请参阅 Windows 自动化 API:UI 自动化。
Microsoft Active Accessibility 是使应用程序可访问的早期解决方案。 Microsoft UI Automation 是 Microsoft Windows 的新的可访问性模型,旨在满足对辅助技术产品和自动测试工具的需求。 与 Active Accessibility 相比,UI 自动化提供了很多改进。
本主题包括 UI 自动化的主要功能,并说明这些功能与 Active Accessibility 的不同之处。
编程语言
Active Accessibility 基于组件对象模型 (COM) 并支持双重接口,因此可采用 C/C++、Microsoft Visual Basic 6.0 和脚本语言进行编程。 UI 自动化(包括用于标准控件的客户端提供程序库)用托管代码编写,且 UI 自动化客户端应用程序可以使用 C# 或 Visual Basic .NET 轻松进行编程。 作为接口实现的 UI 自动化提供程序可以用托管代码或 C/C++ 编写。
Windows Presentation Foundation 中的支持
Windows Presentation Foundation (WPF) 是用于创建用户界面的新模型。 WPF 元素不包含对 Active Accessibility 的本机支持;但是,它们支持 UI 自动化,这包括对 Active Accessibility 客户端的桥接支持。 只有专门为 UI 自动化编写的客户端才可以充分利用 WPF 的辅助功能,例如对文本的丰富支持。
服务器和客户端
在 Active Accessibility 中,服务器和客户端主要通过服务器的 IAccessible
实现进行直接通信。
在 UI 自动化中,核心服务位于服务器(称为提供程序)和客户端之间。 核心服务对由提供程序实现的接口进行调用并提供其他服务,例如,为元素生成唯一的运行时标识符。 客户端应用程序使用库函数来调用 UI 自动化服务。
UI 自动化提供程序可以将信息提供给 Active Accessibility 客户端,而 Active Accessibility 服务器可以将信息提供给 UI 自动化客户端应用程序。 但是,由于 Active Accessibility 公开的信息与 UI 自动化不一样多,因此这两个模型并不完全兼容。
UI 元素
Active Accessibility 以 IAccessible
接口或子标识符的形式呈现 UI 元素。 很难比较两个 IAccessible
指针来确定它们是否引用同一元素。
在 UI 自动化中,每个元素都表示为一个 AutomationElement 对象。 可通过使用相等运算符或 Equals 方法完成比较,这两种方法比较的都是元素的唯一运行时标识符。
树视图和导航
屏幕上的用户界面 (UI) 元素可以被视为树状结构,桌面作为根、应用程序窗口作为直接子项,而应用程序中的元素作为继承子项。
在 Active Accessibility 中,许多与最终用户不相关的自动化元素都公开在树中。 客户端应用程序需要查看所有元素以确定哪些元素是有意义的。
UI 自动化客户端应用程序通过筛选视图查看 UI。 该视图仅包含相关元素:向用户提供信息或实现交互的元素。 还提供了只包含控件元素和只包含内容元素的预定义视图;除此之外,应用程序还可以定义自定义视图。 UI 自动化简化了向用户描述 UI 和帮助用户与应用程序进行交互的任务。
Active Accessibility 中元素之间的导航可以是空间导航(例如,移动到存在于屏幕左侧的元素)、逻辑导航(例如,移动到下一菜单项或对话框中 Tab 键顺序的下一项)或分层导航(例如,移动到容器中的第一个子级,或者从子级移动到其父级)。 分层导航非常复杂,因为子元素并不总是实现 IAccessible
的对象。
在 UI 自动化中,所有 UI 元素都是支持相同基本功能的 AutomationElement 对象。 (从提供程序的角度来看,它们是实现继承自 IRawElementProviderSimple 的接口的对象。)导航主要是分层导航:从父级到子级,以及从同级到下一个同级。 (同级之间的导航具有一个逻辑元素,因为它可能遵照的是 Tab 键顺序。)通过使用 TreeWalker 类,你可以使用树的任何筛选视图从任何起点进行导航。 你还可以通过使用 FindFirst 和 FindAll导航到特定的子级或继承项;例如,很容易检索对话框中支持指定控件模式的所有元素。
UI 自动化中的导航与 Active Accessibility 中的导航更加一致。 某些元素(例如下拉列表和弹出窗口)在 Active Accessibility 树中出现两次,且从它们进行导航可能出现意外结果。 其实就是无法对 rebar 控件正确实现 Active Accessibility。 UI 自动化能够重排根目录并进行重新布置,因此可以在树的任何位置放置元素,不必考虑窗口所有者构建的层次结构。
角色和控件类型
Active Accessibility 使用 accRole
属性 (IAccessible::get_actRole
) 来检索 UI 中元素的角色说明,如 ROLE_SYSTEM_SLIDER 或 ROLE_SYSTEM_MENUITEM。 元素的角色是确定其可用功能的主要线索。 通过使用固定的方法(如 IAccessible::accSelect
和 IAccessible::accDoDefaultAction
)可实现与控件的交互。 客户端应用程序和 UI 之间的交互仅限于可通过 IAccessible
完成的交互。
与此相反,UI 自动化很大程度上会将元素的控件类型(由 ControlType 属性描述)与其预期的功能分离。 功能由通过实现其特殊化接口的提供程序支持的控件模式来确定。 可以结合控件模式来描述特定 UI 元素支持的完整功能集。 某些提供程序需要支持特定的控件模式;例如,复选框的提供程序必须支持 Toggle 控件模式。 其他提供程序需要支持一个或多个控件模式集;例如,一个按钮必须支持 Toggle 或 Invoke。 还有一些提供程序完全不支持任何控件模式;例如,不能移动、调整大小或停靠的窗格没有任何控件模式。
UI 自动化支持由 Custom 属性标识的自定义控件且可通过 LocalizedControlTypeProperty 属性描述。
下表显示 Active Accessibility 角色到 UI 自动化控件类型的映射。
Active Accessibility 角色 | UI 自动化控件类型 |
---|---|
ROLE_SYSTEM_PUSHBUTTON | Button |
ROLE_SYSTEM_CLIENT | 日历 |
ROLE_SYSTEM_CHECKBUTTON | 复选框 |
ROLE_SYSTEM_COMBOBOX | 组合框 |
ROLE_SYSTEM_CLIENT | 自定义 |
ROLE_SYSTEM_LIST | 数据网格 |
ROLE_SYSTEM_LISTITEM | 数据项 |
ROLE_SYSTEM_DOCUMENT | 文档 |
ROLE_SYSTEM_TEXT | 编辑 |
ROLE_SYSTEM_GROUPING | 组 |
ROLE_SYSTEM_LIST | 标头 |
ROLE_SYSTEM_COLUMNHEADER | 标头项 |
ROLE_SYSTEM_LINK | Hyperlink |
ROLE_SYSTEM_GRAPHIC | 映像 |
ROLE_SYSTEM_LIST | 列出 |
ROLE_SYSTEM_LISTITEM | 列表项 |
ROLE_SYSTEM_MENUPOPUP | 菜单 |
ROLE_SYSTEM_MENUBAR | 菜单栏 |
ROLE_SYSTEM_MENUITEM | Menu item |
ROLE_SYSTEM_PANE | 窗格 |
ROLE_SYSTEM_PROGRESSBAR | 进度条 |
ROLE_SYSTEM_RADIOBUTTON | 单选按钮 |
ROLE_SYSTEM_SCROLLBAR | 滚动条 |
ROLE_SYSTEM_SEPARATOR | Separator |
ROLE_SYSTEM_SLIDER | 滑块 |
ROLE_SYSTEM_SPINBUTTON | Spinner |
ROLE_SYSTEM_SPLITBUTTON | “拆分”按钮 |
ROLE_SYSTEM_STATUSBAR | 状态栏 |
ROLE_SYSTEM_PAGETABLIST | 选项卡 |
ROLE_SYSTEM_PAGETAB | 选项卡项 |
ROLE_SYSTEM_TABLE | 表 |
ROLE_SYSTEM_STATICTEXT | 文本 |
ROLE_SYSTEM_INDICATOR | Thumb |
ROLE_SYSTEM_TITLEBAR | 标题栏 |
ROLE_SYSTEM_TOOLBAR | 工具栏 |
ROLE_SYSTEM_TOOLTIP | ToolTip |
ROLE_SYSTEM_OUTLINE | 树 |
ROLE_SYSTEM_OUTLINEITEM | 树项 |
ROLE_SYSTEM_WINDOW | 窗口 |
有关不同控件类型的更多信息,请参阅 UI Automation Control Types。
状态和属性
在 Active Accessibility 中,元素支持一组通用的属性集,且某些属性(如 accState
)必须描述截然不同的事物,具体取决于元素的角色。 服务器必须实现可返回属性的 IAccessible
的所有方法,返回的属性甚至与该元素不相关。
UI 自动化定义更多属性,其中一些属性对应于 Active Accessibility 中的状态。 某些属性是所有元素共有的,但其他属性特定于控件类型和控件模式。 属性由唯一标识符进行区分,并且大多数属性都可通过使用单个方法 GetCurrentPropertyValue 或 GetCachedPropertyValue进行检索。 许多属性还可以轻松从 Current 和 Cached 属性访问器进行检索。
UI 自动化提供程序不需要实现不相关的属性,而可以只返回任何其不支持的属性的 null
值。 此外,UI 自动化核心服务可以从默认窗口提供程序获取一些属性,并且这些属性与提供程序显式实现的属性相合并。
除了支持更多属性外,UI 自动化通过允许使用单一跨进程调用检索多个属性来提供更好的性能。
下表显示了两个模型中属性之间的对应关系。
Active Accessibility 属性访问器 | UI 自动化属性 ID | 备注 |
---|---|---|
get_accKeyboardShortcut |
AccessKeyProperty 或 AcceleratorKeyProperty | 如果两者都存在,AccessKeyProperty 优先。 |
get_accName |
NameProperty | |
get_accRole |
ControlTypeProperty | 请参阅上表,了解角色到控件类型的映射。 |
get_accValue |
ValuePattern.ValueProperty RangeValuePattern.ValueProperty |
仅对支持 ValuePattern 或 RangeValuePattern 的控件类型有效。 RangeValue 值被规范化为 0-100,与 MSAA 行为保持一致。 值项使用一个字符串。 |
get_accHelp |
HelpTextProperty | |
accLocation |
BoundingRectangleProperty | |
get_accDescription |
在 UI 自动化中不支持 | accDescription 在 MSAA 内没有清晰的规范,这将导致提供程序在此属性中放置不同的信息片段。 |
get_accHelpTopic |
在 UI 自动化中不支持 |
下表显示哪些 UI 自动化属性对应于Active Accessibility 状态常量。
Active Accessibility 状态 | UI 自动化属性 | 是否触发状态更改? |
---|---|---|
STATE_SYSTEM_CHECKED | 对于复选框, ToggleStateProperty 对于单选按钮, IsSelectedProperty |
Y |
STATE_SYSTEM_COLLAPSED | ExpandCollapseState = Collapsed | Y |
STATE_SYSTEM_EXPANDED | ExpandCollapseState = Expanded 或 PartiallyExpanded | Y |
STATE_SYSTEM_FOCUSABLE | IsKeyboardFocusableProperty | N |
STATE_SYSTEM_FOCUSED | HasKeyboardFocusProperty | N |
STATE_SYSTEM_HASPOPUP | 针对菜单项的ExpandCollapsePattern | N |
STATE_SYSTEM_INVISIBLE | IsOffscreenProperty = True 且 GetClickablePoint 导致 NoClickablePointException | N |
STATE_SYSTEM_LINKED | ControlTypeProperty = Hyperlink |
N |
STATE_SYSTEM_MIXED | ToggleState = Indeterminate | N |
STATE_SYSTEM_MOVEABLE | CanMoveProperty | N |
STATE_SYSTEM_MUTLISELECTABLE | CanSelectMultipleProperty | N |
STATE_SYSTEM_OFFSCREEN | IsOffscreenProperty = True | N |
STATE_SYSTEM_PROTECTED | IsPasswordProperty | N |
STATE_SYSTEM_READONLY | RangeValuePattern.IsReadOnlyProperty 和 ValuePattern.IsReadOnlyProperty | N |
STATE_SYSTEM_SELECTABLE | 支持 SelectionItemPattern | N |
STATE_SYSTEM_SELECTED | IsSelectedProperty | N |
STATE_SYSTEM_SIZEABLE | CanResize | N |
STATE_SYSTEM_UNAVAILABLE | IsEnabledProperty | Y |
以下状态或者未由大多数 Active Accessibility 控件服务器实现,或者在 UI 自动化中没有等效项。
Active Accessibility 状态 | 备注 |
---|---|
STATE_SYSTEM_BUSY | 在 UI 自动化中不可用 |
STATE_SYSTEM_DEFAULT | 在 UI 自动化中不可用 |
STATE_SYSTEM_ANIMATED | 在 UI 自动化中不可用 |
STATE_SYSTEM_EXTSELECTABLE | 未通过 Active Accessibility 服务器广泛实现 |
STATE_SYSTEM_MARQUEED | 未通过 Active Accessibility 服务器广泛实现 |
STATE_SYSTEM_SELFVOICING | 未通过 Active Accessibility 服务器广泛实现 |
STATE_SYSTEM_TRAVERSED | 在 UI 自动化中不可用 |
STATE_SYSTEM_ALERT_HIGH | 未通过 Active Accessibility 服务器广泛实现 |
STATE_SYSTEM_ALERT_MEDIUM | 未通过 Active Accessibility 服务器广泛实现 |
STATE_SYSTEM_ALERT_LOW | 未通过 Active Accessibility 服务器广泛实现 |
STATE_SYSTEM_FLOATING | 未通过 Active Accessibility 服务器广泛实现 |
STATE_SYSTEM_HOTTRACKED | 在 UI 自动化中不可用 |
STATE_SYSTEM_PRESSED | 在 UI 自动化中不可用 |
有关 UI 自动化属性标识符的完整列表,请参阅 UI 自动化属性概述。
事件
与 Active Accessibility 不同,UI 自动化中的事件机制不依赖于 Windows 事件路由(使用窗口句柄紧密连接)且不需要客户端应用程序来设置挂钩。 可以对事件订阅进行微调,不仅能订阅特定事件,甚至还能订阅树的特定部分。 通过跟踪所侦听的事件,提供程序也可微调其事件的引发。
对于客户端来说检索引发事件的元素也很简单,因为这些事件会被直接传递到事件回调。 如果在客户端订阅该事件时,缓存请求处于活动状态,则会自动预提取元素的属性。
下表显示了 Active Accessibility WinEvents 与 UI 自动化事件对应。
WinEvent | UI 自动化事件标识符 |
---|---|
EVENT_OBJECT_ACCELERATORCHANGE | AcceleratorKeyProperty 属性更改 |
EVENT_OBJECT_CONTENTSCROLLED | 相关联的滚动条上的 或 属性更改 |
EVENT_OBJECT_CREATE | StructureChangedEvent |
EVENT_OBJECT_DEFACTIONCHANGE | 无等效项 |
EVENT_OBJECT_DESCRIPTIONCHANGE | 没有确切的等效项;也许 HelpTextProperty 或 LocalizedControlTypeProperty 属性更改 |
EVENT_OBJECT_DESTROY | StructureChangedEvent |
EVENT_OBJECT_FOCUS | AutomationFocusChangedEvent |
EVENT_OBJECT_HELPCHANGE | HelpTextProperty 已更改 |
EVENT_OBJECT_HIDE | StructureChangedEvent |
EVENT_OBJECT_LOCATIONCHANGE | BoundingRectangleProperty 属性更改 |
EVENT_OBJECT_NAMECHANGE | NameProperty 属性更改 |
EVENT_OBJECT_PARENTCHANGE | StructureChangedEvent |
EVENT_OBJECT_REORDER | 在 Active Accessibility 中使用不一致。 在 UI 自动化中没有定义直接对应的事件。 |
EVENT_OBJECT_SELECTION | ElementSelectedEvent |
EVENT_OBJECT_SELECTIONADD | ElementAddedToSelectionEvent |
EVENT_OBJECT_SELECTIONREMOVE | ElementRemovedFromSelectionEvent |
EVENT_OBJECT_SELECTIONWITHIN | 无等效项 |
EVENT_OBJECT_SHOW | StructureChangedEvent |
EVENT_OBJECT_STATECHANGE | 各种属性更改事件 |
EVENT_OBJECT_VALUECHANGE | RangeValuePattern.ValueProperty 和 ValuePattern.ValueProperty 已更改 |
EVENT_SYSTEM_ALERT | 无等效项 |
EVENT_SYSTEM_CAPTUREEND | 无等效项 |
EVENT_SYSTEM_CAPTURESTART | 无等效项 |
EVENT_SYSTEM_CONTEXTHELPEND | 无等效项 |
EVENT_SYSTEM_CONTEXTHELPSTART | 无等效项 |
EVENT_SYSTEM_DIALOGEND | WindowClosedEvent |
EVENT_SYSTEM_DIALOGSTART | WindowOpenedEvent |
EVENT_SYSTEM_DRAGDROPEND | 无等效项 |
EVENT_SYSTEM_DRAGDROPSTART | 无等效项 |
EVENT_SYSTEM_FOREGROUND | AutomationFocusChangedEvent |
EVENT_SYSTEM_MENUEND | MenuClosedEvent |
EVENT_SYSTEM_MENUPOPUPEND | MenuClosedEvent |
EVENT_SYSTEM_MENUPOPUPSTART | MenuOpenedEvent |
EVENT_SYSTEM_MENUSTART | MenuOpenedEvent |
EVENT_SYSTEM_MINIMIZEEND | WindowVisualStateProperty 属性更改 |
EVENT_SYSTEM_MINIMIZESTART | WindowVisualStateProperty 属性更改 |
EVENT_SYSTEM_MOVESIZEEND | BoundingRectangleProperty 属性更改 |
EVENT_SYSTEM_MOVESIZESTART | BoundingRectangleProperty 属性更改 |
EVENT_SYSTEM_SCROLLINGEND | VerticalScrollPercentProperty 或 HorizontalScrollPercentProperty 属性更改 |
EVENT_SYSTEM_SCROLLINGSTART | VerticalScrollPercentProperty 或 HorizontalScrollPercentProperty 属性更改 |
EVENT_SYSTEM_SOUND | 无等效项 |
EVENT_SYSTEM_SWITCHEND | 没有等效项,但 AutomationFocusChangedEvent 事件表示新的应用程序已收到焦点 |
EVENT_SYSTEM_SWITCHSTART | 无等效项 |
无等效项 | CurrentViewProperty 属性更改 |
无等效项 | HorizontallyScrollableProperty 属性更改 |
无等效项 | VerticallyScrollableProperty 属性更改 |
无等效项 | HorizontalScrollPercentProperty 属性更改 |
无等效项 | VerticalScrollPercentProperty 属性更改 |
无等效项 | HorizontalViewSizeProperty 属性更改 |
无等效项 | VerticalViewSizeProperty 属性更改 |
无等效项 | ToggleStateProperty 属性更改 |
无等效项 | WindowVisualStateProperty 属性更改 |
无等效项 | AsyncContentLoadedEvent 事件 |
无等效项 | ToolTipOpenedEvent |
安全性
某些 IAccessible
自定义应用场景需要包装一个基本 IAccessible
并对其调用。 这具有安全隐患,因为部分受信任的组件不应为代码路径上的中介。
UI 自动化模型使提供程序不再需要通过其他提供程序代码调用。 UI 自动化核心服务将进行所有必要的聚合。