Mise en forme de texte avancée

Windows Presentation Foundation (WPF) fournit un ensemble robuste d’API pour inclure du texte dans votre application. Les API de disposition et d’interface utilisateur (UI), telles que TextBlock, fournissent les éléments les plus courants et les plus utilisés pour la présentation de texte. Les API de dessin, telles que GlyphRunDrawing et FormattedText, fournissent un moyen d’inclure du texte mis en forme dans des dessins. Au niveau le plus avancé, WPF fournit un moteur de mise en forme de texte extensible pour contrôler tous les aspects de la présentation de texte, tels que la gestion du magasin de texte, la gestion de la mise en forme de l’exécution de texte et la gestion des objets incorporés.

Cette rubrique fournit une présentation de la mise en forme du texte WPF. Il se concentre sur l’implémentation du client et l’utilisation du moteur de mise en forme de texte WPF.

Remarque

Tous les exemples de code de ce document se trouvent dans Exemple de mise en forme de texte avancée.

Prérequis

Cette rubrique part du principe que vous connaissez les API de niveau supérieur utilisées pour la présentation de texte. La plupart des scénarios utilisateur ne nécessitent pas les API de mise en forme de texte avancées décrites dans cette rubrique. Pour une présentation des différentes API de texte, consultez Documents dans WPF.

Mise en forme de texte avancée

Les contrôles de disposition de texte et d’interface utilisateur dans WPF fournissent des propriétés de mise en forme qui vous permettent d’inclure facilement du texte mis en forme dans votre application. Ces contrôles exposent un certain nombre de propriétés permettant de gérer la présentation du texte, ce qui inclut sa police, sa taille et sa couleur. Normalement, ces contrôles peuvent gérer la majorité de la présentation du texte dans votre application. Toutefois, certains scénarios avancés nécessitent le contrôle du stockage de texte, ainsi que sa présentation. WPF fournit un moteur de mise en forme de texte extensible à cet effet.

Les fonctionnalités avancées de mise en forme du texte trouvées dans WPF se composent d’un moteur de mise en forme de texte, d’un magasin de texte, d’exécutions de texte et de propriétés de mise en forme. Le moteur de mise en forme du texte, TextFormattercrée des lignes de texte à utiliser pour la présentation. Pour ce faire, vous devez lancer le processus de mise en forme de ligne et appeler le formateur de FormatLinetexte. Le formateur de texte récupère les exécutions de texte à partir de votre magasin de texte en appelant la méthode du GetTextRun magasin. Les TextRun objets sont ensuite formés en TextLine objets par le formateur de texte et donnés à votre application pour inspection ou affichage.

Utilisation du formateur de texte

TextFormatter est le moteur de mise en forme de texte WPF et fournit des services pour la mise en forme et les lignes de texte cassantes. Le formateur de texte peut gérer différents formats de caractères alphabétiques et prend en charge la présentation du texte international.

Contrairement à une API de texte traditionnelle, l’interaction TextFormatter avec un client de disposition de texte via un ensemble de méthodes de rappel. Le client doit fournir ces méthodes dans une implémentation de la TextSource classe. Le diagramme suivant illustre l’interaction de disposition de texte entre l’application cliente et TextFormatter.

Diagram of text layout client and TextFormatter

Le formateur de texte est utilisé pour récupérer des lignes de texte mises en forme à partir du magasin de texte, qui est une implémentation de TextSource. Pour ce faire, commencez par créer une instance du formateur de texte à l’aide de la Create méthode. Cette méthode crée une instance du formateur de texte et définit la hauteur et la largeur de ligne maximales. Dès qu’une instance du formateur de texte est créée, le processus de création de ligne est démarré en appelant la FormatLine méthode. TextFormatter renvoie à la source de texte pour récupérer le texte et les paramètres de mise en forme pour les exécutions de texte qui forment une ligne.

L’exemple suivant illustre le processus de mise en forme d’un magasin de texte. L’objet TextFormatter est utilisé pour récupérer des lignes de texte à partir du magasin de texte, puis mettre en forme la ligne de texte pour le dessin dans le 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

Implémentation du magasin de texte client

Quand vous étendez le moteur de mise en forme du texte, vous devez implémenter et gérer tous les aspects du magasin de texte. Cela n’est pas une tâche facile. Le magasin de texte est chargé de suivre les propriétés de séquence de texte, les propriétés de paragraphe, les objets incorporés et tout autre contenu similaire. Il fournit également le formateur de texte avec des objets individuels TextRun que le formateur de texte utilise pour créer des TextLine objets.

Pour gérer la virtualisation du magasin de texte, le magasin de texte doit être dérivé de TextSource. TextSource définit la méthode utilisée par le formateur de texte pour récupérer des exécutions de texte à partir du magasin de texte. GetTextRun est la méthode utilisée par le formateur de texte pour récupérer les exécutions de texte utilisées dans la mise en forme de ligne. L’appel à est effectué à plusieurs reprises par le formateur de texte jusqu’à GetTextRun ce que l’une des conditions suivantes se produise :

  • Une TextEndOfLine ou une sous-classe est retournée.

  • La largeur cumulée des exécutions de texte dépasse la largeur maximale de ligne spécifiée dans l’appel pour créer le formateur de texte ou l’appel à la méthode du formateur de FormatLine texte.

  • Une séquence de nouvelle ligne Unicode, telle que « CF », « LF » ou « CRLF », est retournée.

Fourniture des séquences de texte

Le cœur du processus de mise en forme du texte est l’interaction entre le formateur de texte et le magasin de texte. Votre implémentation fournit TextSource le formateur de texte avec les TextRun objets et les propriétés avec lesquelles mettre en forme le texte s’exécute. Cette interaction est gérée par la GetTextRun méthode, appelée par le formateur de texte.

Le tableau suivant présente certains des objets prédéfinis TextRun .

Type TextRun Utilisation
TextCharacters Séquence de texte spécialisée utilisée pour passer une représentation des glyphes de caractères au formateur de texte.
TextEmbeddedObject Séquence de texte spécialisée utilisée pour fournir du contenu dont la mesure, le test de positionnement et le dessin sont effectués globalement, par exemple un bouton ou une image dans le texte.
TextEndOfLine Séquence de texte spécialisée utilisée pour marquer la fin d’une ligne.
TextEndOfParagraph Séquence de texte spécialisée utilisée pour marquer la fin d’un paragraphe.
TextEndOfSegment Exécution de texte spécialisée utilisée pour marquer la fin d’un segment, par exemple pour mettre fin à l’étendue affectée par une exécution précédente TextModifier .
TextHidden Séquence de texte spécialisée utilisée pour marquer une plage de caractères masqués.
TextModifier Séquence de texte spécialisée utilisée pour modifier les propriétés des séquences de texte dans sa portée. L’étendue s’étend à l’exécution de texte correspondante TextEndOfSegment suivante, ou à la suivante TextEndOfParagraph.

Tous les objets prédéfinis TextRun peuvent être sous-classés. Cela permet à votre source de texte de fournir au formateur de texte des séquences de texte qui incluent des données personnalisées.

L’exemple suivant illustre une GetTextRun méthode. Ce magasin de texte retourne TextRun des objets au formateur de texte pour traitement.

// 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

Remarque

Dans cet exemple, le magasin de texte fournit les mêmes propriétés de texte à l’ensemble du texte. Les magasins de texte avancés doivent implémenter leur propre gestion de plage pour que les caractères individuels aient des propriétés distinctes.

Spécification des propriétés de mise en forme

TextRun les objets sont mis en forme à l’aide des propriétés fournies par le magasin de texte. Ces propriétés sont de deux types, TextParagraphProperties et TextRunProperties. TextParagraphProperties gérer les propriétés inclusives de paragraphe telles que TextAlignment et FlowDirection. TextRunProperties sont des propriétés qui peuvent être différentes pour chaque exécution de texte dans un paragraphe, comme le pinceau de premier plan, Typefaceet la taille de police. Pour implémenter des types de propriétés d’exécution de paragraphes et de texte personnalisés, votre application doit créer des classes dérivées TextParagraphProperties et TextRunProperties respectivement.

Voir aussi