Zaawansowane formatowanie tekstu
Program Windows Presentation Foundation (WPF) udostępnia niezawodny zestaw interfejsów API do dołączania tekstu do aplikacji. Interfejsy API układu i interfejsu użytkownika, takie jak TextBlock, udostępniają najbardziej typowe i ogólne elementy do prezentacji tekstu. Interfejsy API rysunku, takie jak GlyphRunDrawing i FormattedText, zapewniają metodę dołączania tekstu sformatowanego w rysunkach. Na najbardziej zaawansowanym poziomie WPF zapewnia rozszerzalny aparat formatowania tekstu do kontrolowania każdego aspektu prezentacji tekstu, takich jak zarządzanie magazynem tekstu, zarządzanie formatowaniem przebiegu tekstu i zarządzanie osadzonymi obiektami.
Ten temat zawiera wprowadzenie do formatowania tekstu WPF. Koncentruje się on na implementacji klienta i użyciu aparatu formatowania tekstu WPF.
Uwaga
Wszystkie przykłady kodu w tym dokumencie można znaleźć w przykładzie Zaawansowane formatowanie tekstu.
Wymagania wstępne
W tym temacie założono, że znasz interfejsy API wyższego poziomu używane do prezentacji tekstu. Większość scenariuszy użytkownika nie wymaga zaawansowanych interfejsów API formatowania tekstu omówionych w tym temacie. Aby zapoznać się z wprowadzeniem do różnych interfejsów API tekstu, zobacz Dokumenty w WPF.
Zaawansowane formatowanie tekstu
Układ tekstu i kontrolki interfejsu użytkownika w WPF zapewniają właściwości formatowania, które umożliwiają łatwe dołączanie sformatowanego tekstu w aplikacji. Te kontrolki uwidaczniają wiele właściwości do obsługi prezentacji tekstu, w tym jej kroju typów, rozmiaru i koloru. W zwykłych okolicznościach te kontrolki mogą obsługiwać większość prezentacji tekstu w aplikacji. Jednak niektóre zaawansowane scenariusze wymagają kontroli magazynu tekstu, a także prezentacji tekstu. WPF zapewnia rozszerzalny aparat formatowania tekstu w tym celu.
Zaawansowane funkcje formatowania tekstu znajdujące się w WPF składają się z aparatu formatowania tekstu, magazynu tekstu, przebiegów tekstu i właściwości formatowania. Aparat TextFormatterformatowania tekstu , tworzy wiersze tekstu, które mają być używane do prezentacji. Jest to osiągane przez zainicjowanie procesu formatowania wiersza i wywołanie elementu formatującego tekst .FormatLine Program formatujący tekst pobiera tekst z magazynu tekstu, wywołując metodę sklepu GetTextRun . Obiekty TextRun są następnie tworzone w TextLine obiekty przez program formatujący tekst i przekazywane aplikacji do inspekcji lub wyświetlania.
Korzystanie z programu formatującego tekst
TextFormatter to aparat formatowania tekstu WPF i zapewnia usługi formatowania i przerywania wierszy tekstu. Program formatujący tekst może obsługiwać różne formaty znaków tekstowych i style akapitu oraz obsługuje międzynarodowy układ tekstu.
W przeciwieństwie do tradycyjnego interfejsu API tekstu interfejs TextFormatter API współdziała z klientem układu tekstu za pomocą zestawu metod wywołania zwrotnego. Wymaga to, aby klient dostarczył te metody we wdrożeniu TextSource klasy . Na poniższym diagramie przedstawiono interakcję układu tekstu między aplikacją kliencka a TextFormatter.
Program formatujący tekst służy do pobierania sformatowanych wierszy tekstu z magazynu tekstu, który jest implementacją elementu TextSource. Jest to wykonywane przez najpierw utworzenie wystąpienia formatującego tekst przy użyciu Create metody . Ta metoda tworzy wystąpienie formatującego tekst i ustawia maksymalną wysokość wiersza i wartości szerokości. Po utworzeniu wystąpienia formatującego tekst, proces tworzenia wiersza jest uruchamiany przez wywołanie FormatLine metody . TextFormatter wywołuje źródło tekstu w celu pobrania tekstu i parametrów formatowania dla przebiegów tekstu, które tworzą wiersz.
W poniższym przykładzie pokazano proces formatowania magazynu tekstu. Obiekt jest używany do pobierania TextFormatter wierszy tekstu z magazynu tekstu, a następnie formatowania wiersza tekstu do rysunku w obiekcie 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
Implementowanie magazynu tekstu klienta
Po rozszerzeniu aparatu formatowania tekstu wymagane jest zaimplementowanie wszystkich aspektów magazynu tekstu i zarządzanie nimi. Nie jest to proste zadanie. Magazyn tekstu jest odpowiedzialny za śledzenie właściwości przebiegu tekstu, właściwości akapitu, obiektów osadzonych i inną podobną zawartość. Udostępnia również program formatujący tekst z poszczególnymi TextRun obiektami, których program formatujący tekst używa do tworzenia TextLine obiektów.
Aby obsłużyć wirtualizację magazynu tekstu, magazyn tekstu musi pochodzić z TextSourceelementu . TextSource definiuje metodę używaną przez program formatujący tekst do pobierania przebiegów tekstu z magazynu tekstu. GetTextRun to metoda używana przez program formatujący tekst do pobierania przebiegów tekstu używanych w formatowaniu wiersza. Wywołanie GetTextRun metody jest wielokrotnie wykonywane przez program formatujący tekst do momentu wystąpienia jednego z następujących warunków:
Zwracana TextEndOfLine jest podklasa lub.
Skumulowana szerokość przebiegów tekstu przekracza maksymalną szerokość wiersza określoną w wywołaniu w celu utworzenia formatera tekstu lub wywołania metody formatera FormatLine tekstu.
Zwracana jest sekwencja nowego wiersza Unicode, taka jak "CF", "LF" lub "CRLF".
Dostarczanie przebiegów tekstu
Rdzeniem procesu formatowania tekstu jest interakcja między formatatorem tekstu a magazynem tekstu. Implementacja TextSource elementu zapewnia program formatujący tekst z TextRun obiektami i właściwościami, za pomocą których można sformatować przebiegi tekstu. Ta interakcja jest obsługiwana przez metodę GetTextRun , która jest wywoływana przez program formatujący tekst.
W poniższej tabeli przedstawiono niektóre wstępnie zdefiniowane TextRun obiekty.
TextRun, typ | Użycie |
---|---|
TextCharacters | Wyspecjalizowany przebieg tekstu używany do przekazywania reprezentacji glifów znaków z powrotem do formatującego tekst. |
TextEmbeddedObject | Wyspecjalizowany przebieg tekstu używany do udostępniania zawartości, w której odbywa się pomiar, testowanie trafień i rysowanie, takie jak przycisk lub obraz w tekście. |
TextEndOfLine | Wyspecjalizowany przebieg tekstu używany do oznaczania końca wiersza. |
TextEndOfParagraph | Wyspecjalizowany przebieg tekstu używany do oznaczania końca akapitu. |
TextEndOfSegment | Wyspecjalizowany przebieg tekstu używany do oznaczania końca segmentu, na przykład w celu zakończenia zakresu, którego dotyczy poprzedni TextModifier przebieg. |
TextHidden | Wyspecjalizowany przebieg tekstu używany do oznaczania zakresu ukrytych znaków. |
TextModifier | Wyspecjalizowany przebieg tekstu używany do modyfikowania właściwości tekstu uruchamianych w jego zakresie. Zakres jest rozszerzany do następnego pasującego TextEndOfSegment przebiegu tekstu lub następnego TextEndOfParagraph. |
Każdy ze wstępnie zdefiniowanych TextRun obiektów może być podklasowany. Dzięki temu źródło tekstu może dostarczyć formater tekstu z przebiegami tekstowymi, które zawierają dane niestandardowe.
W poniższym przykładzie przedstawiono metodę GetTextRun . Ten magazyn tekstu zwraca TextRun obiekty do formatowania tekstu do przetwarzania.
// 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
Uwaga
W tym przykładzie magazyn tekstu udostępnia te same właściwości tekstu wszystkim tekstom. Zaawansowane magazyny tekstu muszą zaimplementować własne zarządzanie zakresem, aby umożliwić poszczególnym znakom różne właściwości.
Określanie właściwości formatowania
TextRun obiekty są formatowane przy użyciu właściwości udostępnianych przez magazyn tekstów. Te właściwości są dostępne w dwóch typach: TextParagraphProperties i TextRunProperties. TextParagraphProperties obsługa właściwości inkluzywnych akapitów, takich jak TextAlignment i FlowDirection. TextRunProperties to właściwości, które mogą być różne dla każdego przebiegu tekstu w akapicie, takich jak szczotka pierwszego planu, Typefacei rozmiar czcionki. Aby zaimplementować niestandardowe typy właściwości akapitu i niestandardowego przebiegu tekstu, aplikacja musi utworzyć klasy, które pochodzą odpowiednio z TextParagraphProperties i TextRunProperties .
Zobacz też
.NET Desktop feedback