![]() |
Formulare in hohen DPI korrekt anzeigen
Ich habe eben mehr oder weniger durch Zufall wie Prozedur
Delphi-Quellcode:
gefunden.
Formular.ScaleBy(Screen.PixelsPerInch, 96);
// 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. |
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) ![]() ![]() |
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. |
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. |
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? |
AW: Formulare in hohen DPI korrekt anzeigen
Zitat:
Delphi-Quellcode:
Weitere Anpassungen waren eigentlich nicht nötig, kommt natürlich immer bisschen auf den GUI-Aufbau drauf an.
Formular.ScaleBy(Screen.PixelsPerInch, 96);
|
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. |
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. |
AW: Formulare in hohen DPI korrekt anzeigen
Ja verstehe ich.
Und das funktioniert? Weil meine Anwendung ist auch mehrsprachig. |
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.
|
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. |
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. |
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:
Erklärung:
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; 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. |
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. |
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; |
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.
|
AW: Formulare in hohen DPI korrekt anzeigen
Zitat:
Delphi-Quellcode:
Aber keine Ahnung ob es da was passendes gibt. Eine For-Schleife ist in dem Fall ja auch gut.
Format('%s.' + IntToStr(BlankCount), [' ']);
Edit: Der Format Befehl kann ja führende Nullen ausgeben, deshalb kam ich da drauf. |
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. |
AW: Formulare in hohen DPI korrekt anzeigen
Zitat:
Delphi-Quellcode:
, aber sicher, daß es nach dem "s" stehen soll?
Format('%s.*', [' ', BlankCount]);
Delphi-Quellcode:
:angle:
Format('%.*s', [BlankCount, ' ']);
Delphi-Quellcode:
Format('%1.2s', ['3']) = Format('%*.*s', [1, 2, '3'])
|
AW: Formulare in hohen DPI korrekt anzeigen
Zitat:
|
AW: Formulare in hohen DPI korrekt anzeigen
Zitat:
|
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. ![]()
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); |
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:
So ist es jetzt:
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;
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:
Das Resultat ist, dass Edit1 immer korrekt bei jeglicher DPI genau da im darunterliegenden Text-Control angezeigt wird, wo die Leerzeichen sind.
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; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:28 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