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/)
-   -   Delphi Form nichtmodal anzeigen (https://www.delphipraxis.net/11458-form-nichtmodal-anzeigen.html)

weltaran 7. Nov 2003 07:20


Form nichtmodal anzeigen
 
Hallo Leute!

Bisher habe ich in meiner Anwendung nur modale Fenster benutzt (ich habe jeweils eine Klassenmethode verwendet um das Formular zu erzeugen), der Aufruf ist dann in einer Zeile erledigt, man braucht sich weiter um nichts zu kümmern.

Jetzt muss ich aber eine Art Hilfefenster mit (u.a.) einem Hilfetext aufrufen können (nichtmodal versteht sich), zudem sollen bestimmte Einstellungen, die im Hilfefenster gemacht werden vom aufrufenden Formular übernommen werden.

Am liebsten wäre es mir, wenn ich wieder eine Klassenmethode benutzen könnte. Ich habe bisher das Problem, dass das Hilfefenster wenn ich es mit 'Show' anzeige völlig entkoppelt ist vom aufrufenden Formular; ich muss aber bei schließen des Hauptfensters auch das Hilfefenster schließen können und die dort gemachten Änderungen (nach Rückfrage) übernehmen können.

Eigentlich ein ganz normales Problem, aber ich habe in meinen 2200 Seiten Delphi Know-how nichts dazu gefunden.

Ciao

Leuselator 7. Nov 2003 07:33

Re: Form nichtmodal anzeigen
 
Im OnDestroy des Aufrufenden Fensters Code zum Schließen des aufgerufenen Fensters einbasteln und ev. Werte von dort abfragen:
Delphi-Quellcode:
Unit MainForm
uses SubForm; //Verweis auf SubForm-Unit
type
  TMainForm : class(TForm)
    ...
    procedure FormDestroy(Sender: TObject);
    ...
  end;

var frmMain : TMainForm;

implementation
procedure TMainForm.FormDestroy(Sender: TObject);
begin
  if frmSubForm.Showing then begin
    //Frage alle Werte aus SubForm ab
    self.Irgendeinwert := frmSubForm.DerGleicheWert;
  end;
end;
end.

Unit SubForm
type
  TSubForm = class(TForm)
    ...
    procedure FormShow(Sender: TObject);
  end;
var frmSubForm : TSubForm;
implementation
uses MainForm; //Rückverweis auf HauptForm-Unit

procedure TSubForm.FormShow(Sender: TObject);
begin
  self.Irgendeinwert := frmMain.Irgendeinwert;
end;

end.
Gruß

weltaran 11. Nov 2003 08:33

Re: Form nichtmodal anzeigen
 
OK, aber ich muss zudem die SubForm von verschiedenen Klassen von Formularen (TfrmA, TfrmB, ... alle von TForm abgeleitet) aus aufrufen können.

Typische Abläufe:

A)
-MainForm1 wird erstellt.
-Mittels Button auf MainForm1 wird SubForm aufgerufen und Hilfetext aus MainForm1 angezeigt.
-Hilfetext wird in SubForm geändert.
-SubForm wird geschlossen, Hilfetext in MainForm1 soll aktualisiert werden.
-SubForm wird erneut aufgerufen, Aktualisierter Hilfetext wird angezeigt
-SubForm wird geschlossen
-MainForm1 wird geschlossen


B)
-MainForm1 wird erstellt.
-Mittels Button auf MainForm1 wird SubForm aufgerufen und Hilfetext aus MainForm1 angezeigt.
-Hilfetext wird in SubForm geändert.
-MainForm1 wird geschlossen, geänderter Hilfetext soll in MainForm1 aktualisiert (und weiterverarbeitet) werden

C)
ersetze bei A) MainForm1 durch MainForm2



Vielleicht habt ihr eine Idee für meine (eigentlich nicht ungewöhnliche) Aufgabenstellung

Ciao

Leuselator 11. Nov 2003 09:34

Re: Form nichtmodal anzeigen
 
Wenn ich kapiert habe, was Du willst, dann mußt Du dem SubForm ein Property verpassen vom Typ TStringList z.B.
Vor dem Aufruf aus irgendeinem Form setzt Du dann dieses Property auf eine StringListe, die im aufrufenden Form definiert ist. Im Subform hast Du (z.B.) ein Memo, dessen Lines-Eigenschaft du das Property im OnShow zuweist. Beim Schließen des Subforms schreibst Du den Inhalt des Memos zurück in die StringList des Aufrufer. Damit beim nochmaligen Aufruf des aufgerufenen und angezeigten Subforms durch ein weiteres MainForm die bis dahin erfolgten Änderungen nicht überschrieben werden, prüfst Du vor dem Setzten des Property's ob es schon gesetzt ist - wenn ja, schreibst Du erst die Änderungen in das ursprüngliche MainForm zurück und übernímmst dann die Werte des neuen Aufrufers:
Delphi-Quellcode:
unit SubForm;

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,stdctrls;

type
  TSubForm = class(TForm)
  private
    FStringList : TStringList;
    FMemo : TMemo;
  protected
    procedure SetStringList(Value : TStringList);
    procedure FormHide(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
    property Text : TStringList read FStringList write SetStringList;
  end;

implementation

constructor TSubForm.Create(AOwner: TComponent);
begin
  inherited;
  FStringList := nil;
  FMemo := TMemo.Create(self);
  with FMemo do begin
    Parent := self;
    Left := 10;
    Top := 10;
    Width := 200;
    Height := 200;
  end;
end;

procedure TSubForm.SetStringList(Value : TStringList);
begin
  if Assigned(FStringList) then begin // wenn schon vorhanden, dann Änderungen zurückschreiben
    FStringList.Assign(FMemo.Lines);
  end;
  FStringList := Value; //zeigt jetzt auf Die neue StringListe
end;

procedure TSubForm.FormHide(Sender: TObject);
begin
  if Assigned(FStringList) then begin // Änderungen zurückschreiben
    FStringList.Assign(FMemo.Lines);
  end;
  FStringList := nil; // zeigt nun nirgendwohin
end;
Im Projekt mußt Du zentral das SubForm erzeugen und in den Aufrufenden Forms muß die Variable MeinSubForm initialisiert sein (Create) Angenommen, Du hast in einem MainForm die Variable MeinHilfeText(TStringList) erzeugt und gefüllt, dann erfolgt der Aufruf des Subforms folgendermassen:
Delphi-Quellcode:
procedure TMainForm.SchowSubForm;
begin
  MeinSubForm.StringListe := MeinHilfeText; // weist dem SubForm Deinen Hilfetext zu;
  MeinSubForm.Show;
end;
Du hast recht - ist etwas, was man öfter braucht. um so mehr verwundert Deine Frage - wie wär's mit 'nem Buch - zum Beispiel "Jetzt lerne ich Delphi"?
Gruß

weltaran 11. Nov 2003 10:48

Re: Form nichtmodal anzeigen
 
Ich habe das so ähnlich wie du, aber mein Problem ist jetzt noch, die Daten zurückzuschreiben. Die SubForm soll nicht aus verschiedenen Instanzen von MainForm (vielleicht habe ich mich vorhin da falsch ausgedrückt) sondern von verschiedenen Klassen (welche von TForm abgeleitet sind) aufgerufen werden. Wenn ich also in jeder MainForm Klasse eine Methode 'UpdateHelpText(tsValue: TStrings)' implementiere, dann kann ich in der SubForm trotzdem nicht 'AOwner.UpdateHelpText(FStringList)' aufrufen, da AOwner keine solche derartige Methode hat (sondern ein Nachfahre von AOwner). Ich muss also eine Typumwandlung mit AOnwer machen. Hierzu übergebe ich in TSubForm.Create auch noch den ClassName der MainForm, aber weder ClassName(AOwner).Update... noch (AOwner as ClassName).Update.. findet der Compiler gut.


Danke das du dir so viel Zeit nimmst für mein Problem.


Literatur: - 'Borland Delphi 5', Verlag Hanser
- 'GoTo Delphi 6', Addison-Wesley
jeweils Fehlanzeige:-|

weltaran 11. Nov 2003 11:44

Re: Form nichtmodal anzeigen
 
OK, ich denke ich habs jetzt. Ich verpasse den Main-Formularen nun noch ein Interface und übergebe dieses dem SubForm. Somit kann ich ohne Rücksicht auf den Typ der aufrufenden Formulars die Methode UpdateHelpText(..) aufrufen.

Danke für die Hilfe

P.S Huch! Nur durch FRAGEN bin ich zum Junior-Member geworden. Jetzt hab ich ja ein richtig schlechtes Gewissen.

Leuselator 12. Nov 2003 02:57

Re: Form nichtmodal anzeigen
 
Ok. Du hast meine leicht spitze Bemerkung mit dem Buch nicht krummgenommen - gut. So langsam ahne ich, wo Deine Reise hingehen soll. Wenn ich richtig vermute, dann solltest Du so eine Art CallBack-Funktion in Betracht ziehen. Damit überläßt Du dem MainForm die Kontrolle über die Art und Weise der Abspeicherung der Hilfetexte. Dann also so:
Delphi-Quellcode:
Type
  TMeinCallBack =procedure (Text : TStrings) of object;

  TMeinHilfsForm = class(TForm)
  private
    FmemHelpText : TMemo;
    FbtnClose : TButton;
    FCallBack : TMeinCallBack;
    FMeinCallBack: TMeinCallBack;
  protected
    procedure SetCallBack(Value:TMeinCallBack);
    procedure HideAway(Sender : TObject);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property ReturnProc : TMeinCallBack read FMeinCallBack write SetCallBack;
    procedure ShowWithText(Text:TStrings);
  published
  end;

  TMeinMainForm = class(TForm)
  private
    FbtnShowHelp : TButton;
    FMeinHilfsForm: TMeinHilfsForm;
    FMeinHilfstext : TStringList;
  protected
    procedure SaveHelpText(Text:TStrings); virtual; // kann in Nachfahren
                                                    // überschrieben werden
    procedure ShowHelp(Sender:TObject);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property HelpWindow : TMeinHilfsForm read FMeinHilfsForm write FMeinHilfsForm;
  published
  end;

implementation

{ TMeinHilfsForm }
constructor TMeinHilfsForm.Create(AOwner: TComponent);
begin
  inherited;
  FmemHelpText := TMemo.Create(self);
    // Werte setzen (Größe usw.)
  FbtnClose   := TButton.Create(self);
    // Werte setzen (Größe usw.)
  FbtnClose.OnClick := HideAway;

end;

procedure TMeinHilfsForm.HideAway(Sender : TObject);
begin
  if Assigned(FCallBack) then FCallBack(FmemHelpText.Lines);
  FCallBack := nil;
  self.Hide;
end;

procedure TMeinHilfsForm.SetCallBack(Value:TMeinCallBack);
begin
  if Assigned(FCallBack) then FCallBack(FmemHelpText.Lines);
  FCallBack := Value;
end;

procedure TMeinHilfsForm.ShowWithText(Text: TStrings);
begin
  if Assigned(FCallBack) then begin
  FmemHelpText.Lines.Assign(Text);
  self.Show;
  end else raise Exception.Create('Keine CallBack-Prozedur angegeben!'#13#10+
                                  'Bitte vor Aufruf von ShowWithText '+
                                  'das Property ReturnProc setzen!');
end;

destructor TMeinHilfsForm.Destroy;
begin
  FreeAndNil(FmemHelpText);
  FreeAndNil(FbtnClose);
  inherited;
end;

{ TMeinMainForm }
constructor TMeinMainForm.Create(AOwner: TComponent);
begin
  inherited;
  FbtnShowHelp := TButton.Create(self);
  FbtnShowHelp.OnClick := ShowHelp;
  FMeinHilfstext := TStringList.Create;
  FMeinHilfstext.Text := 'Das ist mein Hilfetext!';
end;

procedure TMeinMainForm.SaveHelpText(Text: TStrings);
begin
  FMeinHilfstext.Assign(Text);
end;

procedure TMeinMainForm.ShowHelp(Sender: TObject);
begin
  if Assigned(FMeinHilfsForm) then begin
    FMeinHilfsForm.ReturnProc := SaveHelpText;
    FMeinHilfsForm.ShowWithText(FMeinHilfstext);
  end;
end;

destructor TMeinMainForm.Destroy;
begin
  FreeAndNil(FbtnShowHelp);
  FreeAndNil(FMeinHilfstext);
  inherited;
end;
Wenn Du nun Deine MainForms nicht von TForm sondern von TMeinMainForm ableitest, hast Du die Funktionalität, die Du haben möchtest in allen Erben von TMeinMainForm.

Gruß


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