Benutzeroberflächenautomatisierung und Bildschirmskalierung
Hinweis
Diese Dokumentation ist für .NET Framework-Entwickler konzipiert, die die verwalteten Klassen zur Automatisierung der Benutzeroberfläche verwenden möchten, die im Namespace System.Windows.Automation definiert sind. Aktuelle Informationen zur Automatisierung der Benutzeroberfläche finden Sie auf der Seite zur Windows-Automatisierungs-API: Benutzeroberflächenautomatisierung.
Seit Windows Vista können Benutzer*innen unter Windows die DPI-Einstellung (Dots Per Inch, Punkte pro Zoll) so ändern, dass die meisten Benutzeroberflächenelemente auf dem Bildschirm größer erscheinen. Obwohl dieses Feature unter Windows bereits seit längerem verfügbar ist, musste die Skalierung in früheren Versionen von Anwendungen implementiert werden. In Windows Vista führt der Desktopfenster-Manager standardmäßig die Skalierung für alle Anwendungen aus, die nicht ihre eigene Skalierung übernehmen. Benutzeroberflächenautomatisierungs-Clientanwendungen müssen dieses Feature berücksichtigen.
Skalierung in Windows Vista
Die DPI-Standardeinstellung ist 96, d. h. 96 Pixel belegen eine Breite oder Höhe eines angenommenen Zolls. Das genaue Maß für ein „Zoll“ ist abhängig von der Größe und der physischen Auflösung des Monitors. Auf einem Monitor mit einer Breite von 12 Zoll bei einer horizontalen Auflösung von 1280 Pixel erstreckt sich eine horizontale Linie von 96 Pixeln beispielsweise über etwas 9/10 eines Zolls.
Das Ändern der DPI-Einstellung ist nicht dasselbe wie das Ändern der Bildschirmauflösung. Mit der DPI-Skalierung bleibt die Anzahl der physischen Pixel auf dem Bildschirm unverändert. Die Skalierung wird jedoch auf die Größe und Position der Benutzeroberflächenelemente angewendet. Diese Skalierung kann vom Desktopfenster-Manager (DWM) für den Desktop und für Anwendungen automatisch durchgeführt werden , die nicht ausdrücklich danach verlangen, nicht skaliert zu werden.
Wenn der Benutzer den Skalierungsfaktor auf 120 DPI festlegt, wird ein vertikales oder horizontales Zoll auf dem Bildschirm um 25 Prozent vergrößert. Alle Dimensionen werden entsprechend skaliert. Der Offset eines Anwendungsfensters vom oberen und linken Rand des Bildschirms wird um 25 Prozent erhöht. Wenn die Anwendungsskalierung aktiviert ist und die Anwendung nicht DPI-fähig ist, wird das Fenster zusammen mit den Offsets und Größen aller darin enthaltenen Benutzeroberflächenelemente im selben Verhältnis vergrößert.
Hinweis
Standardmäßig führt der Desktopfenster-Manager keine Skalierung für nicht DPI-fähige Anwendungen durch, wenn der Benutzer für DPI den Wert 120 festlegt. Die Skalierung wird jedoch ausgeführt, wenn für DPI ein benutzerdefinierter Wert von 144 oder höher festgelegt wird. Das Standardverhalten kann vom Benutzer jedoch außer Kraft gesetzt werden.
Die Bildschirmskalierung stellt an Anwendungen neue Herausforderungen, die sich in irgendeiner Weise mit Bildschirmkoordinaten befassen. Der Bildschirm enthält jetzt zwei Koordinatensysteme: ein physisches und ein logisches. Die physischen Koordinaten eines Punkts stellen den tatsächlichen Offset in Pixeln vom oberen linken Rand des Ursprungs dar. Die logischen Koordinaten sind die Offsets, die sich ergeben würden, wenn die Pixel selbst skaliert würden.
Angenommen, Sie entwerfen ein Dialogfeld mit einer Schaltfläche an den Koordinaten (100, 48). Wenn dieses Dialogfeld mit den standardmäßigen 96 DPI angezeigt wird, befindet sich die Schaltfläche an den physischen Koordinaten (100, 48). Bei 120 DPI befindet sie sich an den physischen Koordinaten (125, 60). Aber die logischen Koordinaten sind bei jeder DPI-Einstellung dieselben: (100, 48).
Logische Koordinaten sind wichtig, da sie für Betriebssystem und Anwendungen unabhängig von der DPI-Einstellung für ein konsistentes Verhalten sorgen. Cursor.Position gibt z. B. normalerweise die logischen Koordinaten zurück. Wenn Sie den Cursor über ein Element in einem Dialogfeld bewegen, werden unabhängig von der DPI-Einstellung dieselben Koordinaten zurückgegeben. Wenn Sie ein Steuerelement an den Koordinaten (100, 100) darstellen, wird es an diesen logischen Koordinaten angezeigt und belegt bei einer beliebigen DPI-Einstellung dieselbe relative Position.
Skalierung in Benutzeroberflächenautomatisierungs-Clients
Die Benutzeroberflächenautomatisierungs-API verwendet keine logischen Koordinaten. Die folgenden Methoden und Eigenschaften geben entweder physische Koordinaten zurück oder verwenden sie als Parameter.
Standardmäßig kann eine Benutzeroberflächenautomatisierungs-Clientanwendung, die in einer Umgebung mit einer anderen Einstellung als 96 DPI ausgeführt wird, mit diesen Methoden und Eigenschaften keine richtigen Ergebnisse erzielen. Da die Cursorposition z. B. in logischen Koordinaten angegeben wird, kann der Client diese Koordinaten nicht einfach an FromPoint übergeben, um das Element abzurufen, das sich unter dem Cursor befindet. Darüber hinaus ist die Anwendung nicht in der Lage, Fenster außerhalb seines Clientbereichs ordnungsgemäß zu platzieren.
Die Lösung besteht aus zwei Teilen.
Sorgen Sie dafür, dass die Clientanwendung DPI-fähig ist. Rufen Sie dazu die Win32-Funktion
SetProcessDPIAware
beim Start auf. Die folgende Deklaration stellt diese Funktion in verwaltetem Code zur Verfügung.[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
Diese Funktion sorgt dafür, dass der gesamte Prozess DPI-fähig ist, d. h. alle zum Prozess gehörenden Fenster werden nicht skaliert. Im Beispiel für Hervorhebungbefinden sich die vier Fenster, die das hervorgehobene Rechteck bilden, beispielsweise an den physischen Koordinaten, die von der Benutzeroberflächenautomatisierung abgerufen werden, und nicht an den logischen Koordinaten. Wenn das Beispiel nicht DPI-fähig wäre, würde die Hervorhebung an den logischen Koordinaten auf dem Desktop dargestellt werden. Dies würde zu einer falschen Platzierung in einer Umgebung mit einer anderen Einstellung als 96 DPI führen.
Rufen Sie die Win32-Funktion
GetPhysicalCursorPos
auf, um Cursorkoordinaten abzurufen. Im folgenden Beispiel wird das Deklarieren und Verwenden dieser Funktion veranschaulicht.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
Achtung
Verwenden Sie nicht Cursor.Position. Das Verhalten dieser Eigenschaft außerhalb der Clientfenster in einer skalierten Umgebung ist nicht definiert.
Wenn Ihre Anwendung direkt prozessübergreifend mit nicht DPI-fähigen Anwendungen kommuniziert, müssen Sie mithilfe der Win32-Funktionen PhysicalToLogicalPoint
und LogicalToPhysicalPoint
möglicherweise zwischen logischen und physischen Koordinaten konvertieren.