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...