共用方式為


自訂文字輸入

Windows.UI.Text.Core 命名空間中的核心文字 API 可讓 Windows 應用程式從 Windows 裝置上支援的任何文字服務接收文字輸入。 API 類似於 文字服務架構 API,應用程式不需要具備文字服務的詳細知識。 這可讓應用程式以任何語言和輸入類型接收文字,例如鍵盤、語音或手寫筆。

重要 API:Windows.UI.Text.Core、CoreTextEditContext

為什麼要使用核心文字 API?

對於許多應用程式,XAML 或 HTML 文字框控制項就足以用於文字輸入和編輯。 不過,如果您的應用程式處理複雜的文字案例,例如文字處理應用程式,您可能需要自訂文字編輯控制項的彈性。 您可以使用 CoreWindow 鍵盤 API 來建立文字編輯控制項,但這些不會提供接收以組合為基礎的文字輸入的方式,這是支援東亞語言的必要專案。

當您需要建立自訂文字編輯控制項時,請改用 Windows.UI.Text.Core API。 這些 API 的設計目的是讓您以任何語言處理文字輸入,並提供最適合您應用程式的文字體驗。 使用核心文字 API 建置的文字輸入和編輯控制項,可以從 Windows 裝置上所有現有的文字輸入法、從 以文字服務架構 為基礎的輸入法編輯器(IME)以及電腦上的手寫,到行動裝置上的 WordFlow 鍵盤(提供自動更正、預測和聽寫)。

架構

以下是文字輸入系統的簡單表示法。

  • 「應用程式」代表裝載使用核心文字 API 所建置之自訂編輯控制項的 Windows 應用程式。
  • Windows.UI.Text.Core API 可協助透過 Windows 與文字服務進行通訊。 文字編輯控制項與文字服務之間的通訊主要是透過 CoreTextEditContext 物件來處理,該物件會提供方法來促進通訊。

CoreText 架構圖表

文字範圍和選取範圍

編輯控制項提供文字項目的空間,而使用者預期在此空間中的任何位置編輯文字。 在這裡,我們會說明核心文字 API 所使用的文字定位系統,以及如何在此系統中呈現範圍和選取範圍。

應用程式插入號位置

與核心文字 API 搭配使用的文字範圍會以插入號位置表示。 「應用程式插入號位置(ACP)」是以零起始的數位,表示插入號前文字串流開頭的字元計數,如下所示。

顯示應用程式插入號位置 (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 事件處理常式中,編輯控制項預期會有這些動作:

  1. 將 CoreTextTextUpdatingEventArgs.Text 中指定的文字插入 CoreTextTextUpdatingEventArgs.Range 中指定的位置。
  2. 將選取範圍放在 CoreTextTextUpdatingEventArgs.NewSelection 中指定的位置。
  3. 將 CoreTextTextUpdatingEventArgs.Result 設定為 CoreTextTextUpdatingResult.Succeeded,通知系統更新成功。

例如,這是使用者輸入 「d」 之前編輯控制項的狀態。 插入點位於 [10, 10]。

文字串流圖的螢幕快照,顯示插入點在 [10, 10] 之前插入點

當使用者輸入 「d」時,會以下列 CoreTextTextUpdatingEventArgs 資料引發 TextUpdating 事件:

在編輯控制項中,套用指定的變更,並將 [結果] 設定[成功]。 以下是套用變更之後控制項的狀態。

文字串流圖的螢幕快照,顯示插入點在插入之後的 \[11, 11\]

拒絕文字更新

有時候,您無法套用文字更新,因為要求的範圍位於不應該變更的編輯控制項區域中。 在此情況下,您不應該套用任何變更。 相反地,請將 CoreTextTextUpdatingEventArgs.Result 設定為 CoreTextTextUpdatingResult.Failed,通知系統更新失敗。

例如,請考慮只接受電子郵件地址的編輯控制項。 因為電子郵件位址不能包含空格,所以當空格鍵引發 TextUpdating 事件時,您應該只將 [結果] 設定為 [編輯] 控制項中的 [失敗]。

通知文字變更

有時候,您的編輯控制項會變更文字,例如文字貼上或自動更正時。 在這些情況下,您必須呼叫 NotifyTextChanged 方法來通知文字服務這些變更。

例如,這是使用者貼上 「World」 之前編輯控制項的狀態。 插入點位於 [6, 6]。

文字串流圖的螢幕快照,顯示插入點在 [6, 6] 之前插入點

使用者會在套用變更之後執行貼上動作和編輯控制項:

文字串流圖的螢幕快照,顯示插入點在插入之後的 \[11, 11\]

發生這種情況時,您應該使用下列自變數呼叫 NotifyTextChanged:

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

將會追蹤一或多個 TextRequested 事件,您可以處理這些事件來更新文字服務正在使用的文字。

覆寫文字更新

在編輯控制項中,您可能會想要覆寫文字更新以提供自動更正功能。

例如,請考慮提供正規化收縮的更正功能的編輯控制項。 這是使用者輸入空格鍵以觸發更正之前編輯控制項的狀態。 插入點位於 [3, 3]。

文字串流圖的螢幕快照,顯示插入點在 [3, 3] 之前插入點

使用者按下空格鍵,並引發對應的 TextUpdating 事件。 編輯控制項接受文字更新。 這是編輯控制項的狀態,在更正完成前的短暫時間。 插入點位於 [4, 4]。

文字串流圖的螢幕快照,顯示插入點在 [4, 4] 之後的插入點

在 TextUpdating 事件處理常式之外,編輯控制項會進行下列更正。 這是完成更正之後編輯控制項的狀態。 插入點位於 [5, 5]。

顯示 [5, 5] 插入點之文字串流圖的螢幕快照

發生這種情況時,您應該使用下列自變數呼叫 NotifyTextChanged:

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

將會追蹤一或多個 TextRequested 事件,您可以處理這些事件來更新文字服務正在使用的文字。

提供要求的文字

文字服務必須有正確的文字來提供自動更正或預測等功能,特別是對於已經存在於編輯控制項中的文字,例如載入檔,或編輯控制項所插入的文字,如前幾節所述。 因此,每當 引發 TextRequested 事件時,您必須為指定的範圍提供目前編輯控制項中的文字。

CoreTextTextRequest 中的 Range 會指定編輯控制項無法依目前的方式容納的範圍。 例如,Range 大於 TextRequested 事件時編輯控制項的大小,或 Range 的結尾超出界限。 在這些情況下,您應該傳回任何有意義的範圍,這通常是所要求範圍的子集。

範例

封存範例