"High DPI" selbst einstellen?

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

"High DPI" selbst einstellen?

Beitrag von Soner »

Kann man irgendwie LCL-Programm vorgaukeln, dass man hochauflösenden Monitor hat?

Das Problem ist folgendes, ich habe ein Programm, dass ich auf 96ppi-Monitor erstellt habe. Dieses Programm soll auch auf einigen Touchscreen-Monitoren laufen, welche auch 96ppi hat, keine Tastatur und Maus nur Touchscreen-Monitor.
Ich habe im Programm große Bilder, Buttons und Schriften benutzt, damit die Leute mit Touchsreen-Monitor leichter benutzen können, aber nun ist es für die anderen Benutzer alles bißchen größer.
Ich könnte es optional alles im Programm selber einstellen, aber mir ist die Idee gekommen, "High DPI"-Eigenschaft von Lazarus zu benutzen und das Programm einmal designen und am Zielcomputer das Programm vorgaukeln, dass man hochauflösenden Monitor hat, dann würde alles automatisch vergrößert und man hätte weniger Programmierarbeit.

Michl
Beiträge: 2463
Registriert: Di 19. Jun 2012, 12:54

Re: "High DPI" selbst einstellen?

Beitrag von Michl »

Soner hat geschrieben:
Sa 5. Jun 2021, 12:47
Kann man irgendwie LCL-Programm vorgaukeln, dass man hochauflösenden Monitor hat?
Natürlich, zum Testen nutze ich die Möglichkeit öfters.
Z.B. Windows 7: Rechtsklick auf Desktop (vom OS, nicht der IDE), sodaß sich das Popup öffnet -> Bildschirmauflösung -> Text und Elemente vergrößern -> Kleiner (96DPI) / Mittel (120DPI) / Größer (144DPI) auswählen. Man kann auch eine individuelle DPI festlegen.
Mit den Linux Distributionen in der VM verfahre ich ähnlich über die Systemeinstellungen - weiß ich jetzt aber nicht aus dem Kopf.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

wp_xyz
Beiträge: 4016
Registriert: Fr 8. Apr 2011, 09:01

Re: "High DPI" selbst einstellen?

Beitrag von wp_xyz »

Achtung bei Windows (wenigstens): Wenn plötzlich der Bildschirm kleiner wird, versucht Windows die Desktop-Icons auf dem kleineren Platz unterzubringen. Das ist ok, aber wenn du wieder zur größeren Auflösung zurückgehst, kehren sie nicht zurück -- sehr ärgerlich, wenn man sich für die Anordnung der Icons eine bestimmte Logik ausgedacht hat. Ich verwende das Programm DesktopOK (https://www.softwareok.de/?seite=Freeware/DesktopOK), um die Icon-Positionen in einer Datei zu speichern und ggfs daraus wieder zu restaurieren.

Aber eigentlich habe ich mein "High-DPI" Windows als Win7 in einer VM. Dann kann ich das Programm auch gleich unter einer anderen Window-Version testen. Das Starten der VM dauert in etwa ähnlich lang wie das An- und Abmelden, das auch heute noch für den DPI-Wechsel nötig ist. Und außerdem kann im Fall von High-DPI Problemen dann einfach in die normale Umgebung zurückwechseln und den Fehler korrigieren.

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

Michl hat geschrieben:
Sa 5. Jun 2021, 13:13
Soner hat geschrieben:
Sa 5. Jun 2021, 12:47
Kann man irgendwie LCL-Programm vorgaukeln, dass man hochauflösenden Monitor hat?
Natürlich, zum Testen nutze ich die Möglichkeit öfters.
Z.B. Windows 7: Rechtsklick auf Desktop (vom OS, nicht der IDE), sodaß sich das Popup öffnet -> Bildschirmauflösung -> Text und Elemente vergrößern -> Kleiner (96DPI) / Mittel (120DPI) / Größer (144DPI) auswählen. Man kann auch eine individuelle DPI festlegen.
Mit den Linux Distributionen in der VM verfahre ich ähnlich über die Systemeinstellungen - weiß ich jetzt aber nicht aus dem Kopf.
Das kenne ich schon. Am Betriebssystem soll nichts geändert werden, nur an meinem Program.

Ich dachte die Auflösungseinstellung/Umrechnung geschieht im LCL von einer einer zentralen Funktion, jetzt habe ich nachgeschaut, es wird an einigen Stellen unabhängig voneinander mit verschiedenen Eigenschaften gerechnet.
Eigentlich hätte man in Controls.pas eine Variable oder Funktion, z.B. GetScreenPixelsPerInch, definieren können, dann wäre es einfacher ändern können.
Vielleicht gibt es schon so etwas ähnliches, ich bin neu in dem Thema.

wp_xyz
Beiträge: 4016
Registriert: Fr 8. Apr 2011, 09:01

Re: "High DPI" selbst einstellen?

Beitrag von wp_xyz »

Es ist nicht vorgesehen, das Programm in einen "simulierten High-DPI-Modus" zu versetzen.

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

Es gibt kein Problem mit der Windows-Auflösung oder Monitor. Es sollte dort nichts geändert werden.

Auf dem Bildschirm ist nichts außer mein Programm zu sehen. Damit die Benutzer in der Produktionsstraße einfacher haben, um Knöpfe zu drücken oder Texte aus ein paar Meter entfernung zu lesen, wollte ich "high-dpi"-Eigenschaft von Lazarus "mißbrauchen", um nur bei meinem Programm Formulare/Dialoge vergrößert darstellen.

Eigentlich wenn ich jetzt so überlege, vielleicht ist es doch einfacher/besser bei Windows-Auflösung die Vergößerung einzustellen, weil es läuft ja nichts außer mein Programm.

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

wp_xyz hat geschrieben:
Sa 5. Jun 2021, 14:09
Es ist nicht vorgesehen, das Programm in einen "simulierten High-DPI-Modus" zu versetzen.
Es wäre aber eigentlich gute Funktion. Es wäre wie Zoom-Funktion bei Browser. Und wie bei meinem Fall und bei allen Kioskanwendungen ist es auch sehr hilfreich.

Ich gucke mir das bei LCL genauer an, vielleicht schaffe ich das. Würde so eine Funkton als Patch akzeptiert werden?

wp_xyz
Beiträge: 4016
Registriert: Fr 8. Apr 2011, 09:01

Re: "High DPI" selbst einstellen?

Beitrag von wp_xyz »

Es gibt auch noch die Einstellung unter "Erleichterte Bedienung" (Win 10) > "Text vergrößern" bzw. "Alles größer einstellen". Das ist keine DPI-Einstellungen, sondern es wird nur die Schrift größer. Aber Achtung: Nur sorgfältig designte Programme mit Anchoring und Autosizing sehen dabei gut aus, selbst die Lazarus-IDE hat da ein paar Schwachpunkte.
Zuletzt geändert von wp_xyz am Sa 5. Jun 2021, 14:26, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 4016
Registriert: Fr 8. Apr 2011, 09:01

Re: "High DPI" selbst einstellen?

Beitrag von wp_xyz »

Soner hat geschrieben:
Sa 5. Jun 2021, 14:15
Würde so eine Funkton als Patch akzeptiert werden?
Nur wenn du keinen Mist baust :wink: In meinen Augen ist das LCL-Scaling sehr kompliziert, ich würde mir nicht zutrauen, da tief im Inneren etwas zu verändern.

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

Ich habe jetzt die Eigenschaft TScreen.PixelsPerInch veränderbar gemacht. Es funktioniert, die Steuerelemente werden vergrößert nur Schriften sind noch klein.
Was ich mich wundere ist, dass TScreen.PixelsPerInch nur in FormXY-Konstruktor veränderbar ist, obwohl es globale Variable ist, deshalb sind die Schriften wahrscheinlich noch klein.
Eigentlich müßte man überall wo Forms.pas eingebunden wird, TScreen.PixelsPerInch verändern können, weil Screen-Variable in initialization-Abschnitt von Forms.pas erstellt wird.

TScreen-Änderung:

Code: Alles auswählen

// in Forms.pas bei TScreen-Class hinzufügen
private
  procedure SetPixelsPerInch(AValue: integer); 
public 
  property PixelsPerInch: integer read FPixelsPerInch write SetPixelsPerInch; //ändern

// in Screen.Inc hinzufügen
procedure TScreen.SetPixelsPerInch(AValue: integer); 
begin
  if AValue<>FPixelsPerInch then FPixelsPerInch:=AValue;
end;   
Test:

Code: Alles auswählen

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  //funktionert nicht es ist 96ppi: Screen.PixelsPerInch:=300;
  Memo1.Lines.Add(IntToStr(Screen.PixelsPerInch));
end;

constructor TForm1.Create(AOwner: TComponent);
begin
  Screen.PixelsPerInch:=300; //nur hier funktioniert es
  inherited Create(AOwner);
end;

initialization
    //funktionert nicht es ist 96ppi: Screen.PixelsPerInch:=300;
end.    

EDIT: Probiert es nicht, es ist unnötig, ich habe gerade bessere Lösung gefunden, Ich poste es wenn ich fertig bin.

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

Die Lösung für die Zoom-Funktion der LCL-Controls ist die Variablen ScreenInfo.PixelsPerInchX, ScreenInfo.PixelsPerInchY aus Graphics-Unit zu ändern.
Wenn man es in der LPR-Datei oder irgendwo anders in Projekt ändert, dann hat es keine Auswirkungen, weil alle anderen Variablen schon vorbelegt sind, ich habe es direkt in LCL-Quelltext geändert.
Das Problem ist jetzt diese beiden Variablen im Projekt ändern zu können.
Falls jemand testen möchte, dann diese Änderung machen:

Code: Alles auswählen

//bei Win32-Widgetset in lcl\interfaces\win32\win32object.inc
//bei qt5 lcl\interfaces\qt5\qt5object.inc
//bei gtk2 lcl\interfaces\gtk2\gtk2widgetset.inc
//...

procedure TWin32WidgetSet.AppInit(var ScreenInfo: TScreenInfo);

  ScreenInfo.PixelsPerInchX := 300; //GetDeviceCaps(DC, LOGPIXELSX);
  ScreenInfo.PixelsPerInchY := 300; //GetDeviceCaps(DC, LOGPIXELSY);

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

Ich habe die Lösung gefunden. falls es jemand braucht, folgende Änderungen bei LCL-Machen.
(Noch nicht richtig getestet).

In lcl\graphics.pp hinzufügen.

Code: Alles auswählen

var 
  MyScreenPpiX : integer = 0; 
  MyScreenPpiY : integer = 0; 
In lcl\interfaces\win32\win32object.inc hinzufügen, für andere Widgets vorherigen Beitrag gucken.

Code: Alles auswählen

procedure TWin32WidgetSet.AppInit(var ScreenInfo: TScreenInfo);
 //...
  if MyScreenPpiX=0 then
    ScreenInfo.PixelsPerInchX := GetDeviceCaps(DC, LOGPIXELSX)
  else
   ScreenInfo.PixelsPerInchX := MyScreenPpiX;
  if MyScreenPpiY=0 then
    ScreenInfo.PixelsPerInchY := GetDeviceCaps(DC, LOGPIXELSY)
  else
    ScreenInfo.PixelsPerInchY := MyScreenPpiY; 
Benutzung in Projekt-LPR-Datei:

Code: Alles auswählen

program project1;

 //.. 
 
begin
  MyScreenPpiX:= 300; // <--- DAS
  MyScreenPpiY:= 300; // <--- DAS
  
  RequireDerivedFormResource:=True;
  Application.Scaled:=True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.  
[code]

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

Vergießt die LCL-Änderungen von vorhin, man muss keine Änderungen machen. Der Grund warum manuelles Ändern ScreenInfo.PixelsPerInchX keine Auswirkung hatte war die Variable ScreenInfo.Initialized. Mann die Variablen an der richtigen Postion, nach Application.Initialize setzen, dann funktioniert es auch.

Code: Alles auswählen

  RequireDerivedFormResource:=True;
  Application.Scaled:=True;
  Application.Initialize;
  ScreenInfo.PixelsPerInchX:=300;    // 300 dpi-Monitor vorgaukeln
  ScreenInfo.PixelsPerInchY:=300;   // 300 dpi-Monitor vorgaukeln
  Screen.PixelsPerInch:=300;         // 300 dpi-Monitor vorgaukeln
  Application.CreateForm(TForm1, Form1);
Nachtrag:
Vergißt das, das funktionert nicht. Ich hatte vergessen die LCL-Änderungen von vorhin zu entfernen.

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: "High DPI" selbst einstellen?

Beitrag von Soner »

Meine Endgültige Lösung ist die Änderungen nur in Forms.pas zu machen.
In lcl/Forms.pas hinzufügen:

Code: Alles auswählen

// in Interface-Abschnitt hinzufügen
var 
  MyScreenPpiX : integer = 0; 
  MyScreenPpiY : integer = 0; 
In lcl/Include/Application.inc:

Code: Alles auswählen

procedure TApplication.Initialize;  // <-- in dieser Prozedur
// ...
  WidgetSet.AppInit(ScreenInfo);  // <-- nach diese Zeile hinzufügen
  if MyScreenPpiX<>0 then ScreenInfo.PixelsPerInchX := MyScreenPpiX;
  if MyScreenPpiY<>0 then ScreenInfo.PixelsPerInchY := MyScreenPpiY; 
  
  //...
end; 
Benutzung in Projekt:

Code: Alles auswählen

program project1;

 //.. 
 
begin
  MyScreenPpiX:= 300; // <--- DAS
  MyScreenPpiY:= 300; // <--- DAS
  
  RequireDerivedFormResource:=True;
  Application.Scaled:=True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.  

Soner
Beiträge: 479
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Wird TImage nicht automatisch sklaiert?

Beitrag von Soner »

Die Bilder von TImage werden nicht automatisch skaliert, muss man da noch etwas einstellen oder ist das ein Bug?

Ich habe im Quelltext von TImage auch nichts entdeckt.

Antworten