Delen via


Geavanceerde tekstopmaak

Windows Presentation Foundation (WPF) biedt een robuuste set API's voor het opnemen van tekst in uw toepassing. Indelings- en gebruikersinterface-API's ( UI) bieden, zoals TextBlock, de meest voorkomende en algemene elementen voor tekstpresentatie. Teken-API's, zoals GlyphRunDrawing en FormattedText, bieden een middel voor het opnemen van opgemaakte tekst in tekeningen. Op het meest geavanceerde niveau biedt WPF een uitbreidbare engine voor tekstopmaak om elk aspect van de tekstpresentatie te beheren, zoals het beheer van tekstarchieven, het beheer van tekstuitvoeringen en het beheer van ingesloten objecten.

In dit onderwerp vindt je een inleiding tot WPF-tekstopmaak. Het richt zich op client-implementatie en het gebruik van de WPF-tekstopmaak-engine.

Notitie

Alle codevoorbeelden in dit document vindt u in het voorbeeld van geavanceerde tekstopmaak.

Voorwaarden

In dit onderwerp wordt ervan uitgegaan dat u bekend bent met de API's op een hoger niveau die worden gebruikt voor tekstpresentaties. Voor de meeste gebruikersscenario's zijn geen geavanceerde API's voor tekstopmaak vereist die in dit onderwerp worden besproken. Zie Documenten in WPF-voor een inleiding tot de verschillende tekst-API's.

Geavanceerde tekstopmaak

De besturingselementen voor tekstindeling en gebruikersinterface in WPF bieden opmaakeigenschappen waarmee u eenvoudig opgemaakte tekst in uw toepassing kunt opnemen. Deze besturingselementen geven een aantal eigenschappen weer om de presentatie van tekst te verwerken, waaronder het lettertype, de grootte en de kleur. Onder normale omstandigheden kunnen deze besturingselementen het merendeel van de tekstpresentatie in uw toepassing verwerken. Voor sommige geavanceerde scenario's is echter het beheer van de tekstopslag en de tekstpresentatie vereist. WPF biedt hiervoor een uitbreidbare engine voor tekstopmaak.

De geavanceerde functies voor tekstopmaak in WPF bestaan uit een tekstopmaakengine, een tekstarchief, tekstuitvoeringen en opmaakeigenschappen. Met de engine voor tekstopmaak, TextFormatter, worden regels tekst gemaakt die voor de presentatie moeten worden gebruikt. Dit wordt bereikt door het proces voor regelopmaak te initiëren en de FormatLinevan de tekstformatter aan te roepen. De tekstopmaker haalt tekstvoeringen uit uw tekstopslag door de GetTextRun-methode van de opslag aan te roepen. De TextRun objecten worden vervolgens gevormd in TextLine objecten door de tekstopmaak en aan uw toepassing voor inspectie of weergave gegeven.

De tekstopmaak gebruiken

TextFormatter is de WPF-tekstopmaak-engine en biedt services voor het opmaken en verbreken van tekstregels. De tekstopmaak kan verschillende tekenopmaak en alineastijlen verwerken en bevat ondersteuning voor internationale tekstindelingen.

In tegenstelling tot een traditionele tekst-API communiceert de TextFormatter met een tekstindelingsclient via een set callback-methoden. Hiervoor moet de client deze methoden opgeven in een implementatie van de TextSource-klasse. In het volgende diagram ziet u de interactie tussen de tekstindeling tussen de clienttoepassing en TextFormatter.

diagram van de client voor tekstindeling en textFormatter-

De tekstformatter wordt gebruikt om opgemaakte tekstregels op te halen uit het tekstarchief, wat een implementatie van TextSourceis. Dit wordt gedaan door eerst een instantie van de tekstformatter aan te maken met behulp van de methode Create. Met deze methode maakt u een exemplaar van de tekstopmaak en stelt u de waarden voor de maximale lijnhoogte en breedte in. Zodra een instantie van de tekstopmaker is gemaakt, wordt het proces voor het creëren van regels gestart door de methode FormatLine aan te roepen. TextFormatter roept de tekstbron aan om de tekst- en opmaakparameters op te halen voor de tekstfragmenten die samen een regel vormen.

In het volgende voorbeeld wordt het opmaakproces van een tekstarchief weergegeven. Het TextFormatter-object wordt gebruikt om tekstregels op te halen uit de tekstopslag en vervolgens de tekstregel op te maken voor het tekenen in de 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

Clienttekstopslag implementeren

Wanneer u de engine voor tekstopmaak uitbreidt, moet u alle aspecten van het tekstarchief implementeren en beheren. Dit is geen triviale taak. Het tekstarchief is verantwoordelijk voor het bijhouden van eigenschappen voor tekstuitvoering, alinea-eigenschappen, ingesloten objecten en andere vergelijkbare inhoud. Het biedt ook afzonderlijke TextRun objecten aan de tekstopmaker, die deze gebruikt om TextLine objecten te maken.

Als u de virtualisatie van het tekstarchief wilt afhandelen, moet het tekstarchief worden afgeleid van TextSource. TextSource definieert de methode die de tekstopmaaker gebruikt om tekstuitvoeringen op te halen uit het tekstarchief. GetTextRun is de methode die door de tekstopmaakprogramma's wordt gebruikt om tekstreeksen op te halen die in lijnopmaak worden gebruikt. De aanroep van GetTextRun wordt herhaaldelijk uitgevoerd door de tekstformatter totdat een van de volgende voorwaarden optreedt:

  • Er wordt een TextEndOfLine of een subklasse geretourneerd.

  • De samengevoegde breedte van tekstregels overschrijdt de maximale regelbreedte die is opgegeven bij de aanroep van het tekstopmaakprogramma of de aanroep van de FormatLine-methode van het tekstopmaakprogramma.

  • Er wordt een Unicode-nieuwelijnreeks, zoals CF, LF of CRLF, geretourneerd.

Het verschaffen van tekstruns

De kern van het tekstopmaakproces is de interactie tussen de tekstopmaak en het tekstarchief. Uw implementatie van TextSource biedt de tekstformatter de TextRun-objecten en hun eigenschappen waarmee de tekstuitvoeringen worden opgemaakt. Deze interactie wordt verwerkt door de GetTextRun methode, die wordt aangeroepen door de tekstopmaak.

In de volgende tabel ziet u enkele vooraf gedefinieerde TextRun objecten.

TextRun Type Gebruik
TextCharacters De gespecialiseerde tekstuitvoering die wordt gebruikt om een weergave van karakterglyphen terug te geven aan de tekstopmaker.
TextEmbeddedObject De gespecialiseerde tekstuitvoering die wordt gebruikt om inhoud te leveren waarin meten, drukken en tekenen in zijn geheel wordt uitgevoerd, zoals een knop of afbeelding in de tekst.
TextEndOfLine De gespecialiseerde tekstuitvoering die wordt gebruikt om het einde van een regel te markeren.
TextEndOfParagraph De gespecialiseerde tekstuitvoering die wordt gebruikt om het einde van een alinea te markeren.
TextEndOfSegment De gespecialiseerde tekstuitvoering die wordt gebruikt om het einde van een segment te markeren, bijvoorbeeld om het bereik te beëindigen dat wordt beïnvloed door een eerdere TextModifier uitvoering.
TextHidden De gespecialiseerde tekstuitvoering die wordt gebruikt om een reeks verborgen tekens te markeren.
TextModifier De gespecialiseerde tekstuitvoering die wordt gebruikt om eigenschappen van tekstuitvoeringen binnen zijn bereik te wijzigen. Het bereik strekt zich uit tot de volgende overeenkomstige TextEndOfSegment tekstreeks of de volgende TextEndOfParagraph.

Elk van de vooraf gedefinieerde TextRun-objecten kan worden uitgebreid. Hierdoor kan uw tekstbron de tekstopmaak opgeven met tekstuitvoeringen die aangepaste gegevens bevatten.

In het volgende voorbeeld ziet u een GetTextRun methode. Deze tekstopslag retourneert TextRun objecten aan de tekstopmaakfunctie voor verwerking.

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

Notitie

In dit voorbeeld bevat het tekstarchief dezelfde teksteigenschappen voor alle tekst. Geavanceerde tekstarchieven moeten hun eigen spanbeheer implementeren, zodat afzonderlijke tekens verschillende eigenschappen kunnen hebben.

Opmaakeigenschappen opgeven

TextRun objecten zijn opgemaakt met behulp van eigenschappen van de tekstopslag. Deze eigenschappen zijn beschikbaar in twee typen, TextParagraphProperties en TextRunProperties. TextParagraphProperties inclusief alinea-eigenschappen verwerken, zoals TextAlignment en FlowDirection. TextRunProperties zijn eigenschappen die kunnen verschillen voor elke tekstgedeelte binnen een alinea, zoals de voorgrondkleur, Typefaceen lettergrootte. Als u aangepaste alinea- en aangepaste typen tekstuitvoeringseigenschappen wilt implementeren, moet uw toepassing klassen maken die zijn afgeleid van respectievelijk TextParagraphProperties en TextRunProperties.

Zie ook