UI Automation y ajuste de escala de la pantalla
Nota
Esta documentación está dirigida a los desarrolladores de .NET Framework que quieran usar las clases de automatización de la interfaz de usuario administradas definidas en el espacio de nombres System.Windows.Automation. Para ver la información más reciente acerca de la automatización de la interfaz de usuario, consulte Windows Automation API: automatización de la interfaz de usuario.
A partir de Windows Vista, Windows permite a los usuarios cambiar la configuración de puntos por pulgada (ppp) para que la mayoría de los elementos de la interfaz de usuario (UI) en la pantalla aparezcan más grandes. Aunque esta característica ha estado disponible desde hace mucho tiempo en Windows, en las versiones anteriores, el escalado se tenía que implementar por las aplicaciones. A partir de Windows Vista, el Administrador de ventanas de escritorio realiza el ajuste de escala predeterminado para todas las aplicaciones que no controlan su propia escala. Las aplicaciones cliente de automatización de la interfaz de usuario deben tener en cuenta esta característica.
Escalado en Windows Vista
La configuración de ppp predeterminada es 96, lo que significa que 96 píxeles ocupan el ancho o el alto de una pulgada teórica. La medida exacta de una "pulgada" depende del tamaño y de la resolución física del monitor. Por ejemplo, en un monitor de 12 pulgadas de ancho, con una resolución horizontal de 1280 píxeles, una línea horizontal de 96 píxeles se amplía aproximadamente 9/10 de una pulgada.
Cambiar la configuración de ppp no es lo mismo que cambiar la resolución de pantalla. Con el ajuste de escala ppp , el número de píxeles físicos de la pantalla sigue siendo el mismo. Sin embargo, se aplica el ajuste de escala al tamaño y a la ubicación de los elementos UI. Este ajuste de escala se puede realizar automáticamente mediante el Administrador de ventanas de escritorio (DWM) para el escritorio y para las aplicaciones que no solicitan explícitamente para cambiar de escala.
En efecto, cuando el usuario establece el factor de escala en 120 ppp, una pulgada vertical u horizontal en la pantalla aumenta en un 25 por ciento. Todas las dimensiones se escalan en consecuencia. El desplazamiento de una ventana de aplicación desde los bordes superior e izquierdo de la pantalla aumenta en un 25 por ciento. Si el ajuste de escala de aplicación está habilitado y la aplicación no es para ppp, el tamaño de la ventana aumenta en la misma proporción, junto con los desplazamientos y los tamaños de todos los elementos UI que contiene.
Nota
De forma predeterminada, el DWM no realiza el ajuste de escala para aplicaciones que no son de ppp cuando el usuario establece ppp en 120, pero lo realiza cuando ppp se establece en un valor personalizado de 144 o superior. Sin embargo, el usuario puede invalidar el comportamiento predeterminado.
El escalado de pantalla crea nuevos desafíos para las aplicaciones a las que les preocupa de cualquier manera las coordenadas de pantalla. La pantalla contiene ahora dos sistemas de coordenadas: físico y lógico. Las coordenadas físicas de un punto son el desplazamiento real en píxeles desde la parte superior izquierda del origen. Las coordenadas lógicas son los desplazamientos de la manera que serían si se escalaran los propios píxeles.
Supongamos que diseña un cuadro de diálogo con un botón en las coordenadas (100, 48). Cuando este cuadro de diálogo se muestre en el ppp 96 predeterminado, el botón se encuentra en las coordenadas físicas (100, 48). En 120 ppp, se encuentra en las coordenadas físicas (125, 60). Sin embargo, las coordenadas lógicas son las mismas en cualquier configuración ppp: (100, 48).
Las coordenadas lógicas son importantes porque hacen que el comportamiento del sistema operativo y las aplicaciones sea coherente independientemente de la configuración de ppp. Por ejemplo, Cursor.Position normalmente devuelve las coordenadas lógicas. Si mueve el cursor sobre un elemento en un cuadro de diálogo, se devuelven las mismas coordenadas con independencia de la configuración ppp. Si dibuja un control en (100, 100), se dibuja con esas coordenadas lógicas y ocupará la misma posición relativa en cualquier configuración ppp.
Escalado en los clientes de automatización de la interfaz de usuario
La API de UI Automation no usa coordenadas lógicas. Los siguientes métodos y propiedades devuelven coordenadas físicas o las toman como parámetros.
De manera predeterminada, una aplicación de cliente de automatización de la interfaz de usuario que se está ejecutando en un entorno que no sea de 96 ppp no podrá obtener resultados correctos de estos métodos y propiedades. Por ejemplo, dado que la posición del cursor se encuentra en coordenadas lógicas, el cliente no podrá pasar simplemente estas coordenadas a FromPoint para obtener el elemento que se encuentra debajo del cursor. Además, la aplicación no podrá colocar correctamente ventanas fuera de su área de cliente.
La solución consta de dos partes.
En primer lugar, haga que la aplicación cliente sea para ppp. Para ello, llame a la función Win32
SetProcessDPIAware
al inicio. En código administrado, la siguiente declaración hace que esta función esté disponible.[System.Runtime.InteropServices.DllImport("user32.dll")] internal static extern bool SetProcessDPIAware();
<System.Runtime.InteropServices.DllImport("user32.dll")> _ Friend Shared Function SetProcessDPIAware() As Boolean End Function
Esta función hace que todo el proceso sea para ppp, lo que significa que todas las ventanas que pertenecen al proceso sean sin escala. En Highlighter Sample, por ejemplo, las cuatro ventanas que componen el rectángulo resaltado se encuentran en las coordenadas físicas obtenidas de UI Automation, y no en las coordenadas lógicas. Si el ejemplo no era para ppp, el resaltado se dibujaría en las coordenadas lógicas del escritorio, lo que daría lugar a una ubicación incorrecta en un entorno que no sea de 96 ppp.
Para obtener las coordenadas del cursor, llame a la función Win32
GetPhysicalCursorPos
. En el ejemplo siguiente se muestra cómo declarar y usar esta función.public struct CursorPoint { public int X; public int Y; } [System.Runtime.InteropServices.DllImport("user32.dll")] internal static extern bool GetPhysicalCursorPos(ref CursorPoint lpPoint); private bool ShowUsage() { CursorPoint cursorPos = new CursorPoint(); try { return GetPhysicalCursorPos(ref cursorPos); } catch (EntryPointNotFoundException) // Not Windows Vista { return false; } }
Structure CursorPoint Public X As Integer Public Y As Integer End Structure <System.Runtime.InteropServices.DllImport("user32.dll")> _ Friend Shared Function GetPhysicalCursorPos(ByRef lpPoint As CursorPoint) As Boolean End Function Private Function ShowUsage() As Boolean Dim cursorPos As New CursorPoint() Try Return GetPhysicalCursorPos(cursorPos) Catch e As EntryPointNotFoundException ' Not Windows Vista Return False End Try End Function
Precaución
No use Cursor.Position. El comportamiento de esta propiedad fuera de las ventanas de cliente en un entorno de escala es indefinido.
Si su aplicación realiza una comunicación directa entre procesos con aplicaciones no compatibles con ppp, es posible que tenga que convertir entre coordenadas lógicas y físicas utilizando las funciones Win32 PhysicalToLogicalPoint
y LogicalToPhysicalPoint
.