Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Low/High DPI zur Laufzeit ändern? (https://www.delphipraxis.net/198573-low-high-dpi-zur-laufzeit-aendern.html)

romber 15. Nov 2018 12:55

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!

ChrisE 15. Nov 2018 13:10

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

Uwe Raabe 15. Nov 2018 13:29

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 SetProcessDpiAwarenessContext den Weg über das Manifest.

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.

DieDolly 15. Nov 2018 13:37

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.

bcvs 15. Nov 2018 14:03

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.

hoika 15. Nov 2018 14:52

AW: Low/High DPI zur Laufzeit ändern?
 
Hallo
clevere Idee von bcvs.

romber 15. Nov 2018 22:37

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.

Uwe Raabe 15. Nov 2018 23:09

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.

romber 16. Nov 2018 10:55

AW: Low/High DPI zur Laufzeit ändern?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1418186)
Du musst sicher stellen, daß der Call vor allen anderen DPI-API Aufrufen abgesetzt wird. Andernfalls wirkt er nicht mehr.

Wo setzte ich den diesen Call am besten ab? Wenn ich die Funktion vor Application.Initialize; passiert das, was ich beschrieben habe.

rabatscher 16. Nov 2018 11:48

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.

Thomasl 22. Jul 2021 15:13

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;

Thomasl 30. Jul 2021 11:56

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 08:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz