Nota: consulte las otras respuestas, ya que contienen técnicas muy valiosas. Mi respuesta aquí solo proporciona advertencias y advertencias contra la suposición de que el conocimiento de DPI es fácil.
Generalmente evito el escalado con reconocimiento de DPI con TForm.Scaled = True
. El conocimiento de DPI solo es importante para mí cuando se vuelve importante para los clientes que me llaman y están dispuestos a pagar por ello. La razón técnica detrás de ese punto de vista es que, si eres consciente de los DPI o no, estás abriendo una ventana a un mundo de dolor. Muchos controles VCL estándar y de terceros no funcionan bien en High DPI. La notable excepción de que las partes de VCL que envuelven los controles comunes de Windows funcionan notablemente bien con un DPI alto. Una gran cantidad de controles personalizados de Delphi VCL integrados y de terceros no funcionan bien, o no funcionan en absoluto, con un DPI alto. Si planea activar TForm.Scaled, asegúrese de probar a 96, 125 y 150 DPI para cada formulario de su proyecto, y cada tercero y control integrado que utilice.
El propio Delphi está escrito en Delphi. Tiene activada la bandera de alta conciencia de DPI, para la mayoría de las formas, aunque incluso tan recientemente como en Delphi XE2, los propios autores de IDE decidieron NO activar esa marca de manifiesto de alta conciencia de DPI. Tenga en cuenta que en Delphi XE4 y versiones posteriores, el indicador de reconocimiento de HIGH DPI está activado y el IDE se ve bien.
Le sugiero que no use TForm.Scaled = true (que es un valor predeterminado en Delphi, por lo que, a menos que lo haya modificado, la mayoría de sus formularios tienen Scaled = true) con las banderas High DPI Aware (como se muestra en las respuestas de David) con Aplicaciones VCL que se crean con el diseñador de formularios integrado delphi.
En el pasado, intenté hacer una muestra mínima del tipo de rotura que puede esperar ver cuando TForm.Scaled es verdadero y cuando el escalado de formularios de Delphi tiene un problema técnico. Estos fallos no siempre y solo son provocados por un valor de DPI distinto de 96. No he podido determinar una lista completa de otras cosas, que incluyen los cambios de tamaño de fuente de Windows XP. Pero dado que la mayoría de estos fallos aparecen solo en mis propias aplicaciones, en situaciones bastante complejas, he decidido mostrarles algunas pruebas que pueden verificar ustedes mismos.
Delphi XE se ve así cuando configura el DPI Scaling en "Fonts @ 200%" en Windows 7, y Delphi XE2 está igualmente roto en Windows 7 y 8, pero estos fallos parecen estar solucionados a partir de Delphi XE4:
En su mayoría, estos son controles VCL estándar que se comportan mal a un DPI alto. Tenga en cuenta que la mayoría de las cosas no se han escalado en absoluto, por lo que los desarrolladores de Delphi IDE han decidido ignorar la conciencia de DPI, así como desactivar la virtualización de DPI. Una elección tan interesante.
Desactive la virtualización de DPI solo si desea esta nueva fuente adicional de dolor y opciones difíciles. Te sugiero que lo dejes solo. Tenga en cuenta que la mayoría de los controles comunes de Windows parecen funcionar bien. Tenga en cuenta que el control del explorador de datos de Delphi es un contenedor de C # WinForms alrededor de un control común de árbol de Windows estándar. Eso es un problema técnico puro de Microsoft, y solucionarlo podría requerir que Embarcadero reescriba un control de árbol .Net nativo puro para su explorador de datos, o que escriba algún código de propiedades de verificación y modificación de DPI para cambiar la altura de los elementos en el control. Ni siquiera microsoft WinForms puede manejar altos DPI de forma limpia, automática y sin código de kludge personalizado.
Actualización: Dato interesante: si bien el IDE de Delphi parece no estar "virtualizado", no está utilizando el contenido del manifiesto mostrado por David para lograr una "virtualización sin DPI". Quizás esté usando alguna función de API en tiempo de ejecución.
Actualización 2: En respuesta a cómo apoyaría el 100% / 125% DPI, se me ocurrió un plan de dos fases. La fase 1 es hacer un inventario de mi código para los controles personalizados que deben arreglarse para un DPI alto y luego hacer un plan para corregirlos o eliminarlos. La fase 2 sería tomar algunas áreas de mi código que están diseñadas como formularios sin administración de diseño y cambiarlas a formularios que usen algún tipo de administración de diseño para que los cambios de DPI o de altura de fuente puedan funcionar sin recortes. Sospecho que este trabajo de diseño de "intercontrol" sería mucho más complejo en la mayoría de las aplicaciones que el trabajo de "intracontrol".
Actualización: En 2016, el último Delphi 10.1 Berlin funciona bien en mi estación de trabajo de 150 ppp.
SetProcessDPIAware
.Su configuración en el archivo .dfm se ampliará correctamente, siempre que lo
Scaled
estéTrue
.Si está configurando dimensiones en el código, debe escalarlas
Screen.PixelsPerInch
dividiendo porForm.PixelsPerInch
. ÚseloMulDiv
para hacer esto.Esto es lo que hace el marco de persistencia de formularios cuando
Scaled
esTrue
.De hecho, puede presentar un argumento convincente para reemplazar esta función con una versión que codifica de forma rígida un valor de 96 para el denominador. Esto le permite usar valores de dimensión absolutos y no preocuparse por el cambio de significado si cambia la escala de fuente en su máquina de desarrollo y vuelve a guardar el archivo .dfm. La razón que importa es que la
PixelsPerInch
propiedad almacenada en el archivo .dfm es el valor de la máquina en la que se guardó por última vez el archivo .dfm.Entonces, continuando con el tema, otra cosa de la que debe tener cuidado es que si su proyecto se desarrolla en varias máquinas con diferentes valores de DPI, encontrará que la escala que usa Delphi al guardar archivos .dfm da como resultado controles que se desvían sobre una serie de ediciones. . En mi lugar de trabajo, para evitar esto, tenemos una política estricta de que los formularios solo se editan a 96 ppp (escala del 100%).
De hecho, mi versión de
ScaleFromSmallFontsDimension
también tiene en cuenta la posibilidad de que la fuente del formulario difiera en tiempo de ejecución de la configurada en tiempo de diseño. En las máquinas XP, los formularios de mi solicitud utilizan 8pt Tahoma. En Vista y versiones posteriores, se usa Segoe UI de 9 puntos. Esto proporciona otro grado de libertad. La escala debe tener en cuenta esto porque se supone que los valores de dimensión absolutos utilizados en el código fuente son relativos a la línea de base de Tahoma de 8 puntos a 96 ppp.Si usa imágenes o glifos en su interfaz de usuario, estos también deben escalar. Un ejemplo común serían los glifos que se usan en barras de herramientas y menús. Querrá proporcionar estos glifos como recursos de iconos vinculados a su ejecutable. Cada ícono debe contener un rango de tamaños y luego, en tiempo de ejecución, usted elige el tamaño más apropiado y lo carga en una lista de imágenes. Algunos detalles sobre ese tema se pueden encontrar aquí: ¿Cómo cargo íconos desde un recurso sin sufrir alias?
Otro truco útil es definir las dimensiones en unidades relativas, relativas a
TextWidth
oTextHeight
. Por lo tanto, si desea que algo tenga un tamaño de alrededor de 10 líneas verticales, puede usar10*Canvas.TextHeight('Ag')
. Esta es una métrica muy aproximada y lista porque no permite el espaciado de línea, etc. Sin embargo, a menudo todo lo que necesita hacer es poder arreglar que la GUI se adapte correctamentePixelsPerInch
.También debe marcar su aplicación como de alta resolución de DPI . La mejor forma de hacerlo es a través del manifiesto de la aplicación. Dado que las herramientas de compilación de Delphi no le permiten personalizar el manifiesto que usa, esto lo obliga a vincular su propio recurso de manifiesto.
El script de recursos se ve así:
donde
Manifest.txt
contiene el manifiesto real. También necesitaría incluir la sección comctl32 v6 y establecerlorequestedExecutionLevel
enasInvoker
. Luego, vincula este recurso compilado a su aplicación y se asegura de que Delphi no intente hacer lo mismo con su manifiesto. En el Delphi moderno, esto se logra estableciendo la opción de proyecto Runtime Themes en None.El manifiesto es la forma correcta de declarar que su aplicación tiene un alto nivel de DPI. Si solo desea probarlo rápidamente sin alterar su manifiesto, llame
SetProcessDPIAware
. Hágalo como lo primero que hace cuando se ejecuta su aplicación. Preferiblemente en una de las primeras secciones de inicialización de la unidad, o como lo primero en su archivo .dpr.Si no declara que su aplicación tiene un alto nivel de DPI, Vista y versiones posteriores la renderizarán en un modo heredado para cualquier escala de fuente superior al 125%. Esto parece bastante espantoso. Trate de evitar caer en esa trampa.
Actualización de DPI por monitor de Windows 8.1
A partir de Windows 8.1, ahora hay soporte del sistema operativo para la configuración de DPI por monitor ( http://msdn.microsoft.com/en-ca/magazine/dn574798.aspx ). Este es un gran problema para los dispositivos modernos que pueden tener diferentes pantallas conectadas con capacidades muy diferentes. Es posible que tenga una pantalla de computadora portátil de DPI muy alto y un proyector externo de DPI bajo. Apoyar tal escenario requiere aún más trabajo que el descrito anteriormente.
fuente
También es importante tener en cuenta que respetar el DPI del usuario es solo un subconjunto de su trabajo real:
Durante décadas, Windows ha resuelto este problema con la noción de realizar el diseño utilizando unidades de diálogo , en lugar de píxeles. Se define una "unidad de diálogo" de modo que el carácter medio de la fuente sea
Delphi se envía con una noción (con errores) de
Scaled
, donde un formulario intenta ajustarse automáticamente en función de laEso no resuelve el problema cuando el usuario usa una fuente diferente a la que diseñó el formulario, por ejemplo:
6.21px x 13.00px
, a 96 ppp)usuario que ejecuta Tahoma 8pt (donde el carácter promedio es
5.94px x 13.00px
, a 96 ppp)Como fue el caso de cualquiera que desarrolle una aplicación para Windows 2000 o Windows XP.
o
5.94px x 13.00px
, a 96 ppp)6.67px x 15px
, a 96 ppp)Como buen desarrollador, respetarás las preferencias de fuente de tu usuario. Esto significa que también necesita escalar todos los controles en su formulario para que coincidan con el nuevo tamaño de fuente:
Scaled
no se encargará de esto por ti.Empeora cuando:
10.52px x 25px
Ahora tienes que escalar todo
Scaled
no se encargará de esto por ti.Si eres inteligente, puedes ver lo irrelevante que es respetar los DPI:
No debería mirar la configuración de DPI del usuario, debería mirar su tamaño de fuente . Dos usuarios corriendo
están ejecutando la misma fuente . DPI es solo una cosa que afecta el tamaño de fuente; las preferencias del usuario son las otras.
StandardizeFormFont
Clovis notó que hago referencia a una función
StandardizeFormFont
que fija la fuente en un formulario y la escala al nuevo tamaño de fuente. No es una función estándar, sino un conjunto completo de funciones que realizan la tarea simple que Borland nunca manejó.Windows tiene 6 fuentes diferentes; no existe una única "configuración de fuente" en Windows.
Pero sabemos por experiencia que nuestros formularios deben seguir la configuración de Fuente de título de icono
Una vez que sabemos el tamaño de fuente vamos a escalar la forma a , obtenemos altura de la fuente actual de la forma ( en píxeles ), y la escala por ese factor.
Por ejemplo, si estoy configurando el formulario en
-16
, y el formulario está actualmente en-11
, entonces necesitamos escalar todo el formulario de la siguiente manera:La estandarización ocurre en dos fases. Primero escale el formulario por la proporción de los tamaños de fuente nuevo: antiguo. Luego, cambie los controles (recursivamente) para usar la nueva fuente.
Aquí está el trabajo de escalar un formulario. Funciona con errores en el propio
Form.ScaleBy
método de Borland . Primero tiene que deshabilitar todos los anclajes en el formulario, luego realizar el escalado y luego volver a habilitar los anclajes:y luego tenemos que usar recursivamente la nueva fuente:
Con los anclajes desactivados de forma recursiva:
Y los anclajes se vuelven a habilitar de forma recursiva:
Con el trabajo de cambiar la fuente de los controles a la izquierda:
Eso es mucho más código de lo que pensaba que iba a ser; Lo sé. Lo triste es que no hay ningún desarrollador de Delphi en la tierra, excepto yo, que realmente hace que sus aplicaciones sean correctas.
fuente
Aquí está mi regalo. Una función que puede ayudarlo con el posicionamiento horizontal de elementos en sus diseños de GUI. Gratuita para todos.
fuente