DPI-Skalierung ist eine Funktion, die entweder vom Betriebssystem oder von der Applikation ausgeführt wird, um die sichtbare Größe des Inhalts proportional zur DPI-Einstellung (Dots Per Inch, dt. Punkte pro Zoll) des Bildschirms zu vergrößern. Grundsätzlich ermöglicht diese Funktion, dass Inhalte auf Systemen mit unterschiedlichen Bildschirmauflösungen in der gleichen physischen Größe dargestellt werden oder zumindest auf sehr hochauflösenden Bildschirmen benutzbar sind. Manchmal erhöht ein Benutzer die DPI-Einstellung, um Inhalte größer zu machen und besser lesen zu können.
A_ScreenDPI gibt üblicherweise die DPI-Einstellung zurück, die der primäre Bildschirm zum Zeitpunkt des Skriptstarts hatte. Dies wird als "System-DPI" bezeichnet, obwohl Prozesse, die zu unterschiedlichen Zeitpunkten gestartet werden, unterschiedliche Werte aufweisen können.
Es gibt zwei verschiedene DPI-Skalierungen, die etwas mit AutoHotkey zu tun haben: Gui-DPI-Skalierung und OS-DPI-Skalierung.
Standardmäßig führen die Gui- und GuiControl-Methoden/Eigenschaften eine automatische Skalierung durch, so dass GUI-Skripte mit hartkodierten Positionen, Größen und Abständen auf Bildschirmen mit hohem DPI-Wert angemessen skaliert werden. Wenn dies negative Auswirkungen auf das Skript hat oder das Skript die Skalierung selbst vornimmt, kann die automatische Skalierung deaktiviert werden. Weitere Informationen finden Sie unter der Option -DPIScale.
Bei Applikationen, die nicht DPI-sensitiv sind, führt das Betriebssystem automatisch eine Skalierung für Koordinaten durch, die an bestimmte Systemfunktionen übergeben und von diesen zurückgegeben werden. Diese Art der Skalierung betrifft AutoHotkey in der Regel in zwei Szenarien:
Welche Skalierung genau vorgenommen wird, hängt von drei Faktoren ab: 1) von der aufgerufenen Systemfunktion, 2) von der DPI-Sensitivität des Skripts und 3) ggf. von der DPI-Sensitivität des Zielfensters.
In Windows 8.1 und höher können sekundäre Bildschirme unterschiedliche DPI-Einstellungen haben. Von "pro-Bildschirm-DPI-sensitiven" Applikationen wird erwartet, dass sie ihre Fenster entsprechend dem DPI-Wert des Bildschirms skalieren, auf dem sie sich gerade befinden, und sich dynamisch anpassen, wenn das Fenster zwischen den Bildschirmen hin- und hergeschoben wird.
Bei Applikationen, die nicht pro-Bildschirm-DPI-sensitiv sind, führt das System eine Bitmap-Skalierung durch, damit die Fenster ihre Größe ändern können, wenn sie zwischen den Bildschirmen hin- und hergeschoben werden, und verbirgt dies vor der Applikation, indem die Koordinaten und Größen auf die globale DPI-Einstellung skaliert werden, die die Applikation erwartet. Auf einem 11-Zoll-4K-Bildschirm wäre z.B. eine GUI, die für die Darstellung auf 96 dpi (100 %) ausgelegt ist, praktisch unbenutzbar, während eine Skalierung auf 200 % sie benutzbar machen würde.
AutoHotkey v2.0 ist nicht für die Durchführung einer Pro-Bildschirm-Skalierung ausgelegt und wurde daher nicht als pro-Bildschirm-DPI-sensitiv gekennzeichnet. Dies ist z.B. vorteilhaft, wenn ein GUI-Fenster zwischen einem großen externen Bildschirm mit 100 % DPI und einem kleineren Bildschirm mit 200 % DPI hin- und hergeschoben wird. Die automatische Skalierung hat jedoch auch negative Auswirkungen.
Damit die automatische Skalierung des Systems funktioniert, werden Koordinaten, die von Systemfunktionen wie MoveWindow und GetWindowRect akzeptiert oder zurückgegeben werden, automatisch skaliert. Wenn AutoHotkey diese Funktionen verwendet, um mit externen Fenstern zu arbeiten, führt dies oft zu unerwarteten Ergebnissen, wenn sich die Koordinaten nicht auf dem primären Bildschirm befinden. Erschwerend kommt hinzu, dass einige Funktionen die Koordinaten auf Basis des Bildschirms skalieren, auf dem das zuletzt aktive Fenster des Skripts angezeigt wurde.
In Windows 10 Version 1607 und höher kann die Systemfunktion SetThreadDpiAwarenessContext verwendet werden, um die DPI-Sensitivitätseinstellung des Programms während der Ausführung zu ändern. Wenn Sie z.B. die Pro-Bildschirm-DPI-Sensitivität aktivieren, wird die systemseitige Skalierung deaktiviert, so dass interne Funktionen wie WinMove und WinGetPos Koordinaten (in Pixel) unabhängig von der DPI-Skalierung akzeptieren oder zurückgeben können. Wenn jedoch die Größe einer GUI für einen Bildschirm mit 100 % DPI ausgelegt ist und dann auf einen Bildschirm mit 200 % DPI verschoben wird, passt sie sich nicht automatisch an und kann unbenutzbar werden.
Um die Pro-Bildschirm-DPI-Sensitivität zu aktivieren, rufen Sie die folgende Funktion auf, bevor Sie Funktionen verwenden, die normalerweise von der DPI-Skalierung betroffen sind:
DllCall("SetThreadDpiAwarenessContext", "ptr", -3, "ptr")
In Windows 10 Version 1703 und höher kann -3 mit -4 ersetzt werden, um den Modus "Per Monitor v2" zu aktivieren. Dies ermöglicht die Skalierung von Dialogfenstern, Menüs, Tooltips und einigem mehr. Allerdings wird dadurch auch der Nicht-Clientbereich (Titelleiste) skaliert, was wiederum dazu führen kann, dass der Clientbereich des Fensters zu klein wird, es sei denn, das Skript ist so konzipiert, dass es sich daran anpasst (z.B. durch Reaktion auf die WM_DPICHANGED-Meldung). Dies lässt sich vermeiden, indem der Kontext vor der Erstellung der GUI auf -3 oder vor der Erstellung von Tooltips, Menüs oder Dialogfenstern auf -4 gesetzt wird.
Wenn das System die Fensterprozedur für ein Fenster aufruft, wird der aktuelle DPI-Sensitivität-Kontext automatisch auf den Kontext gesetzt, der bei der Erstellung des Fensters verwendet wurde. Der Kontext für einen neuen Skript-Thread hängt also davon ab, ob er direkt aus der Meldungsschleife von AutoHotkey oder über eine Fensterprozedur gestartet wurde.
Es wird erwartet, dass sich ein pro-Bildschirm-DPI-sensitives GUI-Fenster automatisch anpasst, wenn es eine WM_DPICHANGED-Meldung erhält. AutoHotkey-v2.0-GUI-Fenster reagieren standardmäßig nicht auf diese Meldung. Wenn die korrekte Implementierung dieser Art von dynamischer Skalierung zu schwierig ist, wäre eine einfachere Alternative die temporäre Deaktivierung der Pro-Bildschirm-DPI-Sensitivität unmittelbar vor der Erstellung der GUI. Zum Beispiel:
; System-DPI-Sensitivität-Modus setzen (Standard in AutoHotkey v2.0): try dac := DllCall("SetThreadDpiAwarenessContext", 'ptr', -2, 'ptr') ; GUI erstellen, die permanent "System-DPI-sensitiv" sein wird: MeineGui := Gui() ; Vorherigen Modus für alle nachfolgenden Funktionsaufrufe wiederherstellen: IsSet(dac) && DllCall("SetThreadDpiAwarenessContext", 'ptr', dac, 'ptr')
Die zusätzlichen Zeilen sind wirkungslos, wenn das Betriebssystem SetThreadDpiAwarenessContext nicht unterstützt oder das Programm bereits im System-DPI-Sensitivität-Modus war.
Wenn nur einige der GUI-Steuerelemente nicht gut skaliert werden, können die System-DPI-sensitiven (oder nicht-System-DPI-sensitiven) Steuerelemente in einem pro-Bildschirm-DPI-sensitiven Fenster gehostet werden. Ein gemischtes Hosting muss vor dem Erstellen des Fensters aktiviert werden (benötigt Windows 10 Version 1803 oder höher):
; GUI-Fenster erstellen, das sensitivschwächere Unterfenster hosten kann: try dhb := DllCall("SetThreadDpiHostingBehavior", 'int', 1) MeineGui := Gui() IsSet(dhb) && DllCall("SetThreadDpiHostingBehavior", 'int', dhb) ; "System-DPI-sensitives" Steuerelement hinzufügen: try dac := DllCall("SetThreadDpiAwarenessContext", 'ptr', -2, 'ptr') MeineListView := MeineGui.AddListView() IsSet(dac) && DllCall("SetThreadDpiAwarenessContext", 'ptr', dac, 'ptr')
Pro-Bildschirm-DPI-Sensitivität kann prozessübergreifend durch Setzen der Elemente "dpiAware" und "dpiAwareness" im Manifest des kompilierten Skripts (eine eingebettete XML-Ressource) aktiviert werden. Einzelheiten über die ordnungsgemäße Verwendung und die Auswirkungen dieser Einstellungen finden Sie unter Standardsensitivität mit dem Manifest der Applikation setzen. Zum Beispiel enthält das Manifest von AutoHotkey v2.0.19 die folgenden Angaben:
<v3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> <dpiAware>true</dpiAware> <ws2:longPathAware>true</ws2:longPathAware> </v3:windowsSettings>
Wie in der Microsoft-Dokumentation erläutert, kann es sinnvoll sein, sowohl "dpiAware" als auch "dpiAwareness" einzufügen, die unterschiedlichen XML-Namensräumen angehören. Da "longPathAware" und "dpiAwareness" demselben Namensraum angehören, lässt sich die XML-Datei durch das Verschieben einiger Elemente optimieren. Die folgenden Angaben aktivieren die Pro-Bildschirm-DPI-Sensitivität (v2, falls verfügbar, andernfalls v1):
<v3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <dpiAwareness>PerMonitorV2</dpiAwareness> <longPathAware>true</longPathAware> </v3:windowsSettings>
Die standardmäßige DPI-Sensitivität des Programms kann mit den Kompatibilitätseinstellungen überschrieben werden. Diese Einstellungen können in den Eigenschaften einer AutoHotkey-EXE-Datei, in den Eigenschaften einer Verknüpfungsdatei oder durch Setzen der Umgebungsvariable __COMPAT_LAYER
mit dem Schlüsselwort DpiUnaware
oder dem Schlüsselwort HighDpiAware
festgelegt werden. Diese Aktivierungsmethode der DPI-Sensitivität kann unerwünschte Nebenwirkungen haben. So kann es beispielsweise vorkommen, dass sich MsgBox-Fenster nicht automatisch anpassen, wenn sie von einem Bildschirm zum anderen verschoben werden.