windows - reales - libro de android studio en español pdf
Escalar el área que no es cliente(barra de título, barra de menú) para soporte de alta resolución de DPI por monitor (2)
Con Per Monitor V2 DPI awareness en Windows 10 Creators Update (compilación 15063) puede resolver esto fácilmente sin EnableNonClientDpiScaling
.
Para habilitar la detección de Per Monitor V2 DPI , al mismo tiempo que se admite la antigua percepción por DPI de Monitor en versiones anteriores de Windows 10 y Windows 8.1 y el reconocimiento de DPI en versiones anteriores de Windows, haga que su aplicación se manifieste así:
<assembly ...>
<!-- ... --->
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
Referencias
Windows 8.1 introdujo la capacidad de tener diferentes configuraciones de DPI para diferentes monitores. Esta característica se conoce como "soporte por alta resolución de DPI por monitor". Persiste y se ha perfeccionado aún más en Windows 10.
Si una aplicación no acepta ( es decir , no tiene conocimiento de PPP o tiene conocimiento de alta DPI), DWM la ampliará automáticamente al DPI adecuado. La mayoría de las aplicaciones pertenecen a una de estas dos categorías, incluida la mayoría de las utilidades incluidas con Windows ( por ejemplo , el Bloc de notas). En mi sistema de prueba, el monitor de PPP alto está configurado a una escala del 150% (144 ppp), mientras que el monitor normal está configurado en el DPI del sistema (escala del 100%, 96 ppp). Por lo tanto, cuando abre una de estas aplicaciones en la pantalla de alta DPI (o la arrastra hacia allí), la virtualización se activa, magnificando todo, pero también haciéndolo increíblemente borroso.
Por otro lado, si una aplicación indica explícitamente que es compatible con alta resolución de dpi por monitor, entonces no se realiza la virtualización y el desarrollador es responsable de escalar. Microsoft tiene una explicación bastante completa here * , pero para el beneficio de una pregunta autocontenida, resumiré. Primero, indique soporte estableciendo <dpiAware>True/PM</dpiAware>
en el manifiesto. Esto le WM_DPICHANGED
recibir mensajes WM_DPICHANGED
, que le informa tanto la nueva configuración de DPI como un nuevo tamaño y posición sugeridos para su ventana. También le permite llamar a la función GetDpiForMonitor y obtener el DPI real , sin que le mientan por razones de compatibilidad. Kenny Kerr también escribió un tutorial completo .
He logrado todo esto con éxito en una pequeña aplicación de prueba C ++. Es un montón de repetición y la mayoría de las configuraciones del proyecto, así que no veo mucho sentido publicar aquí un ejemplo completo. Si desea probarlo, siga las instrucciones de Kenny, este tutorial en MSDN o descargue la muestra oficial de SDK . Ahora, el texto en el área del cliente se ve bien (debido a mi manejo de WM_DPICHANGED
), pero como la virtualización ya no se realiza, no hay escalado del área no cliente. El resultado es que la barra de título / título y la barra de menú tienen el tamaño incorrecto; no se agrandan en la pantalla de PPP alto:
Entonces la pregunta es, ¿cómo hago para que el área no cliente de la ventana se escale al nuevo DPI?
No importa si crea su propia clase de ventana o usa un cuadro de diálogo; tienen un comportamiento idéntico a este respecto.
Se ha sugerido que no hay respuesta, que su única opción es dibujar a medida toda la ventana, incluido el área no cliente. Si bien esto es ciertamente posible, y de hecho lo que hacen las aplicaciones UWP (conocidas anteriormente como Metro), como la Calculadora de Windows 10, no es una opción factible para aplicaciones de escritorio que usan muchos widgets que no son de cliente y esperan parecer nativas.
Aparte de eso, es demostrablemente falso. Las barras de título dibujadas a medida no pueden ser la única forma de obtener el comportamiento correcto, ya que el equipo de shell de Windows lo ha hecho. El humilde diálogo Ejecutar se comporta exactamente como se esperaba, redimensionando correctamente las áreas cliente y no cliente a medida que lo arrastra entre monitores con diferentes DPI:
La investigación con Spy ++ confirma que este es solo un diálogo Win32 estándar de pantano, nada lujoso. Todos los controles son controles estándar de Win32 SDK. No es una aplicación UWP, ni tienen una barra de título personalizada, todavía tiene el estilo WS_CAPTION
. Se inicia mediante el proceso explorer.exe, que está marcado como compatible con un alto porcentaje de DPI por monitor (verificado con Process Explorer y GetProcessDpiAwareness). Esta publicación de blog confirma que tanto el cuadro de diálogo Ejecutar como el Símbolo del sistema se han reescrito en Windows 10 para escalar correctamente (consulte " Command shells et al. "). ¿Qué está haciendo el diálogo Ejecutar para cambiar el tamaño de su barra de título?
La API Common Dialog API , responsable de los nuevos diálogos de Abrir y Guardar, también se escala correctamente cuando se inicia desde un proceso que es compatible con un alto DPI por monitor, como puede ver al hacer clic en el botón "Examinar" del diálogo Ejecutar. Lo mismo ocurre con la API del Diálogo de tareas , que crea una situación extraña en la que una aplicación abre un cuadro de diálogo con una barra de título de tamaño diferente . (La API heredada de MessageBox no se ha actualizado, sin embargo, y muestra el mismo comportamiento que mi aplicación de prueba).
Si el equipo shell lo está haciendo, tiene que ser posible. Simplemente no puedo imaginarme que el equipo responsable de diseñar / implementar la implementación de DPI por monitor descuide proporcionar una forma razonable para que los desarrolladores produzcan aplicaciones compatibles. Las características como esta requieren la asistencia del desarrollador, o están descompuestas de fábrica. Incluso las aplicaciones WPF están rotas: el proyecto Per-Monitor Aware WPF Sample de Microsoft no escala el área que no es cliente, lo que da como resultado una barra de título que tiene un tamaño incorrecto. No soy partidario de teorías de conspiración, pero huele a un movimiento de marketing para desalentar el desarrollo de aplicaciones de escritorio. Si es así, y no hay una forma oficial, aceptaré las respuestas que se basan en el comportamiento no documentado.
Hablando de comportamiento no documentado, al iniciar sesión en los mensajes de la ventana cuando se arrastra el diálogo Ejecutar entre monitores con diferentes configuraciones de DPI, se muestra que recibe un mensaje no documentado, 0x02E1
. Esto es algo interesante porque este ID de mensaje es exactamente uno mayor que el mensaje documentado WM_DPICHANGED
( 0x02E0
). Sin embargo, mi aplicación de prueba nunca recibe este mensaje, independientemente de su configuración de percepción de DPI. (Curiosamente, una inspección minuciosa revela que Windows aumenta ligeramente el tamaño de los glifos de minimizar / maximizar / cerrar en la barra de título a medida que la ventana pasa al monitor de PPP alto. Todavía no son tan grandes como lo son cuando se virtualizan , pero son un poco más grandes que los glifos que usa para las aplicaciones sin sistema de DPI del sistema).
Hasta ahora, mi mejor idea ha sido manejar el mensaje WM_NCCALCSIZE
para ajustar el tamaño del área no cliente. Al utilizar el indicador SWP_FRAMECHANGED
con la función SetWindowPos
, puedo forzar a la ventana a redimensionar y redibujar su área no cliente en respuesta a WM_DPICHANGED
. Esto funciona bien para reducir la altura de la barra de título, o incluso eliminarla por completo, pero nunca lo hará más alto . La leyenda parece tener un pico en la altura determinada por el sistema DPI. Incluso si funcionara, esta no sería la solución ideal, porque no ayudaría con la barra de menú o barras de desplazamiento dibujadas por el sistema ... pero al menos sería un comienzo. ¿Otras ideas?
* Sé que este artículo dice "Tenga en cuenta que el área no cliente de una aplicación compatible con el monitor-DPI no está escalada por Windows, y aparecerá proporcionalmente más pequeña en una pantalla de DPI alta". Vea arriba para saber por qué eso es (1) incorrecto y (2) insatisfactorio. Estoy buscando una solución alternativa que no sea la creación personalizada del área no cliente.
En cualquier versión actualizada de Windows Insider (build> = 14342, SDK version #> = 14332) hay una API EnableNonClientDpiScaling (que toma un HWND como argumento) que habilitará la escala de DPI sin cliente para las HWND de nivel superior . Esta funcionalidad requiere que la ventana de nivel superior se ejecute en el modo de percepción DPI por monitor. Esta API debe invocarse desde el controlador WM_NCCREATE para la ventana. Cuando se llama a esta API en una ventana de nivel superior, su barra de título, barras de desplazamiento de nivel superior, menú del sistema y barra de menús aumentarán cuando el DPI de la aplicación cambie (esto puede suceder cuando la aplicación se mueve a una pantalla con una escala de visualización diferente) valor o cuando el DPI cambia por otros motivos, como por ejemplo que el usuario cambie de configuración o cuando una conexión RDP cambie el factor de escala).
Esta API no admite la ampliación del área no cliente para ventanas secundarias, como barras de desplazamiento en una ventana secundaria.
Que yo sepa, no hay forma de tener una escala DPI sin área de cliente automáticamente sin esta API.
Tenga en cuenta que esta API aún no se ha finalizado y puede cambiar antes de publicarse en la actualización de Windows 10 Anniversary. Manténgase atento a MSDN para obtener documentación oficial cuando sea definitiva.