服务器自动化程序,服务器端 UI 自动化提供程序的实现

服务器端 UI 自动化提供程序的实现

09/04/2008

本文内容

更新:2007 年 11 月

本节介绍如何为自定义控件实现服务器端 UI 自动化提供程序。

Windows Presentation Foundation (WPF) 元素和非 WPF 元素(如专为 Windows 窗体设计的元素)的实现有着根本的不同。WPF 元素通过从 AutomationPeer 派生的类提供对 UI 自动化的支持。而非 WPF 元素通过提供程序接口的实现来提供支持。

本主题包括下列各节。

安全注意事项

Windows Presentation Foundation 元素的提供程序实现

非 WPF 元素的提供程序实现

相关主题

安全注意事项

在编写提供程序时,应当使其可用于部分信任的环境。由于 UIAutomationClient.dll 未配置为在部分信任的环境下运行,因此提供程序代码不应当引用该程序集。如果引用,那么该代码或许能在完全信任的环境中运行,但不能在部分信任的环境中运行。

尤其不要使用 UIAutomationClient.dll 中类的字段,如 AutomationElement 中的字段。而应当使用 UIAutomationTypes.dll 中类的等效字段,如 AutomationElementIdentifiers。

Windows Presentation Foundation 元素的提供程序实现

非 WPF 元素的提供程序实现

不属于 WPF 框架、但采用托管代码编写的自定义控件(多数情况下为 Windows 窗体控件)通过实现接口来提供对 UI 自动化的支持。每个元素必须至少实现下一部分的第一个表中列出的接口之一。此外,如果该元素支持一个或多个控件模式,则它必须为每个控件模式实现相应的接口。

UI 自动化提供程序项目必须引用以下程序集:

UIAutomationProviders.dll

UIAutomationTypes.dll

WindowsBase.dll

本节包含下列子节。

提供程序接口

非 WPF 提供程序的要求

非 WPF 提供程序中的属性值

非 WPF 提供程序中的事件

非 WPF 提供程序导航

重新设置非 WPF 提供程序的父级

重新定位非 WPF 提供程序

提供程序接口

每个 UI 自动化提供程序必须实现下列接口之一。

以下接口可提供附加功能,但并不需要实现。

非 WPF 提供程序的要求

控件必须实现以下主要功能,才能与 UI 自动化通信:

功能

实现

向 UI 自动化公开提供程序

在响应发送到控件窗口的 WM_GETOBJECT 消息时,返回实现 IRawElementProviderSimple(或派生接口)的对象。对于片段,此对象必须是片段根元素的提供程序。

使客户端能与控件交互

引发事件

在片段中进行导航和设置焦点

为片段中的每个元素实现 IRawElementProviderFragment。(对于不属于片段的元素则不必实现。)

对片段中的子元素设置焦点和定位

非 WPF 提供程序中的属性值

自定义控件的 UI 自动化提供程序必须支持可供自动化系统和客户端应用程序使用的某些属性。对于窗口中承载的元素 (HWND),UI 自动化可以从默认的窗口提供程序中检索某些属性,但必须从自定义提供程序获取其他属性。

基于 HWND 的控件的提供程序通常不需要提供以下属性(由字段值标识):

0bccfc35e74eaedf0b3cde0a215a40a0.gif说明:

窗口中承载的简单元素或片段根元素的 RuntimeIdProperty 是从窗口中获取的,但根元素下的片段元素(如列表框中的列表项)必须提供自己的标识符。有关更多信息,请参见 GetRuntimeId。

应当为 Windows 窗体控件中承载的提供程序返回 IsKeyboardFocusableProperty。在这种情况下,默认的窗口提供程序可能无法检索正确的值。

NameProperty 通常由宿主提供程序提供。例如,如果自定义控件派生自 Control,那么该名称将派生自该控件的 Text 属性。

非 WPF 提供程序中的事件

UI 自动化提供程序应当引发事件,以通知客户端应用程序 UI 的状态发生变化。以下方法用于引发事件。

事件的目的是通知客户端用户界面 (UI) 中发生了某些变化,而无论活动是否由 UI 自动化系统自身触发。例如,只要调用控件(无论是通过用户直接输入还是通过客户端应用程序调用 Invoke),就应当引发由 InvokedEvent 标识的事件。

若要优化性能,提供程序可以有选择地引发事件,或者根本不引发事件(如果没有注册客户端应用程序以接收事件)。以下方法用于优化。

方法

说明

此静态属性指定是否有任何客户端应用程序已订阅 UI 自动化事件。

当客户端对片段注册或取消注册事件的事件处理程序时,片段根元素上此接口的提供程序使其可以收到通知。

非 WPF 提供程序导航

简单控件(如窗口中承载的自定义按钮 (HWND))的提供程序不需要支持 UI 自动化树中的导航。从该元素以及到该元素的导航由宿主窗口的默认提供程序处理,这一点在 HostRawElementProvider 的实现中指定。但是,在实现复杂自定义控件的提供程序时,必须支持片段的根节点与其子代,以及同级节点之间的导航。

0bccfc35e74eaedf0b3cde0a215a40a0.gif说明:

除根元素以外的片段元素必须从 HostRawElementProvider 返回 null 引用,因为这些元素并不直接承载于窗口中,没有默认的提供程序能支持从它们以及到它们的导航。

片段的结构由 Navigate 的实现确定。对于每个片段的每个可能方向,此方法都会为该方向上的元素返回提供程序对象。如果在该方向上没有元素,则此方法返回 null 引用。

片段根元素仅支持到子元素的导航。例如,如果方向为 FirstChild,则列表框返回列表中的第一项;如果方向为 LastChild,则返回列表中的最后一项。片段根元素不支持到父级或同级的导航,这由宿主窗口提供程序处理。

根元素以外的片段元素必须支持父级、所有同级及子级的导航。

重新设置非 WPF 提供程序的父级

弹出窗口实际上是顶级窗口,因此,默认情况下在 UI 自动化树中显示为桌面的子级。但是,在大多数情况下,弹出窗口逻辑上是其他某些控件的子级。例如,组合框的下拉列表逻辑上是组合框的子级。同样,菜单弹出窗口逻辑上是菜单的子级。UI 自动化支持重新设置弹出窗口的父级,以使其显示为相关控件的子级。

若要重新设置弹出窗口的父级,请执行以下操作:

为弹出窗口创建提供程序。这要求预先知道弹出窗口的类。

照常实现该弹出窗口的所有属性和模式,就好像它本身是一个控件一样。

实现弹出窗口及其父级的 Navigate,以便可以正确处理从逻辑父级到逻辑子级,以及同级子级之间的导航。

当 UI 自动化遇到弹出窗口时,可识别该重写了默认值的导航,并会在遇到作为桌面子级的弹出窗口时,跳过此弹出窗口。此节点只能通过片段到达。

当控件能承载任何类的窗口时,不适合重新设置父级。例如,rebar 能在其带区内承载任何类型的 HWND。为处理这种情况,UI 自动化支持备用形式的 HWND 重定位,如下一部分所述。

重新定位非 WPF 提供程序

UI 自动化片段可以包含两个或更多个包含在窗口中的元素 (HWND)。因为每个 HWND 都有自己的默认提供程序(将 HWND 视为包含 HWND 的子级),所以默认情况下 UI 自动化树将片段中的 HWND 显示为父窗口的子级。在大多数情况下,此行为都很恰当,但有时会导致混乱,因为它与 UI 的逻辑结构不匹配。

rebar 控件就是一个很好的示例。rebar 控件包含带区,每个带区又可以包含基于 HWND 的控件,如工具栏、编辑框或组合框。rebar HWND 的默认窗口提供程序将带区控件 HWND 视为子级,rebar 提供程序将带区视为子级。因为 HWND 提供程序和 rebar 提供程序先后运行,并组成其子级,所以带区和基于 HWND 的控件都显示为 rebar 的子级。但是,逻辑上只有带区应当显示为 rebar 的子级,并且每个带区提供程序应与它所包含控件的默认 HWND 提供程序结合使用。

为此,rebar 的片段根元素提供程序公开一组表示带区的子级。每个带区都有一个可以公开属性和模式的提供程序。在其 HostRawElementProvider 实现中,带区提供程序通过调用 HostProviderFromHandle 并在控件的窗口句柄中传递,来获取并返回控件 HWND 的默认窗口提供程序。最后,rebar 的片段根元素提供程序实现 IRawElementProviderHwndOverride 接口,并在其 GetOverrideProviderForHwnd 实现中,返回指定的 HWND 中所包含控件的相应带区提供程序。

请参见

任务

概念

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值