´

C# – WPF – Escalar el tamaño de la fuente al cambiar el tamaño de la ventana o control

Esta es una copia cruzada del artículo escrito en el blog original:

C# – WPF – Escalar el tamaño de la fuente al cambiar el tamaño de la ventana o control

---------------------------------------------------------

Cambiar el tamaño de la fuente a medida que el control cambia de tamaño es una tarea frecuente, pero esta pobremente documentada, en este articulo esta la respuesta.

Este es uno de esos temas…

Puedes pasar horas buscando diferentes alternativas alrededor de la web, encontraras cosas como

  • ViewBox
  • FontSizeConverter
  • IValueConverter
  • etc.

Nada de eso funciona al menos no como se espera, aunque según el caso pueden dar una buena aproximación a la solución.

 

He escrito este artículo para ayudar a muchos desarrolladores (y diseñadores) a resolver este problema de manera definitiva.

 

Cómo realizar el cálculo de tamaño de fuente?

 

Dado que las fuentes, en su mayoría, son más altas que anchas es importante entonces que usemos como referencia la propiedad Height del control contenedor para definir el tamaño de la fuente con respecto a su dimensión más grande.

 

El alto de la fuente esta dictado por la medición de tres partes básicas:

  1. Ascendente
  2. Descendente
  3. Inicial

Observando esta gráfica es fácil hacerse una mejor idea:

diagram

 

La clase FontFamily en WPF posee la propiedad LineSpacing, la cual es ni más ni menos que el alto total de la fuente de acuerdo a los parámetros anteriormente citados.

Sin embargo esto no es todo, la propiedad LineSpacing es un valor genérico para la FontFamily sin importar el tamaño actual de la fuente utilizada, es decir este atributo nos da una relación proporcional respecto al tamaño de la fuente en unidades em.

Por ende podemos decir que el alto de una fuente en unidades em es

Alto = tamaño fuente * FontFamily.LineSpacing

Eso es correcto, pero nosotros no necesitamos calcular el alto de la fuente, sino calcular el tamaño de la fuente con respecto al Height del contenedor ( Button, Window etc), en ese caso la formula a utilizar sería:

 

tamaño fuente = Alto / FontFamily.LineSpacing

 

Implementación

Creamos una ventana de WPF con el siguiente código

1
2
3
4
5
6
7
8
9
10
<Window x:Class="AutoScaleFont.MainWindow"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<Label HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
SizeChanged="Control_SizeChanged">
Test</Label>
</DockPanel>
</Window>

En el archivo de código creamos el controlador para el evento SizeChanged

1
2
3
4
5
private void Control_SizeChanged(object sender, SizeChangedEventArgs e)
{
Control tmp = sender as Control;
tmp.FontSize = e.NewSize.Height / tmp.FontFamily.LineSpacing;
}

El código se explica a si mismo, sin embargo haré una explicación breve. Establecemos la propiedad FontSize de acuerdo a la formula explicada más arriba tomamos el nuevo Alto del control y lo dividimos en la propiedad LineSpacing del FontFamily utilizado por el control.

Una optimización adicional es hacer que el alto de la fuente sea calculado con un valor levemente menor al del control contenedor para dejar un espacio de margen, con el ánimo de hacerlo proporcional le restamos solo un porcentaje respecto al alto total, en este caso el 5%, quedando así:

1
2
3
4
5
private void Control_SizeChanged(object sender, SizeChangedEventArgs e)
{
Control tmp = sender as Control;
tmp.FontSize = (e.NewSize.Height - e.NewSize.Height * .05d) / tmp.FontFamily.LineSpacing;
}

Iniciemos la ejecución y revisemos el resultado:

 

Eso es justo lo que deseamos!

Si lo deseas puedes hacerlo respecto al ancho del control en lugar de respecto al alto, según sea tu necesidad, en ese caso debes ayudarte con la clase FormattedText y su propiedad Width para hallar el largo total en pixeles de la cadena.

Leave a Comment

(required) 

(required) 

(optional)
 

(required) 

If you can't read this number refresh your screen
Enter the numbers above: