Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Form.Show Quelle


Quake User - Di 22.06.10 00:39
Titel: Form.Show Quelle
Ich muss bei öffnen einer Form (Form.Show) darauf reagieren, von wo der Aufruf kommt. Wie kann ich das ermitteln.

Bspw.: Ich öffne per Mausklick vo nverschiedenen anderen Formularen eine Form (Form.Show) und möchte eine Auswahlliste anzeigen. Diese Auswahllsiet hängt davon ab, von welchem anderen Formular aus die Form geöffnet wurde.


elundril - Di 22.06.10 00:50

Mach eine neue Methode mit einem Parameter von dem du dann Form.Show aufrufst:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
//Typ deswegen TForm, weil jedes Formular das du erstellst von TForm erbt
procedure TFormX.ShowWithCases(aForm: TForm);
begin
  if (aForm is Form1) then begin
    Showmessage('Form1 hat aufgerufen');
    FormX.Show;
    end
  else begin
    showmessage('Andere Form hat aufgerufen');
    FormX.Show;
  end;
end;


lg elundril


Quake User - Di 22.06.10 01:03

Moderiert von user profile iconNarses: Komplett-Zitat des letzten Beitrags entfernt.

Das verstehe ich nicht. Ich schreibe bspw. in Form1 bei einem Button Klick: "Form2.Show". Im OnShow Event der Form2 müsste ich dann abfragen, wer das Ereignis Show ausgelöst hat, (Form1 oder Form3), damit ich in Form2 eine angepasste Auswahllsite erstellen kann.

Wo soll ich nun die o.g. Funktion einbauen?


jaenicke - Di 22.06.10 05:11

user profile iconQuake User hat folgendes geschrieben Zum zitierten Posting springen:
Ich schreibe bspw. in Form1 bei einem Button Klick: "Form2.Show".
Nein, du schreibst in dem Beispiel Form2.ShowWithCases(Self), denn du musst deine neue Prozedur aufrufen. In dieser Prozedur machst du dann die Unterscheidung anhand des übergebenen Formulars.

Ein Fehler ist noch drin, schreib das besser so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TFormX.ShowWithCases(aForm: TForm);
begin
  if (aForm is Form1) then
  begin
    Showmessage('Form1 hat aufgerufen');
    Self.Show;
  end
  else
  begin
    showmessage('Andere Form hat aufgerufen');
    Self.Show;
  end;
end;
Denn mit explizit FormX statt des aktuellen Formulars kann es Probleme bei dynamisch erstellten Formularen z.B. geben.


Quake User - Do 09.12.10 03:01

Ich bin nicht sicher, ob ich das Problem genau beschrieben habe:

ich habe eine MainForm und eine KalenderForm. Nun rufe ich aus der MainForm an unterschiedlichen Stellen den Kalender auf. Der Kalender soll dann das gewälte Datum an die MainForm zurückgeben bzw. in die DBEdit Felder der MainForm eintragen.

Dazu müsste doch die KalenderForm "wissen", welche Form und welcher Button sie mit Form.Show aufgerufen hat.
Oder ist das der falsche Ansatz?


elundril - Do 09.12.10 04:42

Ja, weil das eigentlich Verantwortung von der MainForm ist. Am besten ist es du rufst dann eine Methode namens "ShowKalender" auf (siehe unten), die dir dann das ausgewählte Datum zurückliefert. Das Zeug was in der MainForm passiert, schreibst du auch in der MainForm. Die KalenderForm darf nicht mal der MainForm da reinpfuschen, weil es nicht in deren Verantwortung liegt die Daten der MainForm zu ändern.


Delphi-Quelltext
1:
2:
3:
4:
5:
function KalenderForm.ShowKalender(Sender: TObject): TDate;
begin
  KalenderForm.Show;
  Result := AusgewaehltesDatum; //Muss natürlich irgendwie Deklariert sein, oder du bekommst von wo anders dein Datum
end;


und im MainForm


Delphi-Quelltext
1:
2:
3:
{...}
DBEdit1.Text := DateToString(KalenderForm.ShowKalender(Self));
{...}


Ich hoffe die Funktionsweise ist klar geworden.

lg elundril


Tankard - Do 09.12.10 04:49

Ein Datum als String in einer DB zu speichern, ist aber böse und sollte nicht gemacht werden. Gibt nur Probleme wenn man nach Datum sortieren und suchen will.


Quake User - Sa 11.12.10 03:55

Der Ansatz von elundril war das, was ich gesucht habe. So habe ich das jetzt auch implementiert.
Danke an Alle.


delfiphan - Sa 11.12.10 12:01

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TFormX.ShowWithCases(aForm: TForm);
begin
  if (aForm is Form1) then
  begin
    Showmessage('Form1 hat aufgerufen');
    Self.Show;
  end
  else
  begin
    showmessage('Andere Form hat aufgerufen');
    Self.Show;
  end;
end;

Das ist nicht so gut. Sowas verstösst gegen separation of concern/single responsibility principle. Die (unnötige) Abhängigkeit führt auch dazu, dass du die Komponente "KalenderForm" wohl nur noch in diesem Programm verwenden kannst.

Wenn man if x is klasse1 then ... if x is klasse2 then im Code hat, sollte man das Design nochmals überdenken. Wenn eine Fallunterscheidung nötig ist, dann könnte man mit Optionen über Properties arbeiten.

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
function KalenderForm.ShowKalender(Sender: TObject): TDate;
begin
  KalenderForm.Show;
  Result := AusgewaehltesDatum; //Muss natürlich irgendwie Deklariert sein, oder du bekommst von wo anders dein Datum
end;

Der Kalender wird hier einfach eingeblendet. Show ist gleichbedeutend wie Visible auf True setzen (+BringToFront). Der Code sieht so aus, als ob der Rückgabeparameter das ausgewählte Datum ist, nachdem die Form eingeblendet wurde.


Quake User - Mo 13.12.10 04:44

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
function KalenderForm.ShowKalender(Sender: TObject): TDate;
begin
  KalenderForm.Show;
  Result := AusgewaehltesDatum; //Muss natürlich irgendwie Deklariert sein, oder du bekommst von wo anders dein Datum
end;

Der Kalender wird hier einfach eingeblendet. Show ist gleichbedeutend wie Visible auf True setzen (+BringToFront). Der Code sieht so aus, als ob der Rückgabeparameter das ausgewählte Datum ist, nachdem die Form eingeblendet wurde.


Das sehe ich jetzt leide auch als Problem an. Ein Nutzer erwartet, dass bspw. ein Klick auf "Fenster schließen" nur das Fenster schließt und nicht eine Datums-Auswahl übernimmt. Bei dieser Variante ist nun leider so, dass immer das selektierte Datum des Kalenders übernommen wird, auch wenn der Nutzer kein Datum ausgewählt hat.

Leider fällt mir dafür keine optimale Lösung ein. Ich könnte bei Klick im Kalender eine Variable "selected" auf true setzen und nur dann den Rückgabewert auswerten. Wenn der Nutzer aber mit der Tastatur im Kalender auswählt, kann das zu Problemen führen.


jaenicke - Mo 13.12.10 07:43

Mit Show funktioniert das doch ohnehin nicht, da der Aufruf sofort zurückkehrt.

ShowModal dagegen wartet. Und hat auch einen Rückgabewert, der dir sagt was passiert ist. (Wenn du ihn im Kalender setzt, d.h. z.B. ModalResult des Ok-Buttons setzt.)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function TKalenderForm.ShowKalender(Sender: TObject; var SelectedDate: TDate): Boolean;
begin
  Result := Self.ShowModal = mrOk;
  if Result then
    SelectedDate := ...
end;
Oder du machst es wie die Delphi-Dialoge:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function TKalenderForm.Execute(Sender: TObject): Boolean;
begin
  Result := Self.ShowModal = mrOk;
end;

if MyKalender.Execute(Self) then
  ...Mykalender.SelectedDate...


Quake User - Mo 13.12.10 16:22

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Oder du machst es wie die Delphi-Dialoge:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function TKalenderForm.Execute(Sender: TObject): Boolean;
begin
  Result := Self.ShowModal = mrOk;
end;

if MyKalender.Execute(Self) then
  ...Mykalender.SelectedDate...

Wie rufe ich diese Funktion auf bzw. wie übergebe ich das Datum an den Hauptdialog?


jaenicke - Mo 13.12.10 23:47

Umgekehrt, der Hauptdialog ruft das wie gezeigt auf und holt sich das Datum. Dafür machst du eine Property SelectedDate in deinem Kalender, über den das Datum abrufbar ist. Das meinte ich hier:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
if MyKalender.Execute(Self) then
  ...Mykalender.SelectedDate...
Als Beispiel schau dir den OpenDialog an:

Delphi-Quelltext
1:
2:
if OpenDialogX.Execute then
  ShowMessage(OpenDialogX.FileName);


Quake User - So 02.01.11 15:14

Ich steh bei dem Problem irgendwo auf dem Schlauch. (Das neue Jahr fängt ja gut an)

Ich habe die Datumsselektion jetzt so gebaut: Ich habe im Hauptformular eine Funktion "ShowKalender". Diese Ruft eine Form auf, auf der ein MonthCalendar liegt.

Delphi-Quelltext
1:
2:
3:
4:
5:
function TFormR.ShowKalender(Sender: TObject): TDate;
begin
  FormKalender.ShowModal;
  Result:= FormKalender.MonthCalendar1.Date;
end;


Diese rufe ich so auf:

Delphi-Quelltext
1:
Datum := ShowKalender(Self);                    

Im MonthCalendar1 ist immer ein Datum selektiert, sodass dieser auch immer ein Datum zurückliefert auch wenn der Benutzer KEIN Datum auswählt und das Fenster schließt. In diesem Fall möchte ich aber auch KEINE Änderung im Hauptformular.
Wie erfahre ich nun, ob eine Datum selektiert wurde oder nicht? Die Fnuktion ShowKalender sollte doch besser ein True/False zurückgeben. Aber wo lese ich dann das Datum aus?

Dann könnte ich schreiben:

Delphi-Quelltext
1:
if ShowKalender then Datum := ???;                    


SvenAbeln - So 02.01.11 18:22


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function TFormR.ShowKalender(out Date: TDate): boolean;
begin
  Result := FormKalender.ShowModal = mrOk;
  if Result then
    Date := FormKalender.MonthCalendar1.Date;  
end;


if ShowKalender(Datum) then 
  // mach was mit dem Datum


Quake User - So 02.01.11 18:41

user profile iconSvenAbeln hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function TFormR.ShowKalender(out Date: TDate): boolean;
begin
  Result := FormKalender.ShowModal = mrOk;
  if Result then
    Date := FormKalender.MonthCalendar1.Date;  
end;


if ShowKalender(Datum) then 
  // mach was mit dem Datum


Danke, das funktioniert gut so. Ich setze nun noch bei Button Klick (Übernahme Datum) ModalResult:= mrOk der KalenderForm.


jaenicke - So 02.01.11 23:02

user profile iconQuake User hat folgendes geschrieben Zum zitierten Posting springen:
Danke, das funktioniert gut so. Ich setze nun noch bei Button Klick (Übernahme Datum) ModalResult:= mrOk der KalenderForm.
Oder du schreibst gar keinen Code und setzt bei dem Button ModalResult auf mrOk. ;-)