delphi windows-7 windows-vista dpi highdpi

delphi - Solución de problemas de Virtualización de DPI y aplicaciones compatibles con DPI, en Windows Vista y Windows 7



windows-7 windows-vista (4)

Tengo un problema donde una aplicación (escrita en Delphi) se comporta correctamente con la configuración predeterminada de 96 ppp en todos los sistemas, pero se comporta de manera inconsistente en la configuración de "150% del tamaño de texto" (internamente 144 ppp), en diferentes sistemas. Parece que en algunos sistemas, algunas partes de texto / fuente de mi aplicación se están extendiendo y en otros sistemas, no lo están. Habría pensado que mi aplicación, en una determinada versión de Windows (Win7), en un determinado DPI, debería comportarse de la misma manera.

O bien mi aplicación le hará saber a Windows que no necesita la función de virtualización de DPI, o no lo hará. Eso lo entiendo mucho. Lo que no entiendo es cómo los cambios de DPI pueden causar una apariencia diferente en dos máquinas, ambas ejecutando Windows 7, ambas a 144 dpi, mostrando las mismas fuentes y formularios en los mismos tamaños fijos.

¿Hay algunos elementos dependientes de la configuración involucrados en la virtualización de DPI que necesito inspeccionar en Windows (registro, etc.)? De lo contrario, ¿cómo soluciona los problemas y sabe si la virtualización de DPI se está realizando en la ventana de su cliente?

En Delphi, uno tiene que establecer la propiedad TForm.Scaled en falso, si uno no quiere escalar. Pero lo que no entiendo es que cuando la propiedad Escalada de la forma principal es verdadera, no siempre puedo predecir el resultado.

Lo que me resulta más desconcertante en mi aplicación es que tengo un control que solo se comporta mal en mi gran aplicación real, pero que no se comporta mal en una aplicación independiente en la que estoy tratando de depurar solo el control. Para comprender el comportamiento de control en una aplicación independiente, me vi obligado a hacer una aplicación de demostración en la que fuerzo el reconocimiento de DPI a través del archivo de manifiesto. Entonces puedo reproducir el fallo de dibujo de control, aunque en una forma diferente.

Aquí está el archivo de manifiesto que uso en mi aplicación de demostración, que expone los problemas que tienen mis controles al tratar con la configuración de ppp alto en Windows. Sin embargo, una cosa extraña que he encontrado es que es posible para una aplicación

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> <dpiAware>true</dpiAware> </asmv3:windowsSettings> </asmv3:application> <assemblyIdentity version="14.0.3615.26342" processorArchitecture="*" name="TestProject" type="win32"></assemblyIdentity> <description>High DPI Controls Test App</description> </assembly>

Este es un ejemplo de uno de los aproximadamente 30 lugares donde los controles de mi aplicación están desordenados cuando deshabilito la virtualización de DPI en mi aplicación. Esta falla en particular se resolvió desactivando la propiedad Escalado en mi forma. Pero en otros lugares, tener TForm.Scaled = false causa el problema, mientras que en algunas formas, lo soluciona:

Actualización: Resulta que algunos de mis controles usan GDI + y que el comportamiento de la fuente en contextos GDI + es diferente al comportamiento de la fuente en contextos GDI normales, al menos para ciertos controles de terceros que usan GDI +. Esa es una fuente importante de dolores de cabeza. En segundo lugar, hay una cobertura de prueba irregular y requisitos mal definidos, para el reconocimiento de DPI, en la VCL. Algunos controles de VCL se basan en los controles comunes de MS, y si bien es justo decir que los controles comunes subyacentes probablemente funcionen bien en situaciones de alto DPI, no se puede garantizar que todas las envolturas de control de VCL funcionen correctamente. Por lo tanto, revisar una aplicación para un alto reconocimiento de DPI en todos sus controles, así como el comportamiento correcto en todos los temas de Windows 7 disponibles:

  1. aero glass on, a 96 ppp (aspecto Win7 predeterminado en la mayoría de los equipos modernos)
  2. Tema básico (aero glass off) pero temas xp habilitados
  3. aspecto clásico de win2000 donde el vidrio está apagado, así como temas de nivel xp,
  4. alto contraste blanco
  5. alto contraste negro
  6. Varios ajustes distintos de 96 ppp

..y la lista continúa., y usted tiene una carga bastante pesada, como desarrollador de aplicaciones. Me parece que si es un usuario de Delphi y utiliza el VCL, o si es un desarrollador de MFC / ATL C ++, admitir que todos los diversos modos de ventanas extravagantes es una carga casi demasiado pesada. Así que la mayoría de la gente no se molesta. Estoy en lo cierto


Debe manifestar que su aplicación es compatible con DPI con una sección como esta:

<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> <dpiAware>true</dpiAware> </asmv3:windowsSettings> </asmv3:application>

Si haces esto, entonces no obtendrás la virtualización DPI.

No se supone que utilices la virtualización de DPI, así que creo que no tiene mucho sentido tratar de averiguar cómo funciona. Fácilmente podría depender de los controladores de la tarjeta gráfica. Es casi imposible para nosotros explicar por qué la virtualización se comporta de esta manera: ni siquiera ha proporcionado capturas de pantalla, detalles de hardware, etc. Sin embargo, simplemente no debería molestarse en intentar diagnosticar esto. Se manifiesta como dpiaware y no es un problema.

Para referencia te ofrezco:


En realidad es una pregunta diferente a esa.

Sus formularios no deben aumentar de tamaño con el DPI del usuario, sino que deben aumentar con el tamaño de la fuente .

La fuente de formulario por defecto de Delphi es 8pt Tahoma .
El caracter average 8pt Tahoma es: 6.08px * 13px .

A partir de Windows Vista, la fuente predeterminada es 9pt Segoe UI .
El personaje average 9pt Segoe UI es: 6.81px * 15px .

Sus aplicaciones de Windows deben respetar las preferencias de fuente del usuario (es decir, IconTitleFont ).

Mi preferencia de fuente de Windows es 12pt Segoe UI , cuyo tamaño de carácter promedio es: 8.98px * 21px :

Esto significa que si diseñó su formulario en Tahoma 8pt (13px alto), necesita escalar el formulario y todos los controles de niños, en un 162%:

scaleFactor = (userFontSize / designedFontSize) = 21px / 13px = 1.615

Si tiene cuidado, notará que cambiar el DPI es solo un caso especial de cambiar el tamaño de la fuente. Su fuente de 8 puntos sigue siendo 8 puntos , pero 8 puntos se traduce en más píxeles . Si ejecuta 131dpi (configuración de zoom del 136% en Windows 7) entonces:

9pt Segoe UI, 96dpi = 6.81px x 15px 9pt Segoe UI, 131dpi = 8.98px x 21px

Nota: no es una coincidencia que haya elegido 131dpi y 12pt como mis ejemplos. En el trabajo corro 96dpi pero 12pt. En casa corro 9pt pero 131dpi. Ambos tienen la misma altura de fuente de píxeles, 21px.

Al final, debe llamar a ScaleControl por la diferencia de tamaño:

procedure StandardizeFormFont(Form: TForm); var iconTitleFontName: string; iconTitleFontSizePixels: Integer; currentFontSizePixels: Integer; begin GetIconTitleFont(iconTitleFontName, iconTitleFontSizePixels); //Change font face first //Some fonts are inheriently taller than others //(even at the same point size) Form.Font.Name := iconTitleFontName; //Get the form''s current font height (in pixels) currentFontSizePixels := Form.Font.Height; //negative number, but so is iconTitleFontSizePixels Form.ScaleBy(iconTitleFontSizePixels, currentFontSizePixels); end;

En realidad este código es muy simplista. Muchos controles secundarios deben actualizarse manualmente:

  • Las columnas de vista de lista necesitan ampliarse
  • los controles con ParentFont = false necesitan tener su fuente ajustada
  • Los controles TImage necesitan extender su imagen al nuevo tamaño
  • La necesidad de la barra de herramientas de usar imágenes más grandes.

En realidad, utilizamos una versión super sofisticada de StandardizeFormFont que recursivamente recorre todos los controles del formulario y hace todo lo posible para ajustar cada control en función de lo que sea.

Se supone que todos los controles que Delphi debe anular son su método ScaleControl y realizar los ajustes necesarios para:

protected procedure ChangeScale(M, D: Integer); override;


La ventana "Configuración de ppp personalizada" tiene un "Usar escala de ppp de estilo Windows XP". Eso podría explicar el comportamiento diferente.


Resulta que las peculiaridades en mi Aplicación cuando el DPI del sistema cambió del valor predeterminado de 96 dpi, se encuentran en tres campos generales:

  1. Algunos de los controles de la aplicación usan GDI y algunos controles usan GDI +. Existen algunas diferencias en la forma en que una fuente GDI y GDI + se procesa en diferentes DPI, al menos en los controles que estoy usando.

  2. Uso un framework llamado VCL en delphi. En este marco de Delphi VCL, algunas formas tienen TForm.Scaled = true, y algunas tienen TForm.Scaled = false. Debido a que requiere que piense en cada control en una forma escalada, es muy común que ocurran cosas que usted, como diseñador de UI, encuentre "feo" o inaceptable en una forma escalada. Si desactiva la opción Escalado, se queda con formularios que pueden ser ajustados por el propio Windows 7, en la configuración de alta DPI (modo de virtualización de DPI) o que aparecen pequeños y, por lo tanto, ignoran la "solicitud" del usuario si lo desea, para una versión de 144 ppp de su 96 dpi UI. Otras personas podrían estar usando otros marcos en otros idiomas, o incluso podrían estar usando algo realmente anticuado, como el Editor de cuadros de diálogo para Visual C ++, donde diseña diálogos en "Unidades de diálogo", que es otra forma de tratar de separar el diálogo general. Diseño, desde una correspondencia 1: 1 a píxeles. Los controles de escalado, estiramiento y diseño son una parte general del diseño de la interfaz de usuario que debe resolverse de manera que coincida con los requisitos de la plataforma. En mi caso, el VCL hace un gran trabajo al dejarme diseñar una aplicación aerodinámica con capacidad de 96 ppp, y funciona muy bien en otras clasificaciones de ppp, pero la mayoría de mis controles personalizados no lo hacen. Por lo tanto, es otra razón para seguir con los controles que vienen con la VCL: si le importa el alto soporte de DPI, su trabajo se vuelve más difícil cuando trata de hacer que el alto soporte de DPI funcione.

  3. La virtualización de DPI, a su vez, está controlada por una configuración de manifiesto que debe incluir expresamente en su aplicación. Dado que mi aplicación ya tenía un manifiesto personalizado (no el que se incluye con su aplicación Delphi cuando hace clic en la casilla de verificación Habilitar-windows-temas en la configuración del proyecto), pude activar y desactivar esta virtualización de DPI y probar Mi aplicación en ambos casos. Descubrí que mi aplicación no estaba lista para ejecutarse sin la virtualización de DPI, por lo que dejé a Windows con su comportamiento predeterminado. Las aplicaciones de otras personas podrían funcionar fácilmente con la virtualización de DPI deshabilitada, si usan controles 100% vcl, con formularios que usan el Escalado de formularios, o alguna otra técnica, para dimensionarse adecuadamente (como el control VL ExpressLayout de DevExpress) en una variedad de tamaños de fuente, y tonos de ppp.). Me parece que, al final, el VCL es lo suficientemente funcional, pero que para las soluciones realmente sólidas en la industria, se requiere un marco más avanzado que el VCL, para tratar de manera integral temas como "entornos de alto DPI" correctamente, y eso Los controles de terceros generalmente no están diseñados para funcionar incluso como funciona el VCL actual, en estos casos. Dichas inquietudes sobre el marco de trabajo están muy presentes en el marco de WPF (Microsoft) y en Java (ala), pero no forman parte del clásico "marco de control común de Win16 / Win32" de la VCL.

En general, estos cambios no son tan diferentes (complejos) ahora, como en los viejos tiempos, cuando Windows XP y otras versiones de Windows le ofrecieron una opción de "tamaños de fuente", mientras que ahora, la experiencia de la interfaz de usuario de Windows 7 intenta enterrar las opciones de tamaño de punto de fuente son bastante profundas y, en cambio, le ofrece una interfaz de usuario cambiante de "tamaño de texto" que modifica el DPI del sistema debajo de la superficie. Estas dos formas de cambiar su experiencia de usuario hacen que casi todos los usuarios tengan problemas con al menos una de las principales aplicaciones comerciales que no se ven o funcionan correctamente con los cambios resultantes. A medida que las pantallas de paso de puntos ultraaltas se vuelven más comunes en el entorno de PC de los consumidores, este problema probablemente empeorará y el diseño de la interfaz de usuario en torno a marcos más adecuados será necesario.