Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Formulare in hohen DPI korrekt anzeigen (https://www.delphipraxis.net/190598-formulare-hohen-dpi-korrekt-anzeigen.html)

Jim Carrey 19. Okt 2016 15:21

Formulare in hohen DPI korrekt anzeigen
 
Ich habe eben mehr oder weniger durch Zufall wie Prozedur
Delphi-Quellcode:
Formular.ScaleBy(Screen.PixelsPerInch, 96);
//
gefunden.

Ich habe die auch direkt ausgetestet und meine auf ein Win7 mit DPI 125% gespeichert.
Die Anwendung ist tatsächlich größer. Generell ist alles größer geau wie erwartet.

Jetzt aber die Frage. Ist das eine absolute Quick & Dirty-Lösung oder kann man sie ruhig so verwenden?
Denn ich habe keine Lust jedes Label, jedes Edit usw auf DPI X anzupassen.

himitsu 19. Okt 2016 15:33

AW: Formulare in hohen DPI korrekt anzeigen
 
Eigentlich machen die VCL-Formulare das von selbst.

In den Formularen (DFM) werden die DPI des Entwicklungsrechners gespeichert (da, wo die DFM zuletzt gespeichert wurde)
und beim Laden der Form, wird es automatisch angepasst. (wenn bei beiden Windows die DPI ordentlich eingestellt waren, bzw. was der Benutzer eingestellt hat > Systemsteuerung\Darstellung und Anpassung\Anzeige)

Delphi-Referenz durchsuchenTForm.PixelsPerInch
Delphi-Referenz durchsuchenTForm.Scaled

Jim Carrey 19. Okt 2016 15:38

AW: Formulare in hohen DPI korrekt anzeigen
 
Ich habe Scaled auf False gestellt und das überall.

Ich meine eigentlich das Aussehen der fertigen Exe-Datei, nicht das Formular in der IDE.

himitsu 19. Okt 2016 16:57

AW: Formulare in hohen DPI korrekt anzeigen
 
Genau das macht Scaled=True.
Erst beim Start der fertigen EXE, aber auch beim Laden in der IDE.

Es werden die aktuellen DPI genommen, mit den in der DFM gespeicherten DPI verrechnet und die Form entsprechend skaliert.

Jim Carrey 19. Okt 2016 17:41

AW: Formulare in hohen DPI korrekt anzeigen
 
Ok das mit der IDE wusste ich nicht.
Dann gehe ich einfach mal davon aus, dass ich nicht drum herum komme hier und da Anpassungen vorzunehmen, damit es bei jeder DPI gleich aussieht, oder?

Darlo 19. Okt 2016 19:03

AW: Formulare in hohen DPI korrekt anzeigen
 
Zitat:

Zitat von Jim Carrey (Beitrag 1351390)
Ok das mit der IDE wusste ich nicht.
Dann gehe ich einfach mal davon aus, dass ich nicht drum herum komme hier und da Anpassungen vorzunehmen, damit es bei jeder DPI gleich aussieht, oder?

VCL ist bei mir ein bisschen her ;-) Aber soweit ich mich erinnere hatte ich immer Form.Scaled auf false und mit der von dir bereits genannten Codezeile gearbeitet
Delphi-Quellcode:
Formular.ScaleBy(Screen.PixelsPerInch, 96);
Weitere Anpassungen waren eigentlich nicht nötig, kommt natürlich immer bisschen auf den GUI-Aufbau drauf an.

Jim Carrey 19. Okt 2016 19:07

AW: Formulare in hohen DPI korrekt anzeigen
 
Bei mir leider schon. Speziell da, wo ich Konstrukte benutze wie...

DAS_IST_EIN_LABEL---[EDIT_FELD]---_TEXT

Sprich: Label mit vielen Leerzeichen, um ein Edit reinzusetzen. Das klappt mit normaler DPI wunderbar, aber ich muss es nun umändern, damit ich bald hohe DPI unterstützen kann.

Darlo 19. Okt 2016 19:10

AW: Formulare in hohen DPI korrekt anzeigen
 
Dann nimm folgenden Aufbau:
[Panel]
->[Label Align Left]"Das ist ein..."[/Label]
->[Edit Align Left]
->[Label Align Left]"Apfelbaum."[/Label]
[/Panel]

Hoffe Du verstehst was ich meine.

Jim Carrey 19. Okt 2016 19:13

AW: Formulare in hohen DPI korrekt anzeigen
 
Ja verstehe ich.
Und das funktioniert?

Weil meine Anwendung ist auch mehrsprachig.

Darlo 19. Okt 2016 19:17

AW: Formulare in hohen DPI korrekt anzeigen
 
Ich arbeite seit XE2 was GUIs ausschließlich mit Firemonkey. Da nehme ich anstatt des Panels ein TLayout und arbeite durchgängig nach diesem Prinzip. Die Skalierung funktioniert fehlerfrei von Android über iOS (Retina und non Retina )bis Windows-Rechner mit diversen DPI-Einstellungen.

Jim Carrey 19. Okt 2016 19:22

AW: Formulare in hohen DPI korrekt anzeigen
 
Ich werde das gleich in jedem Fall mal ausprobieren.
Dann habe ich zwar statt einem Label 2 + ein Panel, aber das ist es mir wert.

Ich gebe dann gleich Bescheid was draus geworden ist.

Jim Carrey 19. Okt 2016 20:15

AW: Formulare in hohen DPI korrekt anzeigen
 
Ich merke gerade erst...
ich kann das mit den Labels nicht machen, da ich einen RadioButton verwende und kein Label.

Jim Carrey 20. Okt 2016 15:52

AW: Formulare in hohen DPI korrekt anzeigen
 
Ich habe mir jetzt eine Funktion geschrieben, welche für mich die Arbeit mit dem Leerzeichen-Problem übernimmt.

Zur Erinnerung mein Aufbau:
[RadioButton_mit_einem___(EDIT_FELD)__ganz_langem_T ext]

Ihr dürft mich später erschlagen für meine Dummheit :thumb:
Delphi-Quellcode:
function calcSpacesNeeded(aEdit: TEdit): string;
var
 iEditWidth, iTmpWidth: Integer;
 i: Integer;
 s: string;
begin
 s := '';
 iEditWidth := aEdit.Width;

 for i := 0 to iEditWidth do
  begin
   s := s + ' ';

   iTmpWidth := Form3.Canvas.TextWidth(s);

   if iTmpWidth >= iEditWidth then
    begin
     s := s + '       ';
     Break;
    end;
  end;

 Result := s;
end;

RadioButton1.Caption := 'Radiobutton mit einem ' + calcSpacesNeeded(Edit1) + ' ganz langem Text';
Edit1.Left := 123;
Erklärung:
mein Code geht in einer for-Schleife von 0 bis "Width des Edits" in Pixeln durch.
Bei jedem Durchgang wird die aktuelle Width der Variablen "s" geprüft. Ist sie kleiner als die des Edits, so wird der Variablen "s" ein Leerzeichen angefügt.
Sobald Width des Konstrukts der Variablen "s" größer oder gleich der des Edits ist, ist Schluss. Vorher werden der Variablen "s" aber noch 8 weitere Leerzeichen angefügt (hat bei mir einen Sinn, da ich meine Edits modifiziere).

Das klappt bei 96 DPI und 120 dpi perfekt.

Aviator 20. Okt 2016 15:56

AW: Formulare in hohen DPI korrekt anzeigen
 
Ich würde keine Schleife zum Überprüfen machen. Ich würde mir einmal die Breite des Leerzeichens auf dem speziellen Canvas merken und dann die Größe des Editfeldes durch die Breite des Leerzeichens teilen. Somit bekommst du die Anzahl der Leerzeichen (plus eventuell noch 2 für einen Freiraum rechts und links vom Edit) und brauchst dann nur noch eine Schleife um die Anzahl der Leerzeichen zu erzeugen.

Ob es mit dem Format Befehl auch geht weiß ich nicht genau. Könntest du aber mal ausprobieren.

Vorteil dieser Methode ist, dass du nicht jedes Mal wieder die Breite auf dem Canvas überprüfen musst. Die ändert sich nämlich nicht mehr.

Jim Carrey 20. Okt 2016 16:01

AW: Formulare in hohen DPI korrekt anzeigen
 
Gute Idee, Danke dir =)

Delphi-Quellcode:
function calcSpacesNeeded(aControl: TControl): string;
var
 i, iTmpWidth, iSpaceWidth: Integer;
 sTmp: string;
 Canvas: TCanvas;
begin
 Canvas := TCanvas.Create;

 try
  Canvas.Handle := GetDC(0);

  try
   Canvas.Font := MainForm.Font;
   iSpaceWidth := Canvas.TextWidth(' ');
  finally
   ReleaseDC(0, Canvas.Handle);
  end;
 finally
  Canvas.Free;
 end;

 sTmp := '';
 iTmpWidth := aControl.Width div iSpaceWidth;

 for i := 0 to iTmpWidth do
  begin
   sTmp := sTmp + ' ';
  end;

 sTmp := sTmp + '       '; // 8 Leerzeichen, <Delphi> zeigt aber nur 1 an
 Result := sTmp;
end;

Jim Carrey 20. Okt 2016 16:33

AW: Formulare in hohen DPI korrekt anzeigen
 
Das würde mich auch brennend interessieren, ob man ein Control, sagen wir mal ein Edit, mit Format() an eine gewisse Stelle packen kann.

Aviator 20. Okt 2016 16:56

AW: Formulare in hohen DPI korrekt anzeigen
 
Zitat:

Zitat von Jim Carrey (Beitrag 1351526)
Das würde mich auch brennend interessieren, ob man ein Control, sagen wir mal ein Edit, mit Format() an eine gewisse Stelle packen kann.

Nein, das bestimmt nicht. Der Format Befehl ist dazu da, einen String entsprechend dem Wunsch zu formatieren und zurückzugeben. Ich dachte mit mit dem Format Befehl nur, dass der so in etwas aussehen könnte.

Delphi-Quellcode:
Format('%s.' + IntToStr(BlankCount), [' ']);
Aber keine Ahnung ob es da was passendes gibt. Eine For-Schleife ist in dem Fall ja auch gut.

Edit: Der Format Befehl kann ja führende Nullen ausgeben, deshalb kam ich da drauf.

Jim Carrey 20. Okt 2016 17:16

AW: Formulare in hohen DPI korrekt anzeigen
 
Ach so ok. Ja stimmt. Wäre auch zu schön gewesen, wenn es das geben würde. Wäre aber auch irgendwie idiotisch.

Habe mir das jedenfalls selber gebastelt. Ich muss zwar zwischen Label (ComboBox/RadioButton) und Edit unterscheiden, aber das macht mir nix.
Soweit ich das jetzt beurteilen kann, funktioniert es einwandfrei mit jeglicher DPI.

Vor dieser Aufgabe habe ich mich immer gescheut aber nun mache ich es, da immer mehr Anwender meiner Software hohe DPI-Einstellungen haben. Warum auch immer zum Teufel man das macht.

himitsu 20. Okt 2016 17:23

AW: Formulare in hohen DPI korrekt anzeigen
 
Zitat:

Delphi-Quellcode:
Format('%s.' + IntToStr(BlankCount), [' ']);

Delphi-Quellcode:
Format('%s.*', [' ', BlankCount]);
, aber sicher, daß es nach dem "s" stehen soll?


Delphi-Quellcode:
Format('%.*s', [BlankCount, ' ']);
:angle:
Delphi-Quellcode:
Format('%1.2s', ['3']) = Format('%*.*s', [1, 2, '3'])

Jim Carrey 20. Okt 2016 17:56

AW: Formulare in hohen DPI korrekt anzeigen
 
Zitat:

Zitat von himitsu (Beitrag 1351542)
Zitat:

Delphi-Quellcode:
Format('%s.' + IntToStr(BlankCount), [' ']);

Delphi-Quellcode:
Format('%s.*', [' ', BlankCount]);
, aber sicher, daß es nach dem "s" stehen soll?


Delphi-Quellcode:
Format('%.*s', [BlankCount, ' ']);
:angle:
Delphi-Quellcode:
Format('%1.2s', ['3']) = Format('%*.*s', [1, 2, '3'])

Jezt verstehe ich gar nichts mehr 8-)

Aviator 20. Okt 2016 22:54

AW: Formulare in hohen DPI korrekt anzeigen
 
Zitat:

Zitat von himitsu (Beitrag 1351542)
Delphi-Quellcode:
Format('%s.*', [' ', BlankCount]);
, aber sicher, daß es nach dem "s" stehen soll?

Ne. War nur mal so dahin geschrieben weil ich nicht genau wusste, ob Format auf das Auffüllen von Leerzeichen unterstützt. Habe deine Zeile auch nicht ausgeführt und weiß dementsprechend immer noch nicht ob es geht.

himitsu 21. Okt 2016 09:43

AW: Formulare in hohen DPI korrekt anzeigen
 
Nja, grundsätzlich meinte ich auch nur, dass die "Format-Formatierungen" zwischen "%" und Typ stehen.

Im Wiki steht nur was vom Abschneiden, also ob auch aufgefüllt wird, könnte man einfach mal probieren.
http://docwiki.embarcadero.com/Libra...Format-Strings

Delphi-Quellcode:
ShowMessage(Format('a#%.8s#', ['x']) + sLineBreak
  + Format('b#%.8s#', ['xxxxxxxxxxxxxxxxxxxxxxx']) + sLineBreak
  + Format('c#%8.s#', ['x']) + sLineBreak
//+ Format('d#%.-8s#', ['x']) + sLineBreak // gibt's net
  + Format('e#%-8.s#', ['x']) + sLineBreak
  + Format('f#%8.8s#', ['x']) + sLineBreak
//+ Format('g#%8.-8s#', ['x']) + sLineBreak
  + Format('h#%-8.8s#', ['x']) + sLineBreak);

Jim Carrey 21. Okt 2016 12:02

AW: Formulare in hohen DPI korrekt anzeigen
 
Meine aktuelle Lösung ist die folgende, für alle die, die es interessiert.
Mein Einsatzzweck ist eine multilinguale Software, wo ich die Edits und ComboBoxen nicht am Ende eines Satzes (CheckBox) haben sollte sondern grammatikalisch korrekt mittendrin.

So war es vorher:
Delphi-Quellcode:
LabelX.Caption := 'Das hier ist ein ganz langer Satz mit gefühlt....................völlig nutzlosen Zeichen!'; // statt den Punkten natürlich Leerzeichen
Edit1.Left := 123;
So ist es jetzt:
Delphi-Quellcode:
LabelX.Caption := 'Das hier ist ein ganz langer Satz mit gefühlt ' + calcSpacesNeeded(Edit1) + ' völlig nutzlosen Zeichen!';
setControlToPosition(Edit1, LabelX);
Delphi-Quellcode:
function getTextWidth(const aString: string; aForm: TForm): Integer;
var
 iRes: Integer;
 // Canvas: TCanvas;
begin
 iRes := 0;

 if aString <> '' then
  begin
   // Canvas := TCanvas.Create;

   // try
   // Canvas.Handle := GetDC(0);

   // try
   // Canvas.Font := aForm.Font;
   iRes := aForm.Canvas.TextWidth(aString); // nur diese Zeile wird benötigt, da aForm schon ein Canvas hat
   // finally
   // ReleaseDC(0, Canvas.Handle);
   // end;
   // finally
   // Canvas.Free;
   // end;
  end;

 Result := iRes;
end;

function calcSpacesNeeded(aControl: TControl): string;
var
 i, iTmpWidth, iSpaceWidth: Integer;
 sTmp: string;
begin
 iSpaceWidth := getTextWidth(' ', TForm(GetParentForm(aControl)));

 sTmp := '';
 iTmpWidth := aControl.Width div iSpaceWidth;

 for i := 0 to iTmpWidth do
  begin
   sTmp := sTmp + ' ';
  end;

 if aControl.ClassType = TEdit then
  sTmp := sTmp + '     ' // 6
 else if aControl.ClassType = TComboBox then
  sTmp := sTmp + '  ' // 4
 else
  sTmp := sTmp + ' '; // 2

 Result := sTmp;
end;

procedure setControlToPosition(aControlToSet, aControlSource: TControl);
var
 iSpacePosition, iCaptionWidth, iTmp: Integer;
 sCaption, sTmp: string;
begin
 if aControlSource.ClassType = TEdit then
  sCaption := (aControlSource as TEdit).Text
 else if (aControlSource.ClassType = TCheckBox) or (aControlSource.ClassType = TRadioButton) then
  sCaption := (aControlSource as TCheckBox).Caption
 else if (aControlSource.ClassType = TLabel) then
  sCaption := (aControlSource as TLabel).Caption;

 iSpacePosition := PosEx(' ', sCaption, 1) + 2;

 if iSpacePosition > 0 then
  begin
   sTmp := Copy(sCaption, 1, iSpacePosition);

   iCaptionWidth := getTextWidth(sTmp, TForm(GetParentForm(aControlToSet)));

   iTmp := aControlToSet.Width;
   if aControlSource.ClassType = TLabel then
    iTmp := aControlToSet.Width div 2;

   if aControlToSet.ClassType = TEdit then
    iTmp := iTmp + 2
   else if aControlToSet.ClassType = TComboBox then
    iTmp := iTmp - 4
   else
    iTmp := iTmp - 6;

   aControlToSet.Left := iCaptionWidth + iTmp;
  end;
end;
Das Resultat ist, dass Edit1 immer korrekt bei jeglicher DPI genau da im darunterliegenden Text-Control angezeigt wird, wo die Leerzeichen sind.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:33 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