![]() |
Low/High DPI zur Laufzeit ändern?
Hallo,
ich habe meine Anwendung für hohe Auflösungen aufwenfig angepasst. Jetzt sieht der GUI auch bei hohen Auflösungen und Skallierungen bis zu einem gewissen Grad schön und sehr scharf aus. Einige Testpersonen finden die Anzeige aber zu scharf und würden gerne zu der alten gewohnten Anzeige zurückkehren. Das Problem ist aber, dass die hohe Auflösung bereits im Manifest der Anwendung festgelegt wird so, dass ich jetzt eine zweite Datei ohne die High DPI-Unterstützung bereitstellen müsste. Gibt es den keine vennünftige Möglichkeit, die hohe Auflösung zur Laufzeit (z.B. bei der Initialisierung der Anwendung) zu aktivieren/deaktivieren, ohne dass ich den ganzen Code umnkrempeln muss? Danke! |
AW: Low/High DPI zur Laufzeit ändern?
Hallo,
im Prinzip nennst du die Lösung bereits elber. Die Tatsache der "hohen Auflösung" bzw. ob Windows für dich Skaliert oder es die Anwendung selber skaliert steht im Manifest. Niemand zwingt dich das Manifest in die EXE zu integrieren. Du kannst Delphi "bitten" kein Manifest zu integrieren und das externe Manifest selber als Datei mit ausliefern. Bei der Umstellung durch den Anwender musst du dann das externe Manifest ändern. Nach einem Neustart sollte das dann funktionieren. Gruß, Chris |
AW: Low/High DPI zur Laufzeit ändern?
Prinzipiell gibt es schon eine Möglichkeit innerhalb des Programms die DPI-Unterstützung anzumelden. Allerdings empfiehlt Microsoft selbst im ersten Satz der Dokumentation zu
![]() Ich selbst würde es auch lieber über diese Funktion machen. Dann hätte man die Möglichkeit, auf unterschiedliche Windows 10 Releases auch unterschiedlich zu reagieren. Nicht alle PerMonitorV2 fähigen Systeme machen ihre Arbeit wirklich gut. Man könnte dann von DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 auf DPI_AWARENESS_CONTEXT_UNAWARE herunterschalten, wenn die Windows Version das nicht gut genug macht. |
AW: Low/High DPI zur Laufzeit ändern?
Deine GUI sieht, könnte man vermuten, gut aus und alles ist am richtigen Platz. Du hast nur ein Schärfeproblem.
Solchen Geschichten würde ich mich gar nicht hingeben und den paar Leuten die eine Extrawurst haben wollen einen Gefallen tun. |
AW: Low/High DPI zur Laufzeit ändern?
Ich habe mir für genau diesen Zweck mit InnoSetup ein kleines Setup gebaut, dass je nach Auswahl eine Manifest-Datei als <MeinProjekt>.exe.manifest entweder mit oder ohne HighDpi-Unterstützung ins Programmverzeichnis kopiert.
In der eigentlichen Exe meines Projeks ist kein Manifest enthalten. Der Benutzer kann das Setup jederzeit aufrufen und nach einem Neustart von <MeinProjekt>.exe ist die HighDpi-Unterstützung umgestellt. |
AW: Low/High DPI zur Laufzeit ändern?
Hallo
clevere Idee von bcvs. |
AW: Low/High DPI zur Laufzeit ändern?
Vielen Dank für Eure Anregungen. SetProcessDPIAwareness sieht gut aus, werde es mir genauer anschauen. Mit den ersten einfachen Test konnte ich zwar die low/high DPI teilweise zur Laufzweit erzwingen, alledings viele der Drittanbieter-Komponente, wie z.B. DevExpress Grid und Bar Suite, spielen (noch) nicht richtig mit. Erstaunlicherweise sind es meistens genau die Bibliotheken, die HighDPI out-of-box unterstützen, wenn mann entsprechenden Kästchen in den Projekteinstellungen aktiviert.
|
AW: Low/High DPI zur Laufzeit ändern?
Du musst sicher stellen, daß der Call vor allen anderen DPI-API Aufrufen abgesetzt wird. Andernfalls wirkt er nicht mehr.
|
AW: Low/High DPI zur Laufzeit ändern?
Zitat:
|
AW: Low/High DPI zur Laufzeit ändern?
Wir benutzen folgende Unit um das Per Registry zu erledigen:
Die Unit muss unbedingt als erstes (bzw. gleich nach der memory manager unit) eingefügt werden.
Delphi-Quellcode:
unit HighDPIInit;
// note this unit needs to be added to the project BEFORE any unit that uses controls.pas!!!! // -> otherwise the screen variable is wrongly initialized interface const Process_DPI_Unaware = 0; Process_System_DPI_Aware = 1; Process_Per_Monitor_DPI_Aware = 2; type TSetProcessDPIAwareness = function (value : LongWord) : HRESULT; stdcall; var setProcessDPIAwareness : TSetProcessDPIAwareness; hdl : THandle; implementation uses Windows, registry, DarwinConsts; initialization with TRegIniFile.Create('', KEY_READ or KEY_WOW64_64KEY) do try RootKey := HKEY_LOCAL_MACHINE; OpenKey('your section here', False); if not ReadBool('','HighDPIAware', False) then exit; finally Free; end; // ############################################### // #### Enable high dpi awareness // ############################################### hdl := LoadLibrary('Shcore.dll'); if hdl <> 0 then begin setProcessDPIAwareness := GetProcAddress(hdl, 'SetProcessDpiAwareness'); if Assigned(setProcessDPIAwareness) then setProcessDPIAwareness(Process_System_DPI_Aware); FreeLibrary(hdl); end; end. |
AW: Low/High DPI zur Laufzeit ändern?
Ab Windows10 1809 gibt es ja UnawareGdiScaled
Das Funktioniert sogar. Alle Schriften sind mit voller Auflösung scharf. Oder auch selbst gemaltes mit GDI+. Ohne jetzt mit viel Aufwand ein ganzes Programm auf PerMonitorAwareV2 zu ändern. Jetzt zum Problem. Das geht nur wenn DoubleBuffered aus ist. Sonst ist es unscharf wie vorher. Also ohne DoubleBuffered und ParentBackground Flackert es. Bekommt man das Flackern auch ohne DoubleBuffered weg? Bei GDI mache ich schon nur Invalidate, dann zeichnet alles in einem rutsch Bei ehr Statischen Programmen ist es OK mit UnawareGdiScaled ein und DoubleBuffered aus. Aber nicht bei einem HMI wo sich viel oft ändert. (Jetzt noch Delphi XE4)
Delphi-Quellcode:
const
Context_Undefined = 0; Context_Unaware = -1; Context_SystemAware = -2; Context_PerMonitorAware = -3; Context_PerMonitorAwareV2 = -4; Context_UnawareGdiScaled = -5; type TSetProcessDPIAwarenessContext = function(value: Integer): HRESULT; stdcall; var setProcessDPIAwarenessContext: TSetProcessDPIAwarenessContext; hd2: THandle; hr: HRESULT; hd2 := LoadLibrary('user32.dll'); if hd2 <> 0 then begin setProcessDPIAwarenessContext := GetProcAddress(hd2, 'SetProcessDpiAwarenessContext'); if Assigned(setProcessDPIAwarenessContext) then begin hr := setProcessDPIAwarenessContext(Context_UnawareGdiScaled); end; FreeLibrary(hd2); end; |
AW: Low/High DPI zur Laufzeit ändern?
So geht es auch bei x64
Code:
{$IFDEF WIN64}
TSetProcessDPIAwarenessContext = function(value: Int64): HRESULT; stdcall; {$ELSE} TSetProcessDPIAwarenessContext = function(value: Integer): HRESULT; stdcall; {$ENDIF} |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz