Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Windows Presentation Foundation (WPF) innehåller en robust uppsättning API:er för att inkludera text i ditt program. API:er för layout och användargränssnitt (UI), till exempel TextBlock, tillhandahåller de vanligaste och allmänna elementen för textpresentation. Ritnings-API:er, till exempel GlyphRunDrawing och FormattedText, är ett sätt att inkludera formaterad text i ritningar. På den mest avancerade nivån tillhandahåller WPF en utökningsbar textformateringsmotor för att styra alla aspekter av textpresentationen, till exempel hantering av textlager, textkörningsformatering och inbäddad objekthantering.
Det här avsnittet innehåller en introduktion till WPF-textformatering. Den fokuserar på klientimplementering och användning av WPF-textformateringsmotorn.
Anmärkning
Alla kodexempel i det här dokumentet finns i Exempel på avancerad textformatering.
Förutsättningar
Det här avsnittet förutsätter att du är bekant med API:er på högre nivå som används för textpresentation. De flesta användarscenarier kräver inte de avancerade API:er för textformatering som beskrivs i det här avsnittet. En introduktion till de olika text-API:erna finns i Dokument i WPF.
Avancerad textformatering
Textlayouten och UI-kontrollerna i WPF innehåller formateringsegenskaper som gör att du enkelt kan inkludera formaterad text i ditt program. Dessa kontroller visar ett antal egenskaper för att hantera presentationen av text, som innehåller dess typsnitt, storlek och färg. Under vanliga omständigheter kan dessa kontroller hantera merparten av textpresentationen i ditt program. Vissa avancerade scenarier kräver dock kontroll av textlagring och textpresentation. WPF tillhandahåller en utökningsbar textformateringsmotor för detta ändamål.
De avancerade textformateringsfunktionerna som finns i WPF består av en textformateringsmotor, ett textlager, textkörningar och formateringsegenskaper. Textformateringsmotorn TextFormatterskapar textrader som ska användas för presentationen. Detta uppnås genom att initiera radformateringsprocessen och anropa textformateringens FormatLine. Textformatören hämtar textkörningar från ditt textlager genom att anropa lagrets GetTextRun-metod. De TextRun objekten formas sedan till TextLine objekt av textformatören och ges till ditt program för inspektion eller visning.
Använda textformaterare
TextFormatter är WPF-textformateringsmotorn och tillhandahåller tjänster för formatering och brytning av textrader. Textformaterare kan hantera olika textteckenformat och styckeformat och innehåller stöd för internationell textlayout.
Till skillnad från ett traditionellt text-API interagerar TextFormatter med en textlayoutklient via en uppsättning återanropsmetoder. Det kräver att klienten tillhandahåller dessa metoder i en implementering av klassen TextSource. Följande diagram illustrerar interaktionen mellan textlayouten mellan klientprogrammet och TextFormatter.
              
              
            
Textformaterare används för att hämta formaterade textrader från textlagret, vilket är en implementering av TextSource. Detta görs genom att först skapa en instans av textformaterare med hjälp av metoden Create. Den här metoden skapar en instans av textformaterare och anger högsta radhöjd och breddvärden. Så snart en instans av textformaterern har skapats startas processen för att skapa rader genom att anropa metoden FormatLine. TextFormatter anropar textkällan för att hämta text- och formateringsparametrarna för textavsnitt som utgör en rad.
I följande exempel visas formateringsprocessen för ett textlager. Objektet TextFormatter används för att hämta textrader från textlagret och formatera sedan textraden för ritning till 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
Implementera klienttextlager
När du utökar textformateringsmotorn måste du implementera och hantera alla aspekter av textlagret. Detta är inte en trivial uppgift. Textlagret ansvarar för att spåra teckenegenskaper, styckeegenskaper, inbäddade objekt och annat liknande innehåll. Den förser även textformateraren med enskilda TextRun-objekt, som textformatören använder för att skapa TextLine-objekt.
För att hantera virtualiseringen av textlagret måste textlagret härledas från TextSource. TextSource definierar vilken metod textformateraren använder för att hämta textkörningar från textlagret. GetTextRun är den metod som används av textformaterare för att hämta textsträngar som används i radformatering. Anropet till GetTextRun görs upprepade gånger av textformaterare tills något av följande villkor inträffar:
En TextEndOfLine eller en underklass returneras.
Den ackumulerade bredden på textsegment överskrider den maximala radbredden som anges i anropet för att skapa textformatören eller anropet till textformatörens FormatLine-metod.
En Unicode newline-sekvens, till exempel "CF", "LF" eller "CRLF", returneras.
Tillhandahålla textsegment
Kärnan i textformateringsprocessen är interaktionen mellan textformateren och textlagret. Implementeringen av TextSource ger textformatören de TextRun objekten och egenskaperna för att formatera textraderna med. Den här interaktionen hanteras av metoden GetTextRun, som anropas av textformaterare.
I följande tabell visas några av de fördefinierade TextRun objekten.
| TextKörtyp | Användning | 
|---|---|
| TextCharacters | Den specialiserade textrun som används för att skicka en representation av teckenglyfer tillbaka till textformaterare. | 
| TextEmbeddedObject | Den specialiserad textkörning som används för att tillhandahålla innehåll där mätning, träfftestning och avbildning görs i sin helhet, till exempel en knapp eller bild inom texten. | 
| TextEndOfLine | Den specialiserade textraden som används för att markera slutet på en rad. | 
| TextEndOfParagraph | Den specialiserade textrun som används för att markera slutet på ett stycke. | 
| TextEndOfSegment | Den specialiserade textdelen som används för att markera slutet på ett segment, till exempel för att avsluta räckvidden som påverkas av en tidigare TextModifier textdel. | 
| TextHidden | Den specialiserade textkörningen som används för att markera ett intervall med dolda tecken. | 
| TextModifier | Den specialiserade textsträngen som används för att ändra egenskaper för textsträngar inom dess område. Omfånget sträcker sig till nästa matchande TextEndOfSegment textrad eller nästa TextEndOfParagraph. | 
Alla fördefinierade TextRun objekt kan underklasseras. På så sätt kan textkällan tillhandahålla textformaterare med textkörningar som innehåller anpassade data.
I följande exempel visas en GetTextRun metod. Det här textlagret returnerar TextRun objekt till textformaterare för bearbetning.
// 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
Anmärkning
I det här exemplet innehåller textlagret samma textegenskaper för hela texten. Avancerade textlager skulle behöva implementera sin egen span-hantering så att enskilda tecken kan ha olika egenskaper.
Ange formateringsegenskaper
TextRun objekt formateras med hjälp av egenskaper som tillhandahålls av textlagret. Dessa egenskaper finns i två typer, TextParagraphProperties och TextRunProperties. TextParagraphProperties hanterar styckeomfattande egenskaper som TextAlignment och FlowDirection. TextRunProperties är egenskaper som kan vara olika för varje textrun inuti ett stycke, till exempel förgrundsfärg, Typefaceoch teckenstorlek. Om din applikation vill implementera anpassade stycke- och textkörningsegenskaper, måste den skapa klasser som härleds från TextParagraphProperties respektive TextRunProperties.
Se även
.NET Desktop feedback