Windows.UI.Text.Core 命名空間中的核心文字 API 讓 Windows 應用程式能接收任何支援於 Windows 裝置的文字服務的文字輸入。 這些 API 類似於 Text Services Framework 的 API,因為應用程式不需要對文字服務有詳細的了解。 這讓應用程式能接收任何語言及任何輸入方式(如鍵盤、語音或筆)的文字。
重要 API: Windows.UI.Text.Core、 CoreTextEditContext
為什麼要使用核心文字 API?
對許多應用程式來說,XAML 或 HTML 文字框控制項已足夠用於文字輸入與編輯。 不過,如果你的應用程式處理複雜的文字情境,比如文字處理軟體,你可能需要自訂文字編輯控制的彈性。 你可以使用 CoreWindow 鍵盤 API 來建立文字編輯控制,但這些 API 無法接收基於組合的文字輸入,而這是支援東亞語言所必需的。
相反地,當你需要建立自訂文字編輯控制項時,請使用 Windows.UI.Text.Core API。 這些 API 設計上讓你在處理任何語言的文字輸入時有很大的彈性,讓你能提供最適合你應用程式的文字體驗。 以核心文字 API 建構的文字輸入與編輯控制,可接收來自 Windows 裝置上所有現有文字輸入法的文字輸入,從基於 文字服務框架 的輸入法編輯器(IME)到電腦上的手寫,到行動裝置上的 WordFlow 鍵盤(提供自動修正、預測與口述功能)。
Architecture
以下是文字輸入系統的簡單表示。
- 「應用程式」代表一個 Windows 應用程式,承載著使用核心文字 API 建構的自訂編輯控制項。
- Windows.UI.Text.Core API 促進了透過 Windows 與文字服務的通訊。 文字編輯控制與文字服務之間的通訊主要透過 CoreTextEditContext 物件處理,該物件提供促進通訊的方法與事件。
文字範圍與選擇
編輯控制提供文字輸入空間,使用者預期能在此區域內任意編輯文字。 在此,我們將說明核心文本 API 所使用的文字定位系統,以及該系統如何表示範圍與選擇。
應用程式插入點位置
核心文字 API 使用的文字範圍以插入符號位置表示。 「Application Caret Position(ACP)」是一個以零為基礎的數字,表示從文字串流開始至插入符號之前的字元數,如圖所示。
文字範圍與選擇
文字範圍與選取由 CoreTextRange 結構表示,該結構包含兩個欄位:
| 領域 | 數據類型 | Description |
|---|---|---|
| StartCaretPosition | 編號 [JavaScript] | System.Int32 [.NET] | int32 [C++] | 範圍的起始位置是位於第一個字元之前的 ACP。 |
| EndCaretPosition | 編號 [JavaScript] | System.Int32 [.NET] | int32 [C++] | 範圍的終點位置是位於最後一個字元之後的 ACP。 |
例如,在先前顯示的文字範圍中,範圍 [0, 5] 表示單字「Hello」。 StartCaretPosition 必須始終小於或等於 EndCaretPosition。 範圍 [5, 0] 是無效的。
插入點
目前的 caret 位置,通常稱為插入點,透過將 StartCaretPosition 設為等於 EndCaretPosition 來表示。
非連續選擇
部分編輯控制項支援非連續選擇。 例如,Microsoft Office 應用程式支援多個任意選取,許多原始碼編輯器也支援欄位選擇。 然而,核心文本 API 不支援非連續選取。 編輯控件必須只報告一個連續的選擇,通常是非連續選取中的活躍子範圍。
例如,下圖顯示了一個文字串流,其中有兩個非連續的選取範圍:[0, 1] 和 [6, 11],編輯控制只能回報其中之一([0, 1] 或 [6, 11])。
處理文字
CoreTextEditContext 類別透過 TextUpdate 事件、TextRequested 事件及 NotifyTextChanged 方法,使 Windows 與編輯控制項間的文字流暢。
你的編輯控制是透過 TextUpdate 事件接收文字,這些事件是使用者與鍵盤、語音或 IME 互動時產生的。
例如,當你在編輯控制項中更改文字時,例如將文字貼上控制項,你需要透過呼叫 NotifyTextChanged 通知 Windows。
如果簡訊服務需要新的簡訊,則會觸發 TextRequested 事件。 您必須在 TextRequested 事件處理程序中提供新文字。
接受文字更新
你的編輯控制通常應該接受文字更新請求,因為它們代表使用者想輸入的文字。 在 TextUpdate 事件處理程序中,以下動作是你編輯控制所期望的:
- 在 CoreTextTextUpdatingEventArgs.Range 指定的位置插入 CoreTextTextUpdatingEventArgs.Text 指定文字。
- 在 CoreTextTextUpdatingEventArgs.NewSelection 指定的位置進行選擇。
- 通知系統更新成功的方法是將 CoreTextTextUpdatingEventArgs.Result 設定為 CoreTextTextUpdatingResult.Succeeded。
例如,這是使用者輸入「d」前編輯控制項的狀態。 插入點位於 [10, 10]。
當使用者輸入「d」時,會觸發一個 TextUpdate 事件,並包含以下 CoreTextTextUpdatingEventArgs 資料:
- 範圍 = [10, 10]
- 文本 = 「d」
- NewSelection = [11, 11]
在你的編輯控制中,套用指定的變更,並將 結果 設為 成功。 以下是變更套用後控制項的狀態。
拒絕文字更新
有時候,你無法套用文字更新,因為請求的範圍位於編輯控制中不應該更改的區域。 在這種情況下,你不應該做任何更改。 相反地,請將 CoreTextTextUpdatingEventArgs.Result 設為 CoreTextTextUpdatingResult.Failed 來通知系統更新失敗。
舉例來說,考慮一個只接受電子郵件地址的編輯控制。 空格應該被拒絕,因為電子郵件地址不能包含空格,所以當 TextUpdate 事件因空格鍵出現時,你只需在編輯控制中將 結果 設為 失敗 即可。
通知文字變更
有時候,編輯控制項會對文字進行更改,例如黏貼文字或自動更正。 在這種情況下,你必須透過呼叫 NotifyTextChanged 方法通知文字服務這些變更。
例如,這是使用者貼上「World」前編輯控制項的狀態。 插入點位於 [6, 6]。
使用者在套用變更之後,執行貼上內容的操作,然後進行編輯控制。
當這種情況發生時,你應該用以下參數呼叫 NotifyTextChanged :
- 修正範圍 = [6, 6]
- newLength = 5
- newSelection = [11, 11]
接著會有一個或多個 TextRequested 事件,你處理這些事件來更新文字服務正在處理的文字。
覆蓋文字更新
在你的編輯控制中,你可能會想覆蓋文字更新,以提供自動更正功能。
舉例來說,考慮一個具有將縮減語形式正式化的修正功能的編輯控制項。 這是使用者輸入空白鍵觸發修正前編輯控制的狀態。 插入點位於 [3, 3]。
使用者按下空白鍵,對應的 TextUpdate 事件就會被觸發。 編輯控制項接受文字更新。 這是編輯控制在修正完成前短暫的狀態。 插入點位於 [4, 4]。
在 TextUpdate 事件處理程序之外,編輯控制項會做出以下修正。 這是修正完成後編輯控制的狀態。 插入點位於 [5, 5]。
當這種情況發生時,你應該用以下參數呼叫 NotifyTextChanged :
- 修正範圍 = [1, 2]
- newLength = 2
- newSelection = [5, 5]
接著會有一個或多個 TextRequested 事件,你處理這些事件來更新文字服務正在處理的文字。
提供所需文字
文字服務必須擁有正確的文字,以提供自動更正或預測等功能,尤其是對於已存在於編輯控制中的文字,例如載入文件,或是編輯控制插入的文字,如前述所述。 因此,每當 TextRequested 事件被提出時,你必須提供目前在編輯控制中指定範圍內的文字。
有時 CoreTextTextRequest 中的範圍會指定一個編輯控制無法照原樣處理的範圍。 例如,範圍在 TextRequested 事件發生時大於編輯控制項的大小,或者範圍的末端超出了界限。 在這種情況下,你應該返回一個合適的範圍,通常是請求範圍的子集。