Share via


進階文字格式化

Windows Presentation Foundation (WPF) 提供一組健全的 API,讓您在應用程式中包含文字。 版面配置和使用者介面 (UI) API,例如 TextBlock ,為文字呈現提供最常見的和一般用途元素。 繪圖 API,例如 GlyphRunDrawingFormattedText ,提供在繪圖中包含格式化文字的方法。 在最進階的層級,WPF 提供可延伸的文字格式設定引擎來控制文字簡報的各個層面,例如文字存放區管理、文字執行格式管理,以及内嵌物件管理。

本主題提供 WPF 文字格式設定的簡介。 其著重于用戶端實作和使用 WPF 文字格式設定引擎。

注意

此文件中的所有程式碼範例位於進階文字格式設定範例

必要條件

本主題假設您已熟悉用於文字簡報的較高層級 API。 大部分的使用者案例都不需要本主題所討論的進階文字格式 API。 如需不同文字 API 的簡介,請參閱 WPF 中的檔。

進階文字格式化

WPF 中的文字版面配置和 UI 控制項提供格式化屬性,可讓您輕鬆地在應用程式中包含格式化的文字。 這些控制項會公開一些屬性來處理文字的呈現方式,包括其字體、大小和色彩。 在一般情況下,這些控制項可以處理您應用程式中大部分的文字呈現。 不過,某些進階的情節需要控制文字儲存以及文字呈現。 WPF 會為此目的提供可延伸的文字格式設定引擎。

WPF 中找到的進階文字格式設定功能是由文字格式設定引擎、文字存放區、文字執行和格式化屬性所組成。 文字格式設定引擎 TextFormatter 會建立要用於簡報的文字行。 這是藉由起始行格式設定程式並呼叫文字格式子 的 FormatLine 來達成此目的。 文字格式器會藉由呼叫 Store 的 GetTextRun 方法來擷取文字從文字存放區執行。 然後,物件 TextRun 會由文字格式器組成 TextLine 物件,並提供給您的應用程式進行檢查或顯示。

使用文字格式子

TextFormatter 是 WPF 文字格式設定引擎,並提供格式化和中斷文字行的服務。 文字格式子可處理不同的文字字元格式和段落樣式,且包含國際文字版面配置的支援。

不同于傳統的文字 API,會 TextFormatter 透過一組回呼方法與文字版面配置用戶端互動。 它要求用戶端在 類別的實作 TextSource 中提供這些方法。 下圖說明用戶端應用程式與 TextFormatter 之間的文字配置互動。

Diagram of text layout client and TextFormatter

文字格式器用來從文字存放區擷取格式化的文字行,這是 的實作 TextSource 。 這是藉由先使用 Create 方法建立文字格式子的實例來完成。 這個方法會建立文字格式子的執行個體,並設定最大線條高度和寬度的值。 一旦建立文字格式子的實例,就會呼叫 FormatLine 方法啟動行建立程式。 TextFormatter 會回呼回文字來源,以擷取形成線條之文字的文字和格式參數。

在下列範例中,會顯示格式設定文字存放區的程序。 物件 TextFormatter 用來從文字存放區擷取文字行,然後格式化文字行以繪製到 DrawingContext

// Create a DrawingGroup object for storing formatted text.
textDest = new DrawingGroup();
DrawingContext dc = textDest.Open();

// Update the text store.
_textStore.Text = textToFormat.Text;
_textStore.FontRendering = _currentRendering;

// Create a TextFormatter object.
TextFormatter formatter = TextFormatter.Create();

// Format each line of text from the text store and draw it.
while (textStorePosition < _textStore.Text.Length)
{
   // Create a textline from the text store using the TextFormatter object.
   using (TextLine myTextLine = formatter.FormatLine(
       _textStore,
       textStorePosition,
       96*6,
       new GenericTextParagraphProperties(_currentRendering),
       null))
   {
       // Draw the formatted text into the drawing context.
       myTextLine.Draw(dc, linePosition, InvertAxes.None);

       // Update the index position in the text store.
       textStorePosition += myTextLine.Length;

       // Update the line position coordinate for the displayed line.
       linePosition.Y += myTextLine.Height;
   }
}

// Persist the drawn text content.
dc.Close();

// Display the formatted text in the DrawingGroup object.
myDrawingBrush.Drawing = textDest;
' Create a DrawingGroup object for storing formatted text.
textDest = New DrawingGroup()
Dim dc As DrawingContext = textDest.Open()

' Update the text store.
_textStore.Text = textToFormat.Text
_textStore.FontRendering = _currentRendering

' Create a TextFormatter object.
Dim formatter As TextFormatter = TextFormatter.Create()

' Format each line of text from the text store and draw it.
Do While textStorePosition < _textStore.Text.Length
   ' Create a textline from the text store using the TextFormatter object.
   Using myTextLine As TextLine = formatter.FormatLine(_textStore, textStorePosition, 96*6, New GenericTextParagraphProperties(_currentRendering), Nothing)
       ' Draw the formatted text into the drawing context.
       myTextLine.Draw(dc, linePosition, InvertAxes.None)

       ' Update the index position in the text store.
       textStorePosition += myTextLine.Length

       ' Update the line position coordinate for the displayed line.
       linePosition.Y += myTextLine.Height
   End Using
Loop

' Persist the drawn text content.
dc.Close()

' Display the formatted text in the DrawingGroup object.
myDrawingBrush.Drawing = textDest

實作用戶端文字存放區

當您延伸文字格式設定引擎時,您必須實作與管理文字存放區的所有層面。 這不是簡單的工作。 文字存放區負責追蹤文字執行屬性、段落屬性、內嵌的物件,以及其他類似的內容。 它也會提供文字格式器與文字格式器用來建立 TextLine 物件的個別 TextRun 物件。

若要處理文字存放區的虛擬化,文字存放區必須衍生自 TextSourceTextSource 定義文字格式器用來從文字存放區擷取文字執行的方法。 GetTextRun 是文字格式器用來擷取行格式設定中使用的文字執行的方法。 文字格式器會重複呼叫 , GetTextRun 直到發生下列其中一個情況為止:

  • TextEndOfLine 回 或 子類別。

  • 文字執行的累積寬度超過呼叫中指定的最大行寬,以建立文字格式器或呼叫文字格式器 FormatLine 的方法。

  • 傳回 Unicode 分行符號序列,例如 「CF」、「LF」 或 「CRLF」。

提供文字執行

文字格式設定程序的核心是文字格式子與文字存放區之間的互動。 的 實作 TextSource 會提供文字格式器,以及 TextRun 用來格式化文字執行的物件和屬性。 這個互動是由 GetTextRun 方法處理,由文字格式器呼叫。

下表顯示一些預先定義的 TextRun 物件。

TextRun 類型 使用方式
TextCharacters 用來將字元圖像 (glyph) 的表示法傳回文字格式子的特殊文字執行。
TextEmbeddedObject 用來提供內容的特殊文字執行,在這些內容中會整體進行測量、點擊測試和繪製,例如文字內的按鈕或影像。
TextEndOfLine 用來標記行尾的特殊文字執行。
TextEndOfParagraph 用來標記段落結尾的特殊文字執行。
TextEndOfSegment 用來標記區段結尾的特製化文字執行,例如結束前 TextModifier 一次執行所影響的範圍。
TextHidden 用來標記隱藏字元範圍的特殊文字執行。
TextModifier 用來在文字執行範圍中修改其屬性的特殊文字執行。 範圍會延伸至下一個相符 TextEndOfSegment 的文字執行,或下一個 TextEndOfParagraph

任何預先定義的 TextRun 物件都可以子類別化。 這可讓文字來源提供文字格式子包含自訂資料的文字執行。

下列範例示範 GetTextRun 方法。 此文字存放區會將物件傳 TextRun 回文字格式器進行處理。

// Used by the TextFormatter object to retrieve a run of text from the text source.
public override TextRun GetTextRun(int textSourceCharacterIndex)
{
   // Make sure text source index is in bounds.
   if (textSourceCharacterIndex < 0)
      throw new ArgumentOutOfRangeException("textSourceCharacterIndex", "Value must be greater than 0.");
   if (textSourceCharacterIndex >= _text.Length)
   {
      return new TextEndOfParagraph(1);
   }

   // Create TextCharacters using the current font rendering properties.
   if (textSourceCharacterIndex < _text.Length)
   {
      return new TextCharacters(
         _text,
         textSourceCharacterIndex,
         _text.Length - textSourceCharacterIndex,
         new GenericTextRunProperties(_currentRendering));
   }

   // Return an end-of-paragraph if no more text source.
   return new TextEndOfParagraph(1);
}
' Used by the TextFormatter object to retrieve a run of text from the text source.
Public Overrides Function GetTextRun(ByVal textSourceCharacterIndex As Integer) As TextRun
   ' Make sure text source index is in bounds.
   If textSourceCharacterIndex < 0 Then
      Throw New ArgumentOutOfRangeException("textSourceCharacterIndex", "Value must be greater than 0.")
   End If
   If textSourceCharacterIndex >= _text.Length Then
      Return New TextEndOfParagraph(1)
   End If

   ' Create TextCharacters using the current font rendering properties.
   If textSourceCharacterIndex < _text.Length Then
      Return New TextCharacters(_text, textSourceCharacterIndex, _text.Length - textSourceCharacterIndex, New GenericTextRunProperties(_currentRendering))
   End If

   ' Return an end-of-paragraph if no more text source.
   Return New TextEndOfParagraph(1)
End Function

注意

在此範例中,文字存放區提供相同的文字屬性給所有文字。 進階的文字存放區必須實作自己的範圍管理,以允許個別字元可以有不同的屬性。

指定格式設定屬性

TextRun 物件是使用文字存放區所提供的屬性來格式化。 這些屬性有兩種類型, TextParagraphProperties 以及 TextRunPropertiesTextParagraphProperties 處理段落內含屬性,例如 TextAlignmentFlowDirectionTextRunProperties 是可在段落內執行之每個文字的屬性,例如前景筆刷、 Typeface 和字型大小。 若要實作自訂段落和自訂文字執行屬性類型,您的應用程式必須分別建立衍生自 TextParagraphPropertiesTextRunProperties 的類別。

另請參閱