自訂文字輸入
Windows.UI.Text.Core 命名空間中的核心文字 API 可讓 Windows 應用程式從 Windows 裝置上支援的任何文字服務接收文字輸入。 API 類似於 文字服務架構 API,應用程式不需要具備文字服務的詳細知識。 這可讓應用程式以任何語言和輸入類型接收文字,例如鍵盤、語音或手寫筆。
為什麼要使用核心文字 API?
對於許多應用程式,XAML 或 HTML 文字框控制項就足以用於文字輸入和編輯。 不過,如果您的應用程式處理複雜的文字案例,例如文字處理應用程式,您可能需要自訂文字編輯控制項的彈性。 您可以使用 CoreWindow 鍵盤 API 來建立文字編輯控制項,但這些不會提供接收以組合為基礎的文字輸入的方式,這是支援東亞語言的必要專案。
當您需要建立自訂文字編輯控制項時,請改用 Windows.UI.Text.Core API。 這些 API 的設計目的是讓您以任何語言處理文字輸入,並提供最適合您應用程式的文字體驗。 使用核心文字 API 建置的文字輸入和編輯控制項,可以從 Windows 裝置上所有現有的文字輸入法、從 以文字服務架構 為基礎的輸入法編輯器(IME)以及電腦上的手寫,到行動裝置上的 WordFlow 鍵盤(提供自動更正、預測和聽寫)。
架構
以下是文字輸入系統的簡單表示法。
- 「應用程式」代表裝載使用核心文字 API 所建置之自訂編輯控制項的 Windows 應用程式。
- Windows.UI.Text.Core API 可協助透過 Windows 與文字服務進行通訊。 文字編輯控制項與文字服務之間的通訊主要是透過 CoreTextEditContext 物件來處理,該物件會提供方法來促進通訊。
文字範圍和選取範圍
編輯控制項提供文字項目的空間,而使用者預期在此空間中的任何位置編輯文字。 在這裡,我們會說明核心文字 API 所使用的文字定位系統,以及如何在此系統中呈現範圍和選取範圍。
應用程式插入號位置
與核心文字 API 搭配使用的文字範圍會以插入號位置表示。 「應用程式插入號位置(ACP)」是以零起始的數位,表示插入號前文字串流開頭的字元計數,如下所示。
文字範圍和選取範圍
文字範圍和選取範圍是由 CoreTextRange 結構來表示,其中包含兩個欄位:
欄位 | 資料類型 | 描述 |
---|---|---|
StartCaretPosition | 數位 [JavaScript] | System.Int32 [.NET] | int32 [C++] | 範圍的開始位置是 ACP,緊接在第一個字元之前。 |
EndCaretPosition | 數位 [JavaScript] | System.Int32 [.NET] | int32 [C++] | 範圍的結尾位置是緊接在最後一個字元之後的 ACP。 |
例如,在先前顯示的文字範圍中,範圍 [0, 5] 會指定 「Hello」 這個字。 StartCaretPosition 必須一律小於或等於 EndCaretPosition。 範圍 [5, 0] 是有效的。
插入點
目前插入號位置,通常稱為插入點,是藉由將 StartCaretPosition 設定為等於 EndCaretPosition 來表示。
非連續選取
某些編輯控制項支援不連續的選取專案。 例如,Microsoft Office 應用程式 支援多個任意選取專案,而且許多原始程式碼編輯器都支援資料行選取。 不過,核心文字 API 不支援非連續選取專案。 編輯控制項只能報告單一連續選取範圍,通常是非連續選取範圍的使用中子範圍。
例如,下圖顯示具有兩個非連續選取範圍的文字串流:[0、1] 和 [6, 11],編輯控制項必須只報告一個 ([0, 1] 或 [6, 11])。
使用文字
CoreTextEditContext 類別可讓 Windows 之間的文字流動,並透過 TextUpdating 事件、TextRequested 事件和 NotifyTextChanged 方法編輯控制項。
您的編輯控制項會透過 TextUpdating 事件接收文字,當使用者與鍵盤、語音或 IME 等文字輸入法互動時所產生的事件。
例如,當您變更編輯控制項中的文字時,將文字貼入控制項時,您必須呼叫 NotifyTextChanged 來通知 Windows。
如果文字服務需要新的文字,則會 引發 TextRequested 事件。 您必須在 TextRequested 事件處理常式中提供新的文字。
接受文字更新
您的編輯控制項通常應該接受文字更新要求,因為它們代表使用者想要輸入的文字。 在 TextUpdating 事件處理常式中,編輯控制項預期會有這些動作:
- 將 CoreTextTextUpdatingEventArgs.Text 中指定的文字插入 CoreTextTextUpdatingEventArgs.Range 中指定的位置。
- 將選取範圍放在 CoreTextTextUpdatingEventArgs.NewSelection 中指定的位置。
- 將 CoreTextTextUpdatingEventArgs.Result 設定為 CoreTextTextUpdatingResult.Succeeded,通知系統更新成功。
例如,這是使用者輸入 「d」 之前編輯控制項的狀態。 插入點位於 [10, 10]。
當使用者輸入 「d」時,會以下列 CoreTextTextUpdatingEventArgs 資料引發 TextUpdating 事件:
- 範圍 = [10, 10]
- Text = "d"
- NewSelection = [11, 11]
在編輯控制項中,套用指定的變更,並將 [結果] 設定為 [成功]。 以下是套用變更之後控制項的狀態。
拒絕文字更新
有時候,您無法套用文字更新,因為要求的範圍位於不應該變更的編輯控制項區域中。 在此情況下,您不應該套用任何變更。 相反地,請將 CoreTextTextUpdatingEventArgs.Result 設定為 CoreTextTextUpdatingResult.Failed,通知系統更新失敗。
例如,請考慮只接受電子郵件地址的編輯控制項。 因為電子郵件位址不能包含空格,所以當空格鍵引發 TextUpdating 事件時,您應該只將 [結果] 設定為 [編輯] 控制項中的 [失敗]。
通知文字變更
有時候,您的編輯控制項會變更文字,例如文字貼上或自動更正時。 在這些情況下,您必須呼叫 NotifyTextChanged 方法來通知文字服務這些變更。
例如,這是使用者貼上 「World」 之前編輯控制項的狀態。 插入點位於 [6, 6]。
使用者會在套用變更之後執行貼上動作和編輯控制項:
發生這種情況時,您應該使用下列自變數呼叫 NotifyTextChanged:
- modifiedRange = [6, 6]
- newLength = 5
- newSelection = [11, 11]
將會追蹤一或多個 TextRequested 事件,您可以處理這些事件來更新文字服務正在使用的文字。
覆寫文字更新
在編輯控制項中,您可能會想要覆寫文字更新以提供自動更正功能。
例如,請考慮提供正規化收縮的更正功能的編輯控制項。 這是使用者輸入空格鍵以觸發更正之前編輯控制項的狀態。 插入點位於 [3, 3]。
使用者按下空格鍵,並引發對應的 TextUpdating 事件。 編輯控制項接受文字更新。 這是編輯控制項的狀態,在更正完成前的短暫時間。 插入點位於 [4, 4]。
在 TextUpdating 事件處理常式之外,編輯控制項會進行下列更正。 這是完成更正之後編輯控制項的狀態。 插入點位於 [5, 5]。
發生這種情況時,您應該使用下列自變數呼叫 NotifyTextChanged:
- modifiedRange = [1, 2]
- newLength = 2
- newSelection = [5, 5]
將會追蹤一或多個 TextRequested 事件,您可以處理這些事件來更新文字服務正在使用的文字。
提供要求的文字
文字服務必須有正確的文字來提供自動更正或預測等功能,特別是對於已經存在於編輯控制項中的文字,例如載入檔,或編輯控制項所插入的文字,如前幾節所述。 因此,每當 引發 TextRequested 事件時,您必須為指定的範圍提供目前編輯控制項中的文字。
CoreTextTextRequest 中的 Range 會指定編輯控制項無法依目前的方式容納的範圍。 例如,Range 大於 TextRequested 事件時編輯控制項的大小,或 Range 的結尾超出界限。 在這些情況下,您應該傳回任何有意義的範圍,這通常是所要求範圍的子集。