Compartir a través de


Formato de texto avanzado

Windows Presentation Foundation (WPF) proporciona un conjunto robusto de APIs para incluir texto en las aplicaciones. Las APIs de diseño y user interface (UI), como TextBlock, proporcionan los elementos de uso más común y general para la presentación de texto. Las APIs de dibujo, como GlyphRunDrawing y FormattedText, proporcionan medios para incluir texto con formato en dibujos. En el nivel más avanzado, WPF proporciona un motor de formato de texto extensible para controlar todos los aspectos de la presentación de texto, como la administración de almacenes de texto, de formatos de ejecución de texto y de objetos incrustados.

En este tema se proporciona una introducción al formato de texto en WPF. Se centra en la implementación del cliente y en el uso del motor de formato de texto de WPF.

NotaNota

Todos los ejemplos de código de este documento se encuentran en Advanced Text Formatting Sample.

Este tema contiene las secciones siguientes.

  • Requisitos previos
  • Formato de texto avanzado
  • Utilizar el formateador de texto
  • Implementar el almacén de texto de cliente
  • Proporcionar ejecuciones de texto
  • Especificar propiedades de formato
  • Temas relacionados

Requisitos previos

En este tema se da por hecho que está familiarizado con las APIs de nivel superior utilizadas para la presentación de texto. En la mayoría de los escenarios de usuarios no se requieren las APIs de formato de texto avanzado que se explican en este tema. Para obtener una introducción a las distintas APIs de texto, vea Documentos en WPF.

Formato de texto avanzado

El diseño de texto y los controles de UI de WPF proporcionan propiedades de formato que permiten incluir con facilidad texto con formato en una aplicación. Estos controles exponen varias propiedades para administrar la presentación de texto, incluidos su tipo de letra, tamaño y color. En circunstancias normales, estos controles pueden administrar la mayoría de la presentación de texto en la aplicación. Sin embargo, algunos escenarios avanzados requieren control de almacenamiento de texto y presentación del texto. WPF proporciona un motor de formato de texto extensible para este propósito.

Las características de formato de texto avanzado de WPF son un motor de formato de texto, un almacén de texto, ejecuciones de texto y propiedades de formato. El motor de formato de texto, TextFormatter, crea líneas de texto que se van a utilizar para la presentación. Para ello, se inicia el proceso de formato de líneas y se llama al método FormatLinedel formateador de texto. El formateador de texto recupera las ejecuciones de texto del almacén de texto llamando al método GetTextRun del almacén. A continuación, el formateador de texto convierte los objetos TextRun en objetos TextLine y se entregan a la aplicación para inspección o presentación.

Utilizar el formateador de texto

TextFormatter es el motor de formato de texto de WPF, que proporciona servicios para dar formato a las líneas de texto e introducir saltos de línea. El formateador de texto puede administrar distintos formatos de caracteres de texto y estilos de párrafo, e incluye compatibilidad con el diseño de texto internacional.

A diferencia de la API de texto tradicional, TextFormatter interactúa con un cliente de diseño de texto a través de un conjunto de métodos de devolución de llamada. Necesita que el cliente proporcione estos métodos en una implementación de la clase TextSource. En el diagrama siguiente se muestra la interacción de diseño de texto entre la aplicación cliente y TextFormatter.

Interacción entre la aplicación y TextFormatter

Diagrama de TextFormatter y cliente de diseño de texto

El formateador de texto se utiliza para recuperar líneas del texto con formato del almacén de texto, que es una implementación de TextSource. Para ello, se crea en primer lugar una instancia del formateador de texto utilizando el método Create. Este método crea una instancia del formateador de texto y establece los valores máximos de alto y ancho de línea. Una vez creada una instancia del formateador de texto, se inicia el proceso de creación de líneas llamando al método FormatLine. TextFormatter vuelve a llamar al origen del texto para recuperar los parámetros de texto y formato correspondientes a las ejecuciones de texto que componen una línea.

En el ejemplo siguiente se muestra el proceso de dar formato a un almacén de texto. Se utiliza el objeto TextFormatter para recuperar líneas de texto del almacén de texto y, a continuación, dar formato a la línea de texto para dibujar en DrawingContext.

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

Implementar el almacén de texto de cliente

Al extender el motor de formato de texto, se hace necesario implementar y administrar todos los aspectos del almacén de texto. No es una labor trivial. El almacén de texto es responsable de realizar el seguimiento de las propiedades de las ejecuciones de texto, las propiedades de párrafo, los objetos incrustados y otro contenido similar. Además, proporciona objetos TextRun individuales al formateador de texto, que este utiliza para crear objetos TextLine.

Para administrar la virtualización del almacén de texto, este último debe derivarse de TextSource. TextSource define el método utilizado por el formateador de texto para recuperar ejecuciones de texto del almacén de texto. GetTextRun es el método utilizado por el formateador de texto para recuperar las ejecuciones de texto utilizadas para dar formato a las líneas. El formateador de texto realiza repetidamente la llamada a GetTextRun hasta que se cumple una de las condiciones siguientes:

  • Se devuelve un TextEndOfLine o una subclase.

  • El ancho acumulado de las ejecuciones de texto supera el ancho de línea máximo especificado en la llamada para crear el formateador de texto o bien en la llamada al método FormatLine del formateador de texto.

  • Se devuelve una secuencia Unicode de nueva línea, como "CF", "LF" o "CRLF".

Proporcionar ejecuciones de texto

El núcleo del proceso de formato de texto es la interacción entre el formateador de texto y el almacén de texto. La implementación de TextSource proporciona al formateador de texto los objetos TextRun y las propiedades con las que dar formato a las ejecuciones de texto. El método GetTextRun, al que llama el formateador de texto, administra esta interacción.

En la tabla siguiente se muestran algunos de los objetos TextRun predefinidos.

Tipo de TextRun

Uso

TextCharacters

Ejecución de texto especializada que se usa para devolver una representación de glifos de caracteres al formateador de textos.

TextEmbeddedObject

Ejecución de texto especializada que se usa para proporcionar contenido en el que se efectúan de manera global las pruebas de posicionamiento, la medición y el dibujo, como un botón o una imagen dentro del texto.

TextEndOfLine

Ejecución de texto especializada que se usa para marcar el fin de una línea.

TextEndOfParagraph

Ejecución de texto especializada que se usa para marcar el fin de un párrafo.

TextEndOfSegment

Ejecución de texto especializada que se usa para marcar el fin de un segmento, como el final del ámbito afectado por la ejecución anterior de TextModifier.

TextHidden

Ejecución de texto especializada que se usa para marcar un intervalo de caracteres ocultos.

TextModifier

Ejecución de texto especializada que se usa para modificar las propiedades de las ejecuciones de texto de su ámbito. El ámbito se extiende hasta la siguiente ejecución de texto TextEndOfSegment coincidente, o hasta el siguiente TextEndOfParagraph.

Se pueden crear subclases de cualquiera de los objetos TextRun predefinidos. Esto permite que el origen de texto proporcione al formateador de texto ejecuciones de texto que incluyen datos personalizados.

En el siguiente ejemplo se muestra un método GetTextRun. Este almacén de texto devuelve objetos TextRun al formateador de texto para procesarlos.

      ' 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
// 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);
}
NotaNota

En este ejemplo, el almacén de texto proporciona las mismas propiedades de texto a todo el texto.Los almacenes de texto avanzados deben implementar su propia administración de intervalos, a fin de permitir que caracteres individuales tengan propiedades diferentes.

Especificar propiedades de formato

Se da formato a los objetos TextRun utilizando propiedades proporcionadas por el almacén del texto. Estas propiedades se proporcionan en dos tipos, TextParagraphProperties y TextRunProperties. TextParagraphProperties administra propiedades de inclusión de párrafo como TextAlignment y FlowDirection. TextRunProperties son propiedades que pueden ser diferentes para cada ejecución de texto de un párrafo, como un pincel de primer plano, Typeface y el tamaño de fuente. Para implementar los tipos de propiedades de párrafos y ejecuciones de texto personalizados, la aplicación debe crear clases que se deriven de TextParagraphProperties y TextRunProperties, respectivamente.

Vea también

Conceptos

Tipografía en WPF

Documentos en WPF