Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Form über anderer Form zentrieren (https://www.delphipraxis.net/191883-form-ueber-anderer-form-zentrieren.html)

striderx 27. Feb 2017 21:07

Form über anderer Form zentrieren
 
folgende Situation:

Form1 ruft Form2 auf, die wiederum ruft Form3 auf, jeweils mit ShowModal. Form2 ist dabei nicht immer dieselbe Form.

Form 3 soll über Form 2 zentriert werden. Ich hätte gedacht, dass das mit Position = poOwnerFormCenter geht; allerdings wird Form3 damit immer über Form1 zentriert.
Um das Zentrieren 'zu Fuß' zu machen, habe ich versucht, mit GetParentForm(Self) an die Top- und Left-Werte der aufrufenden Form2 zu kommen, die sind jedoch immer 0.

Hat jemand eine Idee?

DeddyH 27. Feb 2017 21:49

AW: Form über anderer Form zentrieren
 
Berechne doch in Form2 die Position von Form3, bevor Du es anzeigst.
Delphi-Quellcode:
Form3.Left := (Width - Form3.Width) div 2;
Form3.Top := (Height - Form3.Height) div 2;
Form3.ShowModal;
Ungetestet, sollte aber ungefähr so funktionieren.

striderx 27. Feb 2017 21:53

AW: Form über anderer Form zentrieren
 
Das geht leider nicht, weil die Größe von Form3 bei jedem Aufruf von Form3 neu ermittelt wird.

himitsu 27. Feb 2017 21:54

AW: Form über anderer Form zentrieren
 
Da fehlt jeweils noch eine Addition der Fensterposition.

DeddyH 27. Feb 2017 22:00

AW: Form über anderer Form zentrieren
 
Stimmt, aber das Prinzip bleibt gleich. Und was spricht dagegen, erst die Größe zu berechnen, bevor man das Formular positioniert?

striderx 27. Feb 2017 22:11

AW: Form über anderer Form zentrieren
 
Zur Erläuterung:

Form3 ist meine Alternative zum Windows Message-Dialog. Je nach Aufruf werden in Form3 die Anzahl der Buttons und der angezeigte Text festgelegt und daraus dann die Größe des Dialogs ermittelt.

Ich habe es jetzt mal so probiert:

Delphi-Quellcode:
  F := GetParentForm(Self);
  dlgShowMsg.Top := F.Top + Trunc((F.Height - dlgShowMsg.Height) / 2);
  dlgShowMsg.Left := F.Left + Trunc((F.Width - dlgShowMsg.Width) / 2);
edit: Aber damit erscheint der Dialog immer in der oberen linken Ecke.

himitsu 27. Feb 2017 22:19

AW: Form über anderer Form zentrieren
 
GetParentForm?
Bzw. was ist Self?

Also als Subkomponente genutzt (Parent gesetzt) und nicht als eigenständige Form?
Dann natürlich ohne die Addition der Position des äußeren Fensters, da hier das Offset 0 ist.

striderx 27. Feb 2017 22:22

AW: Form über anderer Form zentrieren
 
Zitat:

Zitat von himitsu (Beitrag 1362833)
GetParentForm?

Also als Subkomponente genutzt (Parent gesetzt) und nicht als eigenständige Form?

Doch, das ist eine eigenständige Form. Self müsste Form3 sein.

DeddyH 27. Feb 2017 22:24

AW: Form über anderer Form zentrieren
 
Spontan fallen mir 2 Möglichkeiten ein:
- Form3 bekommt eine öffentliche Methode, die die Größenberechnung anstößt
- Form3 bekommt eine Property vom Typ TForm, in der sich das aufrufende Formular einträgt und berechnet seine Position anhand dieser Property dann selbst

striderx 27. Feb 2017 22:34

AW: Form über anderer Form zentrieren
 
Zitat:

Zitat von DeddyH (Beitrag 1362835)
Spontan fallen mir 2 Möglichkeiten ein:
- Form3 bekommt eine öffentliche Methode, die die Größenberechnung anstößt
- Form3 bekommt eine Property vom Typ TForm, in der sich das aufrufende Formular einträgt und berechnet seine Position anhand dieser Property dann selbst

Form3 hat bereits eine öffentliche Methode, in der die Form zusammengebastelt wird und die das ModelResult zurück liefert.

Delphi-Quellcode:
function ShowMsg(MsgText, HeaderText: String; mButtons, mIcon: Word): Integer;


Ich könnte die Werte der aufrufenden Form noch als Parameter aufnehmen, das wäre aber nicht besonders elegant.

himitsu 27. Feb 2017 22:37

AW: Form über anderer Form zentrieren
 
Zitat:

Zitat von striderx (Beitrag 1362836)
Form3 hat bereits eine öffentliche Methode, in der die Form zusammengebastelt wird und die das ModelResult zurück liefert.

Dann ist also Self die aufrufende Form?

Tja, dann redest du von 2 Forms und ich zähle im Code aber 3 Forms/Variablen.
(Self, F und dlgShowMsg)

striderx 27. Feb 2017 22:44

AW: Form über anderer Form zentrieren
 
Zitat:

Zitat von himitsu (Beitrag 1362837)
Zitat:

Zitat von striderx (Beitrag 1362836)
Form3 hat bereits eine öffentliche Methode, in der die Form zusammengebastelt wird und die das ModelResult zurück liefert.

Dann ist also Self die aufrufende Form?

Tja, dann redest du von 2 Forms und ich zähle im Code aber 3 Forms/Variablen.
(Self, F und dlgShowMsg)


Form1 ist die Haupt-Form, Form2 eine beliebige von dort aufgerufene Form die wiederum Form3 aufruft. Form3 ist gleich dlgShowMsg. F sollte der Aufrufer von Form3 sein, Self ist Form 3.

haentschman 28. Feb 2017 05:54

AW: Form über anderer Form zentrieren
 
Moin...:P
Zitat:

Ich könnte die Werte der aufrufenden Form noch als Parameter aufnehmen, das wäre aber nicht besonders elegant.
Delphi-Quellcode:
function ShowMsg(ParentForm: TForm; MsgText, HeaderText: String; mButtons, mIcon: Word): Integer;
..
oder im constructor beim erzeugen von Form3
Delphi-Quellcode:
constructor Create(AOwner: TComponent; ParentForm: TForm); reintroduce;
..
constructor TfrBlubb.Create(AOwner: TComponent; ParentForm: TForm);
begin
  inherited Create(AOwner);
  ..
end;
...was ist daran nicht elegant? :P

Die Dialog Form intessiert nur wer in aufgerufen hat, damit er seine eigenen Positionen berechnen kann. (siehe DeddyH) ...fertsch. 8-)

striderx 28. Feb 2017 07:49

AW: Form über anderer Form zentrieren
 
Da Form 3 von unterschiedlichen anderen Formularen aufgerufen wird, ist der Constructor kaum die richtige Stelle. Ich habe es stattdessen mit einer überladenenen Version von ShowModal gemacht:

Delphi-Quellcode:
function ShowModal(MsgText, HeaderText: String; mButtons, mIcon: Word; aCaller: tForm): Integer; overload;


Was nicht elegant ist: Dass ich bei über 100 Aufrufen jetzt jedesmal das aufrufende Formular als Parameter einfügen muss.

haentschman 28. Feb 2017 07:56

AW: Form über anderer Form zentrieren
 
Zitat:

Da Form 3 von unterschiedlichen anderen Formularen aufgerufen wird, ist der Constructor kaum die richtige Stelle.
...dynamische Erzeugung nur wenn die Form (der Dialog) gebraucht wird? :gruebel:
Delphi-Quellcode:
Dialog := TfoBlubb.Create(nil, self);
try
  Dialog.ShowMessage('Bla');
finally
  Dialog.Free;
end;

striderx 28. Feb 2017 08:38

AW: Form über anderer Form zentrieren
 
Da ist mir der Einzeiler mit dem Aufruf von ShowModal deutlich lieber ... :)

Slipstream 28. Feb 2017 08:58

AW: Form über anderer Form zentrieren
 
Geht das nicht auch mit Form3.Position := poMainFormCenter oder poOwnerFormCenter? Im zweiten Fall müsste man Form3 als Owner Form2 mitgeben, oder?

striderx 28. Feb 2017 11:03

AW: Form über anderer Form zentrieren
 
Zitat:

Zitat von Slipstream (Beitrag 1362852)
Geht das nicht auch mit Form3.Position := poMainFormCenter oder poOwnerFormCenter? Im zweiten Fall müsste man Form3 als Owner Form2 mitgeben, oder?


Ich hätte auch gedacht, dass 'poOwnerFormCenter' genau für einen solchen Fall da ist (s. mein Eingangs-Post), klappt aber leider nicht.

haentschman 28. Feb 2017 11:34

AW: Form über anderer Form zentrieren
 
Moin...:P
Zitat:

Ich hätte auch gedacht, dass 'poOwnerFormCenter' genau für einen solchen Fall da
... und wer ist der Owner wenn das Form automatisch in der MainForm erzeugt wird? :zwinker:

Slipstream 28. Feb 2017 13:24

AW: Form über anderer Form zentrieren
 
Zitat:

Zitat von haentschman (Beitrag 1362879)
Moin...:P
Zitat:

Ich hätte auch gedacht, dass 'poOwnerFormCenter' genau für einen solchen Fall da
... und wer ist der Owner wenn das Form automatisch in der MainForm erzeugt wird? :zwinker:

Das Folgende klappt bei mir fehlerfrei, das 2. Formular wird genau in der Mitte des 1. Formulars angezeigt, und zwar immer und egal, von welchem Formular aus ich aufrufe:

Delphi-Quellcode:
procedure TForm1.Bt_Form2Click(Sender: TObject);
begin
  U2 := TForm2.Create(Self);
  Try
    U2.Position := poOwnerFormCenter;
    U2.ShowModal;
  Finally
    U2.Free;
  End;
end;

striderx 28. Feb 2017 15:31

AW: Form über anderer Form zentrieren
 
@haentschmann

Wenn ich mir meine dpr-Dateien anschaue, sehe ich nichts davon, dass etwas "automatisch in der MainForm erzeugt wird".


@slipstream

Wie ich schon geschrieben habe: Da ist mir der Einzeiler mit dem Aufruf von ShowModal deutlich lieber ...



Ich bin mir sicher, dass es einen Weg geben muss, den Caller festzustellen (wie macht das z. B. MessageDlg?). Aber so komme ich jetzt erst mal klar.

striderx 1. Mär 2017 07:43

AW: Form über anderer Form zentrieren [gelöst]
 
So, ich habe jetzt eine Lösung gefunden:

Die aufrufende Form läßt sich über Screen.Forms[0] ermitteln.

Das Ganze sieht bei mir dann so aus:

Delphi-Quellcode:
  aCaller := Screen.Forms[0];
  if aCaller <> Nil then begin
     dlgShowMsg.Position := poDesigned;
     dlgShowMsg.Top := aCaller.Top + Trunc((aCaller.Height - dlgShowMsg.Height) / 2);
     dlgShowMsg.Left := aCaller.Left + Trunc((aCaller.Width - dlgShowMsg.Width) / 2);
  end
  else dlgShowMsg.Position := poOwnerFormCenter;

himitsu 1. Mär 2017 09:28

AW: Form über anderer Form zentrieren [gelöst]
 
Zitat:

Zitat von striderx (Beitrag 1362937)
Die aufrufende Form läßt sich über Screen.Forms[0] ermitteln.

Jain. Das ist die Form, welche aktuell den Fokus besitzt, denn immer wenn eine Form den bekommt, wird sie auf 0 verschoben.

Ist deine Form bereits sichtbar, dann wäre sie selbst die 0.

Zitat:

Zitat von striderx (Beitrag 1362937)
Das Ganze sieht bei mir dann so aus

Delphi-Quellcode:
aCaller <> nil
aka
Delphi-Quellcode:
Assigned(aCaller)
wirst du nie erleben, denn das ist niemals NIL, da Forms[i] immer eine Form zurückliefert, und wenn nicht, dann wird eine Exception geworfen (index out of bounds).

t.roller 1. Mär 2017 10:15

AW: Form über anderer Form zentrieren [gelöst]
 
Zitat:

Zitat von striderx (Beitrag 1362937)
So, ich habe jetzt eine Lösung gefunden:

Die aufrufende Form läßt sich über Screen.Forms[0] ermitteln.

Delphi-Quellcode:
procedure TForm2.Button1Click(Sender: TObject);
var aCaller : TForm;
begin
aCaller := Self;
...

striderx 1. Mär 2017 11:36

AW: Form über anderer Form zentrieren
 
Zitat:

Ist deine Form bereits sichtbar, dann wäre sie selbst die 0.
Stimmt. Da ich aber meine Form in der aufgerufenen Methode erst konfiguriere, passiert das, bevor sie sichtbar wird. In meinem Anwendungsfalls klappt das somit.


@t.roller: Das geht auch einfacher, indem ich den Caller als Parameter beim Methodenaufruf übergebe. Aber mit meinem Ansatz kann ich mir das schenken.


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