自定义文本输入Custom text input

Windows.UI.Text.Core 命名空间中的核心文本 API 支持通用 Windows 平台 (UWP) 应用通过 Windows 设备上受支持的任何文本服务接收文本输入。The core text APIs in the Windows.UI.Text.Core namespace enable a Universal Windows Platform (UWP) app to receive text input from any text service supported on Windows devices. 该 API 类似于文本服务框架 API,因此应用不需要详细了解该文本服务。The APIs are similar to the Text Services Framework APIs in that the app is not required to have detailed knowledge of the text services. 这使应用接收的文本可以是任何语言以及来自任何输入类型,例如键盘、语音或笔。This enables the app to receive text in any language and from any input type, like keyboard, speech, or pen.

重要 APIWindows.UI.Text.CoreCoreTextEditContextImportant APIs: Windows.UI.Text.Core, CoreTextEditContext

为什么使用核心文本 API?Why use core text APIs?

对于许多应用而言,XAML 或 HTML 文本框控件对于文本输入和编辑已够用。For many apps, the XAML or HTML text box controls are sufficient for text input and editing. 然而,如果你的应用需要处理复杂文本方案(如字处理应用),你可能需要自定义文本编辑控件的灵活性。However, if your app handles complex text scenarios, like a word processing app, you might need the flexibility of a custom text edit control. 你可以使用 CoreWindow 键盘 API 来创建你的文本编辑控件,但是这些控件无法提供某种方式来接收基于合成的文本输入(它需要支持东亚语言)。You could use the CoreWindow keyboard APIs to create your text edit control, but these don't provide a way to receive composition-based text input, which is required to support East Asian languages.

在你需要创建自定义文本编辑控件时,请改用 Windows.UI.Text.Core API。Instead, use the Windows.UI.Text.Core APIs when you need to create a custom text edit control. 这些 API 旨在向你提供处理文本输入时以及在任何语言方面的大量灵活性,并提供最适合你的应用的文本体验。These APIs are designed to give you a lot of flexibility in processing text input, in any language, and let you provide the text experience best suited to your app. 使用核心文本 API 生成的文本输入和编辑控件可以接收来自 Windows 设备上的所有现有文本输入法的文本输入,从电脑上基于文本服务框架的输入法编辑器 (IME) 和手写输入到移动设备上的 WordFlow 键盘(该键盘可以提供自动更正、预测和听写)。Text input and edit controls built with the core text APIs can receive text input from all existing text input methods on Windows devices, from Text Services Framework based Input Method Editors (IMEs) and handwriting on PCs to the WordFlow keyboard (which provides auto-correction, prediction, and dictation) on mobile devices.

体系结构Architecture

下面简单介绍了文本输入系统。The following is a simple representation of the text input system.

  • “应用程序”表示托管使用核心文本 API 生成的自定义编辑控件的 UWP 应用。"Application" represents a UWP app hosting a custom edit control built using the core text APIs.
  • Windows.UI.Text.Core API 有助于通过 Windows 与文本服务进行通信。The Windows.UI.Text.Core APIs facilitate the communication with text services through Windows. 文本编辑控件和文本服务之间的通信主要通过 CoreTextEditContext 对象进行处理,该对象提供的方法和事件有利于通信。Communication between the text edit control and the text services is handled primarily through a CoreTextEditContext object that provides the methods and events to facilitate the communication.

核心文本体系结构图示

文本范围和选择Text ranges and selection

编辑控件提供的空间可用于文本输入,并且用户可在此空间的任意位置编辑文本。Edit controls provide space for text entry and users expect to edit text anywhere in this space. 我们将在此处介绍核心文本 API 所使用的文本定位系统,以及范围和选定在此系统中的表示方式。Here, we explain the text positioning system used by the core text APIs and how ranges and selections are represented in this system.

应用程序插入光标位置Application caret position

与核心文本 API 一起使用的文本范围以插入光标位置的形式表示。Text ranges used with the core text APIs are expressed in terms of caret positions. “应用程序插入光标位置 (ACP)”是从零开始的数字,表示紧接插入光标前的文本流从头开始算起的字符数,如下面所示。An "Application Caret Position (ACP)" is a zero-based number that indicates the count of characters from the start of the text stream immediately before the caret, as shown here.

示例文本流图示

文本范围和选择Text ranges and selection

文本范围和选择由包含两个字段的 CoreTextRange 结构表示:Text ranges and selections are represented by the CoreTextRange structure which contains two fields:

字段Field 数据类型Data type 说明Description
StartCaretPositionStartCaretPosition Number [JavaScript]Number [JavaScript] System.Int32 [.NET]System.Int32 [.NET]
EndCaretPositionEndCaretPosition Number [JavaScript]Number [JavaScript] System.Int32 [.NET]System.Int32 [.NET]

例如,在前面显示的文本范围中,范围 [0, 5] 可指定单词 “Hello”。For example, in the text range shown previously, the range [0, 5] specifies the word "Hello". StartCaretPosition 必须始终小于或等于 EndCaretPositionStartCaretPosition must always be less than or equal to the EndCaretPosition. 范围 [5, 0] 无效。The range [5, 0] is invalid.

插入点Insertion point

通常称为插入点的当前插入光标位置通过将 StartCaretPosition 设置为等于 EndCaretPosition 来表示。The current caret position, frequently referred to as the insertion point, is represented by setting the StartCaretPosition to be equal to the EndCaretPosition.

非连续选择Noncontiguous selection

一些编辑控件支持非连续选择。Some edit controls support noncontiguous selections. 例如,Microsoft Office 应用支持多个任意选择,并且许多源代码编辑器支持列选择。For example, Microsoft Office apps support multiple arbitrary selections, and many source code editors support column selection. 但是,核心文本 API 并不支持非连续选择。However, the core text APIs do not support noncontiguous selections. 编辑控件必须仅报告单个连续选择(通常是非连续选择的活动子范围)。Edit controls must report only a single contiguous selection, most often the active sub-range of the noncontiguous selections.

例如,考虑此文本流:For example, consider this text stream:

<span data-ttu-id="a0349-154">示例文本流图示 有两种选择:[0, 1] 和 [6, 11]。example text stream diagram](images/coretext/stream-2.png) There are two selections: [0, 1] and [6, 11]. 编辑控件必须仅报告其中一个选择:[0, 1] 或 [6, 11]。The edit control must report only one of them; either [0, 1] or [6, 11].

使用文本Working with text

CoreTextEditContext 类通过 TextUpdating 事件、TextRequested 事件和 NotifyTextChanged 方法支持 Windows 和编辑控件之间的文本流。The CoreTextEditContext class enables text flow between Windows and edit controls through the TextUpdating event, the TextRequested event, and the NotifyTextChanged method.

你的编辑控件通过 TextUpdating 事件接收文本,这些事件在用户与文本输入法(如键盘、语音或 IME)交互时生成。Your edit control receives text through TextUpdating events that are generated when users interact with text input methods like keyboards, speech, or IMEs.

当在你的编辑控件中更改文本时(例如,通过将文本粘贴到该控件中),需要通过调用 NotifyTextChanged 来通知 Windows。When you change text in your edit control, for example, by pasting text into the control, you need to notify Windows by calling NotifyTextChanged.

如果文本服务需要新的文本,将引发 TextRequested 事件。If the text service requires the new text, then a TextRequested event is raised. 必须在 TextRequested 事件处理程序中提供新的文本。You must provide the new text in the TextRequested event handler.

接受文本更新Accepting text updates

由于文本更新请求表示用户想要输入的文本,因此你的编辑控件通常应接受这些请求。Your edit control should typically accept text update requests because they represent the text the user wants to enter. TextUpdating 事件处理程序中,这些操作按你的编辑控件要求进行:In the TextUpdating event handler, these actions are expected of your edit control:

  1. CoreTextTextUpdatingEventArgs.Text 中指定的文本插入 CoreTextTextUpdatingEventArgs.Range 中指定的位置。Insert the text specified in CoreTextTextUpdatingEventArgs.Text in the position specified in CoreTextTextUpdatingEventArgs.Range.
  2. 将选定内容放置在 CoreTextTextUpdatingEventArgs.NewSelection 中指定的位置。Place selection at the position specified in CoreTextTextUpdatingEventArgs.NewSelection.
  3. 通知系统更新已成功,方法为将 CoreTextTextUpdatingEventArgs.Result 设置为 CoreTextTextUpdatingResult.SucceededNotify the system that the update succeeded by setting CoreTextTextUpdatingEventArgs.Result to CoreTextTextUpdatingResult.Succeeded.

例如,这是编辑控件在用户键入“d”之前的状态。For example, this is the state of an edit control before the user types "d". 该插入点位于 [10, 10]。The insertion point is at [10, 10].

<span data-ttu-id="a0349-170">示例文本流图示 当用户键入“d”时,将引发 TextUpdating 事件并带有以下 CoreTextTextUpdatingEventArgs](https://msdn.microsoft.com/library/windows/apps/dn958229) 数据:example text stream diagram When the user types "d", a TextUpdating event is raised with the following CoreTextTextUpdatingEventArgs data:

在你的编辑控件中,应用指定的更改并将 Result 设置为 SucceededIn your edit control, apply the specified changes and set Result to Succeeded. 下面是该控件在应用更改后的状态。Here's the state of the control after the changes are applied.

示例文本流图示

拒绝文本更新Rejecting text updates

由于请求的范围是不应进行更改的编辑控件区域,因此有时无法应用文本更新。Sometimes, you cannot apply text updates because the requested range is in an area of the edit control that should not be changed. 在这种情况下,不应该应用任何更改。In this case, you should not apply any changes. 相反,应通知系统更新失败,方法为将 CoreTextTextUpdatingEventArgs.Result 设置为 CoreTextTextUpdatingResult.FailedInstead, notify the system that the update failed by setting CoreTextTextUpdatingEventArgs.Result to CoreTextTextUpdatingResult.Failed.

例如,请考虑只接受电子邮件地址的编辑控件。For example, consider an edit control that accepts only an e-mail address. 由于电子邮件地址不能含有空格,因此应拒绝空格;以便在针对空格键引发 TextUpdating 事件时,只需在你的编辑控件中将 Result 设置为 FailedSpaces should be rejected because e-mail addresses cannot contain spaces, so when TextUpdating events are raised for the space key, you should simply set Result to Failed in your edit control.

通知文本更改Notifying text changes

有时,你的编辑控件会对文本进行更改,例如在粘贴或自动更正文本时。Sometimes, your edit control makes changes to text such as when text is pasted or auto-corrected. 在这些情况下,必须通过调用 NotifyTextChanged 方法向文本服务通知这些更改。In these cases, you must notify the text services of these changes by calling the NotifyTextChanged method.

例如,这是编辑控件在用户粘贴“World”之前的状态。For example, this is the state of an edit control before the user pastes "World". 该插入点位于 [6, 6]。The insertion point is at [6, 6].

<span data-ttu-id="a0349-188">示例文本流图示](images/coretext/stream-5.png) 用户执行粘贴操作,编辑控件结束时会带有以下文本:</span><span class="sxs-lookup"><span data-stu-id="a0349-188">example text stream diagram The user performs the paste action and the edit control ends up with the following text:

<span data-ttu-id="a0349-189">示例文本流图示 当发生此情况时,应调用带有以下参数的 NotifyTextChanged](https://msdn.microsoft.com/library/windows/apps/dn958172):example text stream diagram When this happens, you should call NotifyTextChanged with these arguments:

  • modifiedRange = [6, 6]modifiedRange = [6, 6]
  • newLength = 5newLength = 5
  • newSelection = [11, 11]newSelection = [11, 11]

按顺序处理陆续生成的一个或多个 TextRequested 事件以更新文本服务所使用的文本。One or more TextRequested events will follow, which you handle to update the text that the text services are working with.

覆盖文本更新Overriding text updates

在你的编辑控件中,你可能希望覆盖文本更新以提供自动更正功能。In your edit control, you might want to override a text update to provide auto-correction features.

例如,请考虑提供支持形式化缩略的更正功能的编辑控件。For example, consider an edit control that provides a correction feature that formalizes contractions. 这是编辑控件在用户键入空格键以触发更正之前的状态。This is the state of the edit control before the user types the space key to trigger the correction. 该插入点位于 [3, 3]。The insertion point is at [3, 3].

<span data-ttu-id="a0349-199">示例文本流图示 用户按空格键,将引发相应的 TextUpdating](https://msdn.microsoft.com/library/windows/apps/dn958176) 事件。example text stream diagram The user presses the space key and a corresponding TextUpdating event is raised. 编辑控件将接受文本更新。The edit control accepts the text update. 这是编辑控件在完成更正之前所处的短暂状态。This is the state of the edit control for a brief moment before the correction is completed. 该插入点位于 [4, 4]。The insertion point is at [4, 4].

<span data-ttu-id="a0349-203">示例文本流图示TextUpdating](https://msdn.microsoft.com/library/windows/apps/dn958176) 事件处理程序之外,编辑控件将进行以下更正。example text stream diagram Outside of the TextUpdating event handler, the edit control makes the following correction. 这是编辑控件在完成更正之后的状态。This is the state of the edit control after the correction is complete. 该插入点位于 [5, 5]。The insertion point is at [5, 5].

<span data-ttu-id="a0349-206">示例文本流图示 当发生此情况时,应调用带有以下参数的 NotifyTextChanged](https://msdn.microsoft.com/library/windows/apps/dn958172):example text stream diagram When this happens, you should call NotifyTextChanged with these arguments:

  • modifiedRange = [1, 2]modifiedRange = [1, 2]
  • newLength = 2newLength = 2
  • newSelection = [5, 5]newSelection = [5, 5]

按顺序处理陆续生成的一个或多个 TextRequested 事件以更新文本服务所使用的文本。One or more TextRequested events will follow, which you handle to update the text that the text services are working with.

提供请求的文本Providing requested text

请务必确保文本服务具有正确的文本,特别是已存在于编辑控件中的文本(例如,通过加载文档,或由编辑控件插入的文本(如前面的部分所述),以便提供诸如自动更正或预测的功能。It's important for text services to have the correct text to provide features like auto-correction or prediction, especially for text that already existed in the edit control, from loading a document, for example, or text that is inserted by the edit control as explained in previous sections. 因此,每当引发 TextRequested 事件时,都必须向当前在你的编辑控件中的文本提供指定范围。Therefore, whenever a TextRequested event is raised, you must provide the text currently in your edit control for the specified range.

CoreTextTextRequest 中的 Range 可以多次指定你的编辑控件不能按原样容纳的某个范围。There will be times the Range in CoreTextTextRequest specifies a range that your edit control cannot accommodate as-is. 例如,Range 大于发生 TextRequested 事件时的编辑控件的大小,或者 Range 的末尾超出范围。For example, the Range is larger than the size of the edit control at the time of the TextRequested event, or the end of the Range is out of bounds. 在这些情况下,应返回有意义的任何范围,该范围通常是请求的范围的子集。In these cases, you should return whatever range makes sense, which is typically a subset of the requested range.

示例Samples