Text 和 TextRange 控件模式
介绍实现 ITextProvider、ITextProvider2 和 ITextRangeProvider 的准则和约定,包括有关属性和方法的信息。 文本控件模式使应用程序和控件能够公开简单的文本对象模型,使客户端能够从基于文本的控件中检索文本内容、文本属性和嵌入对象。
为了支持 文本 控件模式,控件实现 ITextProvider 和 ITextProvider2 接口。 应支持 Text 控件模式的控件类型包括 “编辑” 和“ 文档” 控件类型,以及允许用户输入文本或选择只读文本的任何其他控件类型。
文本控件模式可以与其他 Microsoft UI 自动化控件模式一起使用,以支持文本中的多种类型的嵌入对象,包括表、超链接和命令按钮。
ITextProvider 和 ITextProvider2 接口包含许多用于获取文本范围的方法。 文本范围是一个对象,它表示文本容器中连续的文本跨度或多个不连续的文本范围。 一个 ITextProvider 方法获取表示整个文档的文本范围,而其他方法获取表示文档某些部分(例如所选文本、可见文本或嵌入在文本中的对象)的文本范围。
文本范围对象由 TextRange 控件模式表示,该模式通过 ITextRangeProvider 接口实现。 TextRange 控件模式提供方法和属性,用于公开有关区域中文本的信息、移动范围的终结点、选择或取消选择文本、将范围滚动到视图中等。
有关 Text 和 TextRange 控件模式的详细信息,请参阅UI 自动化支持文本内容。
从Windows 8.1提供程序可以实现 ITextRangeProvider2 接口。 这样就可以调用与文本区域关联的上下文菜单。 这支持文本自动更正或输入法编辑器 (输入法) 候选选择等方案。
本主题包含以下各节:
实现准则和约定
实现 文本 控件模式时,请注意以下准则和约定:
- 允许访问文本的任何控件 (例如输入文本或选择只读文本) 应支持 Text 控件模式。
- Text 控件模式可以与任何显示文本的 UI 元素一起使用,甚至是标准按钮控件上的静态标签。 但是,对于无法选择或没有插入点的静态文本控件,这不是必需的。
- 为了确保文本完全可访问,实现 ITextProvider 的 控件还应支持 IValueProvider 接口。 IValueProvider 通过提供一种编程方式更改文本来补充 ITextProvider 。 它还提供与辅助技术客户端应用程序(包括基于旧技术(如 Microsoft Active Accessibility)的应用程序的更高兼容性。 实现这两种控件模式后, TextChanged 事件 (UIA_Text_TextChangedEventId) 和 AutomationPropertyChanged 事件 (UIA_AutomationPropertyChangedEventId) 等效于 Value 属性 (UIA_ValueValuePropertyId) 。 必须支持这两个事件。
- 文本控件模式仅支持一个文本流和每个控件的一个视区。 如果应用程序在窗格中提供多个文档视图,则每个视图 (控件) 应独立支持 ITextProvider 。
- ITextProvider::GetSelection 方法可能会返回表示当前所选文本的单个文本范围。 如果控件支持选择多个非连续文本范围, 则 GetSelection 方法应返回一个数组,其中包含每个所选文本范围的 一个 ITextRangeProvider 接口。
- Text 控件模式将插入点表示为文本范围) 空 (退化的插入点。 当插入点存在且未选择任何文本时 ,ITextProvider::GetSelection 方法应返回退化的文本范围。 有关详细信息,请参阅 与系统插入点的互操作性。
- 如果连续的文本范围在视区中可见, ITextProvider::GetVisibleRanges 方法可能会返回单个文本范围,也可能返回表示多行部分可见文本的不连续文本范围的数组。
- 如果子元素不包含任何文本, 则 ITextProvid::RangeFromChild 方法应返回退化的范围。 由于嵌入对象可以包含文本, RangeFromChild 方法可能并不总是返回退化的文本范围。 有关详细信息,请参阅 UI 自动化如何公开嵌入对象。
- ITextProvider::RangeFromPoint 方法使用指定的屏幕坐标在文档区域中执行命中测试。 生成的文本范围应与通过单击指定屏幕坐标处的位置产生的插入点或所选内容保持一致。 例如,如果图像驻留在指定的屏幕坐标处,则生成的文本范围应与 ITextProvider::RangeFromChild 方法为图像获取的文本范围相同。 同样,如果客户端应用程序请求插入点 (插入点) 的系统插入点中心位置的文本范围,则生成的文本范围应与系统插入点位置相同。
- ITextProvider::D ocumentRange 属性应始终提供包含相应 ITextProvider 实现支持的所有文本的文本范围。
- 发生任何文本更改后,必须引发 UIA_Text_TextChangedEventId 事件,即使更改在视区中不可见也是如此。 例如,即使用户将完全相同的文本粘贴到所选文本上,提供程序也应引发 事件。
- 每当文本选择发生更改或插入点 (插入点) 文本之间移动时 ,都必须引发 UIA_Text_TextSelectionChangedEventId。
实现 TextRange 控件模式时,请注意以下准则和约定:
- TextRange 控件模式的所有方法都应执行文本操作,而不考虑文本的可见性状态。 始终可以通过查询 IsHidden 文本属性 (UIA_IsHiddenAttributeId) 来确定 文本范围的可见性。
- 如果可能,提供程序应确保任何文本更改(如删除、插入和移动)反映在 ITextRangeProvider 接口 (实例的关联文本范围对象) 并引发 UIA_Text_TextChangedEventId 事件。 客户端可以使用 事件作为提示来确认对控件文本所做的编辑更改。
- ITextRangeProvider::Compare、CompareEndpoints 和 MoveEndpointByRange 方法使用的所有文本范围对象都必须是同一 Text 控件模式实现的对等方。
- 虽然不是必需的,但 ITextRangeProvider::CompareEndpoints 方法检索的 pRetVal 值可以指示两个终结点之间的距离(以字符 (TextUnit_Character) 为单位)。 但是,客户端应用程序不应依赖于 pRetVal 的准确度超过其正值或负值。
- ITextRangeProvider::ExpandToEnclosingUnit、Move 和 MoveEndpointByUnit 方法需要仔细考虑指定的文本单元。 有关详细信息,请参阅按文本单元操作 TextRange。
- 有关 与 ITextRangeProvider::Select、 AddToSelection 和 RemoveFromSelection 方法相关的实现要求,请参阅在文本范围内选择文本。
- ITextRangeProvider::FindText 和 FindAttribute 方法可向前或向后搜索单个匹配文本字符串或文本属性。 如果未找到匹配项,它们应返回 NULL 。
- ITextRangeProvider::GetAttributeValue 方法必须返回从 UiaGetReservedMixedAttributeValue 或 UiaGetReservedNotSupportedValue 函数获取的地址,前提是关联属性在范围中不同,或者如果属性不受文本控件支持。 TextRange 控件模式规范不允许添加新的文本属性标识符或更改现有属性的定义方式。
- 如果可能, ITextRangeProvider::GetBoundingRectangles 方法应返回一个数组,该数组包含文本范围中每个完全或部分可见的文本行的一个边框。 如果这不可行,提供程序可以返回一个数组,该数组仅包含完全可见线条的边框;但是,这限制了客户端应用程序准确描述文本在屏幕上显示方式的能力。
- ITextRangeProvider::GetChildren 方法应返回嵌入在文本范围中的所有子元素,但它不需要返回子元素的任何子元素。 例如,如果文本区域包含具有多个子单元格的表, 则 GetChildren 方法可能仅返回 table 元素,而不返回单元格元素。 出于性能或体系结构原因,提供程序可能无法公开自动化树文档中托管的所有嵌入对象。 在这种情况下,提供程序应至少支持通过 GetChildren 方法枚举子对象,并且作为选项,支持 虚拟化支持的 VirtualizedItem 控件模式。
- ITextRangeProvider::GetEnclosingElement 方法通常返回提供文本范围的文本提供程序。 但是,如果文本提供程序支持子对象(如表或超链接),则封闭元素可以是文本提供程序的后代。 GetEnclosingElement 返回的元素应该是最接近给定文本范围的元素。 例如,如果文本区域位于表格的单元格中, 则 GetEnclosingElement 应返回包含单元格而不是 table 元素。
- ITextRangeProvider::GetText 方法应返回区域中的纯文本。 有关详细信息,请参阅从文本范围获取文本。
- 调用 ITextRangeProvider::ScrollIntoView 应对齐 由 alignToTop 参数指定的文本控件视区中的文本。 尽管在水平对齐方面没有要求,但文本范围应该在水平和垂直方向上都可见。 评估 alignToTop 参数时,提供程序必须考虑文本控件的方向和文本的流方向。 例如,如果 alignToTop 对于包含从右到左流动的文本的垂直方向文本控件为 TRUE ,则提供程序应将文本范围与视区的右侧对齐。
- 按 TextUnit_Line在文档中移动时,如果文本区域进入嵌入表格,单元格中的每一行文本都应被视为一行。
ITextProvider 的必需成员
实现 ITextProvider 接口需要以下属性和方法。
必需的成员 | 成员类型 | 说明 |
---|---|---|
DocumentRange | 属性 | 无 |
SupportedTextSelection | 属性 | 无 |
GetSelection | 方法 | 无 |
GetVisibleRanges | 方法 | 无 |
RangeFromChild | 方法 | 无 |
RangeFromPoint | 方法 | 无 |
UIA_Text_TextChangedEventId | 事件 | 无 |
UIA_Text_TextSelectionChangedEventId | 事件 | 无 |
实现 ITextProvider2 接口需要以下附加属性和方法。
必需的成员 | 成员类型 | 说明 |
---|---|---|
GetCaretRange | 方法 | 无 |
RangeFromAnnotation | 方法 | 无 |
ITextRangeProvider 的必需成员
实现 ITextRangeProvider 接口需要以下属性和方法。
必需的成员 | 成员类型 | 说明 |
---|---|---|
AddToSelection | 方法 | 无 |
克隆 | 方法 | 无 |
比较 | 方法 | 无 |
CompareEndpoints | 方法 | 无 |
ExpandToEnclosingUnit | 方法 | 无 |
FindAttribute | 方法 | 无 |
FindText | 方法 | 无 |
GetAttributeValue | 方法 | 无 |
GetBoundingRectangles | 方法 | 无 |
GetChildren | 方法 | 无 |
GetEnclosingElement | 方法 | 无 |
GetText | 方法 | 无 |
移动 | 方法 | 无 |
MoveEndpointByUnit | 方法 | 无 |
MoveEndpointByRange | 方法 | 无 |
Select | 方法 | 无 |
ScrollIntoView | 方法 | 无 |
实现 ITextRangeProvider2 接口需要以下附加属性和方法。
必需的成员 | 成员类型 | 说明 |
---|---|---|
显示上下文菜单 | 方法 | 请参阅“实现 ShowContextMenu”部分 |
TextRange 控件模式没有关联的事件。
支持文本范围
本部分介绍提供程序应如何实现 ITextRangeProvider 和 ITextRangeProvider2 接口的各种方法以支持 TextRange 控件模式。
按文本单位操作文本范围
ITextRangeProvider 接口提供了多种方法,用于在基于文本的控件中操作和导航文本范围。 ITextRangeProvider::Move、MoveEndpointByUnit 和 ExpandToEnclosingUnit 方法按指定的文本单位(如字符、字、段落等)移动文本范围或其终结点之一。 有关详细信息,请参阅UI 自动化文本单位。
尽管其名称为 ITextRangeProvider::ExpandToEnclosingUnit 方法不一定扩展文本范围。 相反,它通过移动终结点使文本范围包含指定的文本单位来“规范化”文本范围。 如果范围小于指定的单位,则扩大;如果范围长于指定单位,则缩短范围。 ExpandToEnclosingUnit 方法始终以一致的方式规范化文本范围至关重要:否则,文本单元的文本范围操作的其他方面将是不可预知的。 下图显示了 ExpandToEnclosingUnit 如何通过移动范围的终结点来规范化文本范围。
如果文本范围从文本单元的开头开始,到下一个文本单元边界的开头或之前结束,则结束终结点将移动到下一个文本单元边界, (上图) 中看到 1 和 2。
如果文本范围从文本单元的开头开始,到下一个单元边界结束或之后结束,则结束终结点将保留或向后移动到下一个单位边界后,起始端点 (上图) 中所示的 3 和 4。 如果起始终结点和结束终结点之间有多个文本单元边界,则结束终结点将向后移动到起始终结点之后的下一个单元边界,从而产生长度为一个文本单位的文本范围。
如果文本范围从文本单元的中间开始,则起始终结点向后移动到文本单元的开头,并根据需要向前或向后移动结束终结点,在起始终结点 (在上图) 中看到 5 到 8。
调用 ITextRangeProvider::Move 方法时,提供程序使用与 ExpandToEnclosingUnit 方法相同的规范化逻辑,按指定的文本单位规范化文本范围。 然后,提供程序按指定的文本单位数向后或向前移动范围。 移动范围时,提供程序应忽略文本中任何嵌入对象的边界。 (但是,单元边界本身可能会受到嵌入对象) 的存在的影响。 下图演示 了 Move 方法如何跨嵌入的对象和文本单元边界逐个移动文本范围。
ITextRangeProvider::MoveEndpointByUnit 方法按指定的文本单位向前或向后移动其中一个终结点,如下图所示。
ITextRangeProvider::MoveEndpointByRange 方法使客户端应用程序能够将文本范围的一个终结点设置为与第二个文本范围的指定终结点相同的位置。
在文本范围内选择文本
ITextRangeProvider 接口包括多种用于控制基于文本的控件中的文本选择的方法。
ITextRangeProvider::Select 方法应选择与文本范围对应的文本,并从文本控件中删除之前的选定内容(如果有)。 如果在退化的文本区域上调用 了 Select ,提供程序应将插入点移动到文本区域的位置,而不选择任何文本。
如果控件支持选择多个不连续的文本范围, 则 ITextRangeProvider::AddToSelection 和 RemoveFromSelection 方法会将文本范围添加到所选文本范围的集合并将其从中删除。 如果控件一次仅支持一个选定的文本范围,但选择操作将导致选择多个不连续文本范围,则提供程序应返回 E_INVALIDOPERATION 错误,或者应扩展或截断当前所选内容。 ITextProvider::SupportedTextSelection 属性应指示控件是支持选择单个或多个文本范围,还是根本不支持选择文本。
如果基于文本的控件支持文本插入,则对控件中退化的文本范围调用 ITextRangeProvider::AddToSelection 或 RemoveFromSelection 应移动插入点,但不应选择任何文本。
从文本范围获取文本
ITextRangeProvider::GetText 方法应返回文本范围的纯文本。 纯文本应包括源文本中找到的所有控制字符,例如回车符和 Unicode 从左到右标记 (LRM) 。 纯文本不应包含源文本中可能存在的任何标记,例如 HTML。 此外,源文本中的任何转义代码都应转换为纯文本等效项。 例如,应将“”“转换为简单空格字符。
如果嵌入对象跨越一系列文本,则纯文本应包含该对象的内部文本,但不能包含嵌入对象) 的 name 属性 (可选文字,因为它可能与描述性内部文本不一致。 有关详细信息,请参阅 UI 自动化如何公开嵌入对象。
实现 ShowContextMenu
ITextRangeProvider2::ShowContextMenu 应始终在范围的起点显示上下文菜单。 这应该等效于当用户按下上下文菜单键或 SHIFT + F10 时,插入点位于范围开头时会发生的情况。
如果显示上下文菜单通常会导致插入点移动到给定位置,则它应该通过编程方式调用 ShowContextMenu 以获取UI 自动化支持。
与系统插入点的互操作性
正确支持插入点对许多客户端应用程序至关重要,包括那些不基于UI 自动化的应用程序。 在 文本 控件模式中,插入点由系统插入点位置处的退化 (空) 文本范围表示。 当插入点移动时,控件应引发 TextSelectionChanged 事件 (UIA_Text_TextSelectionChangedEventId) 。 某些客户端应用程序依赖于此事件来监视插入点的位置,并跟踪文本选择。
当控件包含所选文本时, 文本 控件模式的当前设计不提供将插入点的位置与特定文本范围直接关联的方法。 提供程序必须跟踪文本选择,并相应地设置插入点的位置。 由于选择文本通常是通过在按住 SHIFT 键或 CTRL 键的同时移动插入点来完成的,因此提供程序可以通过在选择更改时检查这些键的状态来跟踪文本选择。
由于辅助功能框架为系统插入点提供内置支持,但不提供对自定义插入点的内置支持,因此基于文本的控件应尽可能使用系统插入点。 使用自定义插入点的控件可以通过创建尺寸与自定义插入点相同的系统插入点,并将系统插入点定位在控件 UI 中与自定义插入点相同的位置(即插入点)来确保插入点可访问插入点。 作为替代方法,使用自定义插入点的控件可以实现适用于 OBJID_CARET 的 Microsoft Active Accessibility 提供程序,以便直接为自定义插入点提供辅助功能信息。
有关系统插入符号的详细信息,请参阅 插入符号。
若要测试控件是否正确公开了系统插入点的位置,请使用 检查 和 可访问的事件观察程序 工具。
系统插入点位图中心的屏幕坐标应始终与插入点的位置匹配。 这样,客户端就可以在调用 ITextProvider::RangeFromPoint 时使用插入点屏幕坐标来检索准确表示插入点位置的文本范围。
相关主题