Einzelnen Beitrag anzeigen

Benutzerbild von Der Jan
Der Jan

Registriert seit: 22. Dez 2005
289 Beiträge
 
Delphi XE7 Ultimate
 
#1

Formular als MDI-Child und modalen Dialog nutzen

  Alt 18. Jan 2006, 08:28
Hallo zusammen,

ich hatte das Problem, ein Formular in einer Anwendung sowohl als MDI-Child als auch modal als Dialog darstellen zu wollen. Da die Lösung, die ich gefunden habe (genau genommen sind es zwei), recht gut funktioniert und auch für andere interessant sein könnte, poste ich sie mal, vielleicht wäre das ja was für die Code-Library.

Die erste Lösung.
Wir Erzeugen uns ein Formular, Eigenschaft Visible im OI auf False. Wir erweitern die erzeugte Form-Klasse, überschreiben zwei Konstruktoren und Loaded und CreateParams:

Delphi-Quellcode:
type
  TMyForm = class(TForm)
  //...
  private
    f_blChild: boolean;
    f_Parent: TWinControl;
  protected
  //...
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Loaded; override;
  public
  //...
    //Der "normale" Konstruktor für den modalen Dialog
    constructor Create(AOwner: TComponent); overload; override;
    //Der Konstruktor für das MDI-Form
    constructor Create(AOwner: TComponent; AParent: TWinControl); reintroduce; overload;
  end;

//...

//-----------------------------------------------------------------------------
constructor TMyForm.Create(AOwner: TComponent);
begin
  f_blChild := false;
  inherited Create(AOwner);
end;
//-----------------------------------------------------------------------------
constructor TMyForm.Create(AOwner: TComponent; AParent: TWinControl);
begin
  f_blChild := true;
  f_Parent := AParent;
  inherited Create(AOwner);
end;
//-----------------------------------------------------------------------------
procedure TMyForm.Loaded;
begin
  inherited;
  if(f_blChild) then begin
    Parent := f_Parent;
    //Hier kann man noch Werte setzen, wie Align, Größe etc.
    Position := poDefault;
  end else
    Position := poOwnerFormCenter;
end;
//-----------------------------------------------------------------------------
procedure TMyForm.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  if(f_blChild) then
    Params.Style := Params.Style or WS_CHILD;
end;
Die Anwendung ist simpel:

Delphi-Quellcode:
//Erzeugen des Formulars als modaler Dialog:
frmDialog := TMyForm.Create(self);
frmDialog.ShowModal;
frmDialog.Release;

//Erzeugen als MDI-Child, Aufrufer sollte MDI-Window sein
frmChild := TMyForm.Create(self, self);
frmChild.Show;

//Erzeugen als MDI-Child, Parent kann auch z.B. ein Panel sein
frmChild := TMyForm.Create(self, pnlParent);
frmChild.Show;
Die zweite Lösung:
Wir leiten uns eine Klasse vom TForm ab, in der alles nötige getan wird und packen das Ganze zweckmäßigerweise in eine eigene Unit:

Delphi-Quellcode:
unit nhModalAndMDIForm;
//-----------------------------------------------------------------------------
interface

uses Classes, Forms;

type
  TModalAndMDIForm = class(TForm)
  private
    f_blChild: boolean;
  protected
    procedure Loaded; override;
    procedure DoClose(var Action: TCloseAction); override;
  public
    constructor Create(AOwner: TComponent); overload; override;
    constructor CreateChild(AOwner: TComponent);
    property IsChild: boolean read f_blChild;
end;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
implementation

uses SysUtils;
//-----------------------------------------------------------------------------
constructor TModalAndMDIForm.Create(AOwner: TComponent);
begin
  f_blChild := false;
  inherited Create(AOwner);
end;
//-----------------------------------------------------------------------------
constructor TModalAndMDIForm.CreateChild(AOwner: TComponent);
begin
  f_blChild := true;
  GlobalNameSpace.BeginWrite;
  try
    inherited CreateNew(AOwner);
    if(not(csDesigning in ComponentState)) then begin
      Include(FFormState, fsCreating);
      try
        FormStyle := fsMDIChild;
        if(not(InitInheritedComponent(self, TForm))) then
          raise Exception.CreateFmt('Kann Formular %s nicht als MDI-Child erzeugen', [ClassName]);
      finally
        Exclude(FFormState, fsCreating);
      end;
    end;
  finally
    GlobalNameSpace.EndWrite;
  end;
end;
//-----------------------------------------------------------------------------
procedure TModalAndMDIForm.Loaded;
begin
  inherited;
  if(f_blChild) then
    Position := poDefault
  else begin
    Position := poOwnerFormCenter;
    BorderStyle := bsDialog;
  end;
end;
//-----------------------------------------------------------------------------
procedure TModalAndMDIForm.DoClose(var Action: TCloseAction);
begin
  if(f_blChild) then
    Action := caFree;
  inherited DoClose(Action);
end;
//-----------------------------------------------------------------------------
end.
Die Anwendung ist ebenfalls einfach:

Delphi-Quellcode:
uses nhModalAndMDIForm;

type
  TMyForm = class(TModalAndMDIForm) //That's all folks
  //...
end;

//Modal
frmDialog := TMyForm.Create(self);
frmDialog.ShowModal;
frmDialog.Release;

//MDI-Child
frmDialog := TMyForm.CreateChild(self);
frmDialog.Show;
Über das Property IsChild kann festgestellt werden, ob das Formular als MDI-Child. Dies kann man zum Beispiel wie folgt genutzt werden:

Delphi-Quellcode:
procedure TMyForm.FormShow(Sender: TObject);
begin
  if(not IsChild) then begin //Modaler Dialog: Buttons zum Bestätigen/Abbrechen anzeigen
    btnOk.Visible := true;
    btnAbort.Visible := true;
  end;
end;
Vor- und Nachteile der Varianten:

1. Variante:
  • Vorteil:
  • Die MDI-Child können auch in anderen WinControls außer dem MDI-Window, z.B. in einem Panel "gehostet" werden.
  • Nachteil:
  • Bei den MDI-Childs handelt es sich (zumindest im Sinne der VCL) nicht um "echte" Childs. D.h. sie zeigen nicht das normale Verhalten beim Maximieren etc., werden nicht automatisch in das WindowMenu aufgenommen...
2. Variante:
  • Vorteil:
  • Die MDI-Childs verhalten sich ganz normal, wie original...
  • Nachteil:
  • Sind mir noch keine bekannt.


So, bleibt mir noch, euch viel Spaß mit dem Code zu wünschen...
Gruß, Jan
  Mit Zitat antworten Zitat