Partager via


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 sont disponibles dans l’exemple de mise en forme de texte avancé.

Conditions préalables

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 pour gérer la présentation du texte, qui inclut sa police, sa taille et sa couleur. Dans des circonstances ordinaires, ces contrôles peuvent gérer la majorité de la présentation de texte dans votre application. Toutefois, certains scénarios avancés nécessitent le contrôle du stockage de texte ainsi que la présentation de texte. 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. Cela se fait en lançant le processus de mise en forme de ligne et en appelant le formateur de texte FormatLine. 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 la césure des lignes de texte. Le formateur de texte peut gérer différents formats de caractères de texte et styles de paragraphes, et inclut la prise en charge de la mise en page internationale du texte.

Contrairement à une API de texte traditionnelle, la TextFormatter interagit 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 classe TextSource. Le diagramme suivant illustre l’interaction de disposition de texte entre l’application cliente et TextFormatter.

Diagramme du client de disposition de texte et 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 de ligne maximale et les valeurs de largeur. 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.

Dans l’exemple suivant, le processus de mise en forme d’un magasin de texte s’affiche. 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 du client

Lorsque vous étendez le moteur de mise en forme du texte, vous devez implémenter et gérer tous les aspects du magasin de texte. Ce n’est pas une tâche triviale. Le magasin de texte est responsable du suivi des propriétés d’exécution de texte, des propriétés de paragraphe, des objets incorporés et d’autres contenus similaires. 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 segments 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 à GetTextRun est répété par le formateur de texte jusqu'à ce que l'une des conditions suivantes se produise :

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

  • La largeur cumulée des segments 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 texte.

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

Fourniture de 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 au formateur de texte TextSource les objets TextRun et les propriétés pour mettre en forme les séquences de texte. 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 de TextRun Utilisation
TextCharacters Exécution de texte spécialisée utilisée pour transmettre une représentation des glyphes de caractères au formateur de texte.
TextEmbeddedObject Le segment de texte spécialisé utilisé pour fournir du contenu dans lequel la mesure, le test de positionnement et le dessin sont effectués globalement, comme 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 Segment de texte spécialisé utilisé pour marquer la terminaison d’un paragraphe.
TextEndOfSegment Une exécution de texte spécialisée qui est 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 Exécution de texte spécialisée utilisée pour marquer une plage de caractères masqués.
TextModifier Portion de texte spécialisée utilisée pour modifier les propriétés des portions de texte dans sa portée. La portée s'étend jusqu'au prochain segment de texte correspondant TextEndOfSegment, ou au prochain 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 exécutions 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 structures de texte avancées doivent implémenter leur propre gestion de portée pour permettre à chaque caractère d'avoir 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