Bernhard hat schon vollkommen recht: Die sauberste Lösung wäre die dynamische Erzeugung der Formulare bei Bedarf. Leider kann man gewachsene Projekte nur recht schwer auf soetwas umstellen. Bei neuen Projekten werde ich das aber in Zukunft so machen.
Auch bei der Umstellung existierender Projekte kann ich Dir einen Ansatz zur Prüfung empfehlen, den ich derzeit mittels
Emballo bereits umsetze: Hier nimmt Dir das Framework das Instanziieren ab und Du greifst auf Deine Formulare und Service-Komponenten nur noch über Funktionen zu. Das passiert über Interfaces, so dass es keine
Unit-Referenzen erfordert.
In der .dpr steht dann bspw.
Delphi-Quellcode:
//Services
RegisterFactory(IdcXMLStore, TdcXMLStore).Singleton.Done;
RegisterFactory(IdcSettings, TdcSettings).Singleton.Done;
RegisterFactory(IdcLanguage, TdcLanguages).Singleton.Done;
RegisterFactory(IdcObservers, TdcObservers).Singleton.Done;
RegisterFactory(IdcTimer, TdcTimer).Done;
// Komponenten
RegisterFactory(IdcMainMenuPanel, TdcMainMenuPanel).Singleton.Done;
RegisterFactory(IdcTileHeader, TdcTileHeader).Done;
RegisterFactory(IdcTileView, TdcTileView).Singleton.Done;
RegisterFactory(IdcListMenu, TdcListMenu).Done;
RegisterFactory(IdcEasyItem, TdcEasyItem).Done;
RegisterFactory(IdcTreeview, TdcTreeView).Done;
Application.CreateForm(TdcMainForm, dcMainForm);
// Forms & Frames
RegisterFactory(IdcMainForm, dcMainForm).Singleton.Done;
RegisterFactory(IdcFrameMenuStudio, TdcFrameMenuStudio).Done;
RegisterFactory(IdcFrameMenuSettings, TdcFrameMenuSettings).Singleton.Done;
Application.Run;
Lediglich der Aufruf
Application.CreateForm
"tut" tatsächlich etwas, der Rest wird nur registriert.
Die Deklaration von MainForm ist wie gewohnt, z.B.:
Delphi-Quellcode:
type
TdcMainForm = class(TBaseForm, IdcMainForm)
Und in einer Interface-
Unit deklariere ich:
Delphi-Quellcode:
type
IdcMainForm = interface(IdcWinControl)
['{344DCBC9-1B4B-48C6-B7C4-E5CC329EA658}']
function BaseForm : TWinControl;
procedure ApplyStyle;
end;
function DI_MainForm : IdcMainForm;
Wobei die Funktion nur kapselt:
Delphi-Quellcode:
function DI_MainForm : IdcMainForm;
begin
Result := DIService.Get<IdcMainForm>;
end;
Emballo kommt bei mir also nur an 2 Stellen in's Spiel: in der
dpr mit
RegisterFactory
und in der Interface-
Unit im Funktions-Aufruf mit
DIService.Get<IdcMainForm>
.
Lohn der Mühe ist nun, das ich überall, wo ich die Interface-
Unit einbinde, ich mittels Funktionsaufruf auf die Forms usw. zugreifen kann, ohne deren Units einzubinden und mich um die Instanziierung und/oder Freigabe kümmern zu müssen. Das gibt übersichtlicheren Code und keine Cross-Referenzen.
In diesem Beispiel nutze ich mehrere Service-Interfaces (DI_XXX) für das Einblenden eines Frames in das Hauptformular:
Delphi-Quellcode:
DI_BlendTransition.Start(DI_MainForm.BaseForm);
try
DI_Stages.ActiveStageViewIndex := aButton.StageViewIndex;
DoOnActiveStageItemChanged;
finally
DI_BlendTransition.Stop;
end;
Dabei muss keine
Unit für das MainForm (oder die Transition) eingebunden werden, den die "kennen" sich über die Interface-Deklarationen und Emballo liefert mir den Rest und kümmert sich auch (mit Delphi) um die Freigabe
Sorry für die etwas längere Antwort, aber ich wollte nicht nur eine Link posten.