Megosztás a következőn keresztül:


Speciális szövegformázás

A Windows Presentation Foundation (WPF) robusztus API-kat biztosít a szöveg alkalmazásba való beépítéshez. Az elrendezés és a felhasználói felület (UI) API-k, például TextBlocka szövegmegjelenítések leggyakoribb és általánosan használt elemeit biztosítják. A rajz API-k( például GlyphRunDrawing és FormattedText) lehetővé teszik a formázott szöveg rajzokba való beépítét. A legfejlettebb szinten a WPF bővíthető szövegformázási motort biztosít a szövegmegjelenítések minden aspektusának szabályozásához, például a szövegtár-kezeléshez, a szövegfuttatások formázásának kezeléséhez és a beágyazott objektumkezeléshez.

Ez a témakör bemutatja a WPF-szövegformázást. A WPF szövegformázási motorjának ügyfél-implementációjára és használatára összpontosít.

Megjegyzés:

A dokumentumban található összes kódminta megtalálható a Speciális szövegformázási mintában.

Előfeltételek

Ez a témakör feltételezi, hogy ismeri a szöveges bemutatókhoz használt magasabb szintű API-kat. A legtöbb felhasználói forgatókönyvhez nem lesz szükség a jelen témakörben tárgyalt speciális szövegformázási API-kra. A különböző szöveges API-k bemutatása: Dokumentumok a WPF-ben.

Speciális szövegformázás

A WPF szövegelrendezési és felhasználói felületi vezérlői olyan formázási tulajdonságokat biztosítanak, amelyek lehetővé teszik, hogy a formázott szöveg egyszerűen szerepeljen az alkalmazásban. Ezek a vezérlők számos tulajdonságot fednek fel a szöveg megjelenítésének kezelésére, beleértve a betűtípust, a méretet és a színt. Normál körülmények között ezek a vezérlők képesek kezelni az alkalmazásban a szöveges bemutatók többségét. Bizonyos speciális forgatókönyvek azonban megkövetelik a szövegtárolás és a szövegbemutató szabályozását. A WPF egy bővíthető szövegformázási motort biztosít erre a célra.

A WPF-ben található speciális szövegformázási funkciók szövegformázási motorból, szövegtárból, szövegfuttatásokból és formázási tulajdonságokból állnak. A szövegformázási motor TextFormattera bemutatóhoz használandó szövegsorokat hozza létre. Ez úgy érhető el, hogy elindítjuk a sorformázási folyamatot, és meghívjuk a szövegformázó FormatLine-ját. A szövegformázó az áruház GetTextRun metódusának meghívásával lekéri a szöveges futtatásokat a szövegtárolóból. Az TextRun objektumokat ezután a szövegformáló TextLine objektummá alakítja, majd átadja az alkalmazásnak ellenőrzés vagy megjelenítés céljából.

A Szövegformáló használata

TextFormatter a WPF szövegformázási motorja, amely szolgáltatásokat nyújt a szövegformázáshoz és a szövegsorok tördeléséhez. A szövegformáló képes kezelni a különböző szöveges karakterformátumokat és bekezdésstílusokat, és támogatja a nemzetközi szövegelrendezést.

A hagyományos szöveges API-kkal ellentétben a TextFormatter visszahívási metódusok segítségével kommunikál egy szövegelrendezési ügyféllel. Megköveteli, hogy az ügyfél ezeket a metódusokat a TextSource osztály implementációjában adja meg. Az alábbi ábra az ügyfélalkalmazás és a TextFormatterközötti szövegelrendezést mutatja be.

Szövegelrendezési ügyfél és a TextFormatter diagramja

A szövegformázó a formázott szövegsorok lekérésére szolgál a szövegtárból, amely a(z) TextSource megvalósítása. Ehhez először létre kell hoznia a szövegformáló egy példányát a Create metódus használatával. Ez a metódus létrehozza a szövegformáló egy példányát, és beállítja a vonalmagasság és a szélesség maximális értékét. A szövegformáló egy példányának létrehozása után a sorlétrehozási folyamat a metódus meghívásával FormatLine kezdődik. TextFormatter visszahívja a szövegforrást, hogy lekérje a sorokat alkotó szövegfuttatások szöveg- és formázási paramétereit.

Az alábbi példában egy szövegtár formázási folyamata látható. Az TextFormatter objektum szövegsorok lekérésére szolgál a szövegtárolóból, majd formázza a szövegsort a DrawingContextrajzba.

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

Az ügyfélszöveg-tároló implementálása

A szövegformázási motor kiterjesztésekor a szövegtár minden aspektusát implementálnia és kezelnie kell. Ez nem triviális feladat. A szövegtár felelős a szövegfuttatás tulajdonságainak, a bekezdéstulajdonságoknak, a beágyazott objektumoknak és más hasonló tartalmaknak a nyomon követéséért. A szövegformáló olyan egyedi TextRun objektumokat is biztosít, amelyeket a szövegformáló TextLine objektumok létrehozására használ.

A szövegtár virtualizálásának kezeléséhez a szövegtárat a következőből TextSourcekell származtatnia: TextSource meghatározza azt a metódust, amelyet a szövegformáló a szövegtárból történő szövegfuttatások lekérésére használ. GetTextRun a szövegformázó által a sorok formázásánál használt szövegszakaszok lekérésére szolgáló metódus. GetTextRun meghívása a szövegformáló által ismételten történik, amíg az alábbi feltételek valamelyike nem következik be.

  • A TextEndOfLine függvény egy vagy egy alosztályt ad vissza.

  • A halmozott szövegszélesség túllépi a szövegformáló létrehozására irányuló hívásban vagy a szövegformáló FormatLine metódusának hívásában megadott maximális vonalszélességű vonalat.

  • A rendszer egy Unicode újsoros sorozatot ad vissza, például "CF", "LF" vagy "CRLF".

Szövegfuttatások biztosítása

A szövegformázási folyamat lényege a szövegformázási folyamat és a szövegtároló közötti interakció. A implementáció TextSource biztosítja a szövegformálónak az TextRun objektumokat és a szöveg formázásához használt tulajdonságokat. Ezt az interakciót a GetTextRun metódus kezeli, amelyet a szövegformáló hív meg.

Az alábbi táblázat néhány előre definiált TextRun objektumot mutat be.

Szövegfuttatás típusa Használat
TextCharacters A speciális szövegfuttatás, amellyel a karakterjelek reprezentációját visszaadhatja a szövegformázónak.
TextEmbeddedObject A speciális szövegfuttatás olyan tartalmak megadására szolgál, amelyekben a mérés, a találattesztelés és a rajzolás egészében történik, például egy gomb vagy kép a szövegben.
TextEndOfLine A sor végének megjelöléséhez használt speciális szöveg.
TextEndOfParagraph A bekezdés végének megjelöléséhez használt speciális szöveg.
TextEndOfSegment A szegmens végének megjelöléséhez használt speciális szövegfuttatás, például az előző TextModifier futtatás által érintett hatókör megszüntetéséhez.
TextHidden Az a speciális szöveg, amelyet rejtett karakterek tartományának megjelölésére használnak.
TextModifier A szövegfuttatások tulajdonságainak módosítására használt speciális szövegfuttatás a hatókörében. A hatókör a következő egyező TextEndOfSegment szövegfuttatásra vagy a következőre TextEndOfParagraphterjed ki.

Az előre definiált TextRun objektumok bármelyike alosztályozott. Ez lehetővé teszi, hogy a szövegforrás egyéni adatokat tartalmazó szövegfuttatásokat biztosítson a szövegformálónak.

Az alábbi példa egy metódust GetTextRun mutat be. Ez a szövegtár objektumokat TextRun ad vissza a szövegformálónak feldolgozás céljából.

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

Megjegyzés:

Ebben a példában a szövegtároló ugyanazokat a szövegtulajdonságokat biztosítja az összes szöveghez. A speciális szövegtárolóknak saját spankezelést kell implementálniuk, hogy az egyes karakterek különböző tulajdonságokkal rendelkezzenek.

Formázási tulajdonságok megadása

TextRun az objektumok formázása a szövegtár által biztosított tulajdonságok használatával történik. Ezek a tulajdonságok két típusba tartoznak, TextParagraphProperties és TextRunProperties. TextParagraphProperties kezeli a bekezdést tartalmazó tulajdonságokat, például TextAlignment és FlowDirection. TextRunProperties Azok a tulajdonságok, amelyek különbözőek lehetnek a bekezdésen belüli egyes szövegek esetében, például az előtér ecsete és Typefacea betűméret. Az egyéni bekezdés- és szövegfuttatási tulajdonságtípusok megvalósításához az alkalmazásnak olyan osztályokat kell létrehoznia, amelyek a TextParagraphProperties illetve a TextRunProperties osztályokból származnak.

Lásd még