Ajuste automático de escala en Windows Forms

El escalado automático permite que un formulario y sus respectivos controles, diseñados en una máquina con una determinada resolución de pantalla o fuente del sistema, se muestren correctamente en otra máquina con una resolución de pantalla o una fuente de sistema diferentes. El escalado automático garantiza que el formulario y sus controles cambien de tamaño para mantener la coherencia con las ventanas nativas y otras aplicaciones tanto en máquinas de los usuarios como en las de otros desarrolladores. La compatibilidad de .NET Framework con el escalado automático y los estilos visuales permite que las aplicaciones de .NET Framework mantengan una apariencia coherente en comparación con aplicaciones Windows nativas del equipo de cada usuario.

En su mayor parte, el escalado automático funciona según lo previsto en .NET Framework 2.0 y versiones posteriores. Sin embargo, los cambios en la combinación de fuentes pueden causar problemas. Para obtener un ejemplo de cómo resolver esto, vea Procedimiento para responder a los cambios de las combinaciones de fuentes en una aplicación de Windows Forms.

Necesidad de escalado automático

Sin escalado automático, una aplicación diseñada para una fuente o una resolución de pantalla aparecerá demasiado pequeña o demasiado grande cuando se cambie la fuente o la resolución. Por ejemplo, si la aplicación está diseñada con Tahoma de 9 puntos como línea base, sin el ajuste aparecerá demasiado pequeña si se ejecuta en una máquina donde la fuente de sistema sea Tahoma de 12 puntos. Los elementos de texto, como títulos, menús, el contenido de cuadros de texto, etc. se representarán más pequeños que en otras aplicaciones. Además, el tamaño de los elementos de interfaz de usuario (UI) que contienen texto —como la barra de título, los menús y muchos controles— depende de la fuente usada. En este ejemplo, estos elementos también aparecerán relativamente más pequeños.

Una situación análoga se produce cuando se diseña una aplicación para una determinada resolución de pantalla. La resolución de pantalla más común es de 96 puntos por pulgada (PPP), lo que equivale a un escalado de la pantalla del 100 %, pero cada vez son más comunes las pantallas de mayor resolución que admiten 125 %, 150 %, 200 % (que equivalen, respectivamente, a 120, 144 y 192 PPP) y superiores. Si no se ajusta la escala de una aplicación diseñada para una resolución —especialmente si se trata de una aplicación basada en gráficos—, dicha aplicación se verá demasiado grande o demasiado pequeña cuando se ejecute a otra resolución.

El escalado automático busca mejorar estos problemas con un cambio automático el tamaño del formulario y de sus controles secundarios, de acuerdo con el tamaño de fuente o la resolución de pantalla relativos. El sistema operativo Windows admite el escalado automático de cuadros de diálogo mediante una unidad relativa de medida denominada unidades de cuadro de diálogo. Una unidad de cuadro de diálogo se basa en la fuente del sistema y su relación con los píxeles se puede determinar mediante la función del SDK de Win32 GetDialogBaseUnits. Cuando un usuario cambia el tema usado por Windows, todos los cuadros de diálogo se ajustan automáticamente según corresponda. Además, .NET Framework admite el escalado automático en función de los valores predeterminados de fuente o resolución de pantalla del sistema. Opcionalmente, el escalado automático se puede deshabilitar en una aplicación.

Compatibilidad original con el escalado automático

Las versiones 1.0 y 1.1 de .NET Framework admitían el escalado automático de una manera sencilla que dependía de la fuente predeterminada de Windows usada para la interfaz de usuario, representada por el valor del SDK de Win32 DEFAULT_GUI_FONT. Por lo general, esta fuente solo se cambia cuando se modifica la resolución de pantalla. El mecanismo siguiente se usó para implementar el escalado automático:

  1. En tiempo de diseño, la propiedad AutoScaleBaseSize (que ahora está en desuso) se estableció en el alto y ancho de la fuente predeterminada del sistema en la máquina del desarrollador.

  2. En runtime, la fuente predeterminada del sistema de la máquina del usuario se usaba para inicializar la propiedad Font de la clase Form.

  3. Antes de mostrar el formulario, se llamaba al método ApplyAutoScaling para escalar el formulario. Este método calculaba los tamaños de escala relativa de AutoScaleBaseSize y Font y, a continuación, se llamaba al método Scale para escalar el formulario y sus elementos secundarios.

  4. El valor de AutoScaleBaseSize se actualizaba para que las siguientes llamadas a ApplyAutoScaling no cambiaran progresivamente el tamaño del formulario.

Aunque este mecanismo era suficiente para la mayoría de los propósitos, sufría las limitaciones siguientes:

  • Puesto que la propiedad AutoScaleBaseSize representaba el tamaño de fuente básico como valores enteros, se producían errores de redondeo que se hacían evidentes cuando un formulario recorría varias resoluciones.

  • El escalado automático se implementó solo en la clase Form, no en la clase ContainerControl. Como resultado, los controles de usuario solo se escalaban correctamente si el control de usuario estaba diseñado con la misma resolución que el formulario y se colocaba en el formulario en tiempo de diseño.

  • Los formularios y sus controles secundarios solo podían diseñarse de manera simultánea por varios desarrolladores si las resoluciones de sus máquinas eran iguales. Igualmente, hacía que la herencia de un formulario dependiese de la resolución asociada con el formulario principal.

  • No es compatible con los administradores de diseño más recientes introducidos con .NET Framework versión 2.0, como FlowLayoutPanel y TableLayoutPanel.

  • No admitía el escalado automático basado directamente en la resolución de pantalla necesaria para ser compatible con .NET Compact Framework.

Aunque este mecanismo se conserva en .NET Framework versión 2.0 para mantener la compatibilidad con versiones anteriores, se ha sustituido por el mecanismo de escalado más sólido que se describe a continuación. En consecuencia, AutoScale, ApplyAutoScaling, AutoScaleBaseSize y determinadas sobrecargas Scale están marcadas como obsoletas.

Nota:

Puede eliminar las referencias a estos miembros cuando actualice su código heredado a .NET Framework versión 2.0.

Compatibilidad actual con el escalado automático

.NET Framework versión 2.0 supera las limitaciones anteriores gracias a la introducción de los cambios siguientes en el escalado automático de Windows Forms:

  • El soporte básico para el escalado se ha movido a la clase ContainerControl para que los formularios, los controles compuestos nativos y los controles de usuario reciban soporte de escalado uniforme. Se han agregado los nuevos miembros AutoScaleFactor, AutoScaleDimensions, AutoScaleMode y PerformAutoScale.

  • La clase Control también tiene varios miembros nuevos que le permiten participar en el escalado y admitir escalado mixto en el mismo formulario. Concretamente, los miembros Scale, ScaleChildren y GetScaledBounds admiten el escalado.

  • Se ha agregado soporte de escalado basado en la resolución de pantalla para complementar el soporte de fuentes del sistema, tal como se define en la enumeración AutoScaleMode. Este modo es compatible con el escalado automático admitido por .NET Compact Framework, lo que permite una migración de aplicaciones más sencilla.

  • Se ha agregado compatibilidad con administradores de diseño como FlowLayoutPanel y TableLayoutPanel a la implementación del escalado automático.

  • Los factores de escalado se representan ahora como valores de número de punto flotante, normalmente mediante la estructura SizeF, con lo que prácticamente se han eliminado los errores de redondeo.

Precaución

No se admiten combinaciones arbitrarias de los modos de escalado de DPI y fuente. Aunque puede escalar sin ningún problema un control de usuario usando un modo (por ejemplo, DPI) y colocarlo en un formulario usando otro modo (Font), la combinación de un formulario base en un modo y un formulario derivado en otro puede provocar resultados inesperados.

Escalado automático en acción

Windows Forms ahora usa la lógica siguiente para escalar automáticamente los formularios y su contenido:

  1. En tiempo de diseño, cada ContainerControl registra el modo de escalado y su resolución actual en AutoScaleMode y AutoScaleDimensions, respectivamente.

  2. En tiempo de ejecución, la resolución real se almacena en la propiedad CurrentAutoScaleDimensions. La propiedad AutoScaleFactor calcula dinámicamente la proporción entre la resolución de escalado en tiempo de ejecución y tiempo de diseño.

  3. Si al cargar el formulario los valores de CurrentAutoScaleDimensions y AutoScaleDimensions son diferentes, se llamará al método PerformAutoScale para escalar el control y sus elementos secundarios. Este método suspende el diseño y llama al método Scale para realizar el escalado real. Después, el valor de AutoScaleDimensions se actualiza para evitar el escalado progresivo.

  4. PerformAutoScale también se invoca automáticamente en las situaciones siguientes:

    • En respuesta al evento OnFontChanged si el modo de escalado es Font.

    • Cuando el diseño del contenedor se reanuda y se detecta un cambio en las propiedades AutoScaleDimensions o AutoScaleMode.

    • Como se insinúa anteriormente, cuando se escala un elemento primario ContainerControl. Cada control contenedor es responsable de realizar el escalado de sus elementos secundarios mediante sus propios factores de escala, no los del contenedor primario.

  5. Los controles secundarios pueden modificar su comportamiento de escalado a través de varios medios:

    • La propiedad ScaleChildren se puede invalidar para determinar si se deben escalar sus controles secundarios o no.

    • El método GetScaledBounds se puede invalidar para ajustar los límites a los que se escala el control, pero no la lógica de escalado.

    • El método ScaleControl se puede invalidar para cambiar la lógica de escalado del control actual.

Vea también