Mike Torrettinni 198 Posted January 27, 2019 To speed up the opening of my project, I want to only create forms when needed. So, I commented out all CreateForm in Project source, except for Main form. And now when I need to open a form, I use: if Form2 = nil then Application.CreateForm(TForm2, Form2); Form2.ShowModal; this works good.. but, now I have this code all over the Main form unit. Is it possible to have a common method like AccessForm(Form2, True); that would do this code in a method, for all forms: procedure AccessForm(aForm: TForm; aModal: boolean); begin if aForm = nil then Application.CreateForm(aForm, ??? TForm... ??? ); // <-- how to determine what type aForm is? if aModal then aForm.ShowModal else aForm.Show; end; // open Form AccessForm(Form2, True); Is something like this possible? If yes, how I can find out what class a Form is, even before is created? Share this post Link to post
Alexander Elagin 143 Posted January 27, 2019 Maybe something like this? procedure AccessForm(var aForm: TForm; aClass: TFormClass; aModal: Boolean); begin if not Assigned(aForm) then aForm := aClass.Create(Application); Assert(Assigned(aForm)); // just in case :-) if aModal then aForm.ShowModal else aForm.Show; end; ..... AccessForm(Form2, TForm2, True); .... Share this post Link to post
Mike Torrettinni 198 Posted January 27, 2019 Nice, this is better. Is it possible to do this somehow without Form class? I assume not, since we can't get Form's class, if it's nil (not created yet), right? Share this post Link to post
Kryvich 165 Posted January 27, 2019 (edited) 3 hours ago, Mike Torrettinni said: I commented out all CreateForm in Project source, except for Main form. There is option in the project options (Application | Forms) to select what forms to create when an application starts. Edited January 27, 2019 by Kryvich Share this post Link to post
David Heffernan 2345 Posted January 27, 2019 The entire design seems wrong. Don't use a global variable for each form. Remove them. Use a local variable and destroy it when ShowModal returns. 2 Share this post Link to post
ConstantGardener 31 Posted January 27, 2019 TfrmBase = class (TForm) public constructor Create(AOwner: TComponent); override; destructor Destroy; override; class function Execute : boolean; virtual; end; class function TfrmBase.Execute: boolean; var Form: TfrmBase; begin Form:=Create(nil); try Result:=Form.showModal<>mrCancel; finally Form.Release; end; end; Inherit your forms from a BaseClass like this on. If you need an other behavior in the actual class you override the class-function. 2 Share this post Link to post
Mike Torrettinni 198 Posted January 27, 2019 2 hours ago, ConstantGardener said: TfrmBase = class (TForm) public constructor Create(AOwner: TComponent); override; destructor Destroy; override; class function Execute : boolean; virtual; end; class function TfrmBase.Execute: boolean; var Form: TfrmBase; begin Form:=Create(nil); try Result:=Form.showModal<>mrCancel; finally Form.Release; end; end; Inherit your forms from a BaseClass like this on. If you need an other behavior in the actual class you override the class-function. How do I open a form with this approach? Share this post Link to post
Dalija Prasnikar 1396 Posted January 27, 2019 4 hours ago, Alexander Elagin said: Maybe something like this? procedure AccessForm(var aForm: TForm; aClass: TFormClass; aModal: Boolean); begin if not Assigned(aForm) then aForm := aClass.Create(Application); Assert(Assigned(aForm)); // just in case :-) if aModal then aForm.ShowModal else aForm.Show; end; ..... AccessForm(Form2, TForm2, True); .... Just in case... What case? If construction of the form fails you will never hit Assert line anyway. Share this post Link to post
ConstantGardener 31 Posted January 27, 2019 TMYForm.execute; Or if TMYFORM.Execute then begin doSomething; end; Share this post Link to post
Attila Kovacs 629 Posted January 27, 2019 (edited) I prefer caFree action in onClose so I don't have to deal with references at all and doesn't really care if it's shown modal or not. Of course this means the forms are always (re)-created. Edited January 28, 2019 by Attila Kovacs Share this post Link to post
Mike Torrettinni 198 Posted January 27, 2019 5 hours ago, Kryvich said: There is option in the project options (Application | Forms) to select what forms to create when an application starts. Thanks. I never used that option, always changing this in project source. Share this post Link to post
Alexander Elagin 143 Posted January 28, 2019 9 hours ago, Dalija Prasnikar said: Just in case... What case? If construction of the form fails you will never hit Assert line anyway. Have you seen the smile in my comment? I'd never use such design myself (for modal forms I use class functions, non-modal always have their own local variables). This was just an in-situ snippet to show how to use TFormClass and polymorphism in action based on the originally posted code. Share this post Link to post
Dalija Prasnikar 1396 Posted January 28, 2019 1 hour ago, Alexander Elagin said: Have you seen the smile in my comment? I'd never use such design myself (for modal forms I use class functions, non-modal always have their own local variables). This was just an in-situ snippet to show how to use TFormClass and polymorphism in action based on the originally posted code. Some people will just copy paste anything smile or no smile 😉 Share this post Link to post
dummzeuch 1505 Posted January 28, 2019 6 hours ago, David Heffernan said: Can't work out how to delete this post in mobile interface.... You can't delete a post at all. The way to go is to report it so an admin can delete it. Share this post Link to post
Mike Torrettinni 198 Posted January 28, 2019 22 hours ago, Alexander Elagin said: Maybe something like this? procedure AccessForm(var aForm: TForm; aClass: TFormClass; aModal: Boolean); begin if not Assigned(aForm) then aForm := aClass.Create(Application); Assert(Assigned(aForm)); // just in case :-) if aModal then aForm.ShowModal else aForm.Show; end; ..... AccessForm(Form2, TForm2, True); .... I just couldn't make it work with var parameter, it kept giving me : E2033 Types of actual and formal var parameters must be identical So, I changed into a function: function AccessForm2(aForm: TForm; aClass: TFormClass; aModal: Boolean = True): TForm; begin if not Assigned(aForm) then Result := aClass.Create(Application) else Result := aForm; Assert(Assigned(Result)); // just in case :-) if aModal then Result.ShowModal else Result.Show; end; and I call it with: Form2 := AccessForm2(Form2, TForm2, True) as TForm2; Seems a bit complicated... am I doing something wrong? Share this post Link to post
PeterBelow 238 Posted January 28, 2019 2 hours ago, Mike Torrettinni said: I just couldn't make it work with var parameter, it kept giving me : E2033 Types of actual and formal var parameters must be identical So, I changed into a function: function AccessForm2(aForm: TForm; aClass: TFormClass; aModal: Boolean = True): TForm; begin if not Assigned(aForm) then Result := aClass.Create(Application) else Result := aForm; Assert(Assigned(Result)); // just in case :-) if aModal then Result.ShowModal else Result.Show; end; and I call it with: Form2 := AccessForm2(Form2, TForm2, True) as TForm2; Seems a bit complicated... am I doing something wrong? There is one loophole in your design: if a form is destroyed it will not automatically set the form variable the designer created for it to nil. I can only stress what has been posted in some of the other replies: do not use the form variables for forms that are not autocreated! Delete the variable declaration directly after the form unit has been created by the designer. Use local variables for modal forms (or a class method to create, use, and destroy them). For modeless forms you can always find existing instances by looking at the Screen.Forms array, or have the main form (which presumably creates such a form on an as needed basis) keep the reference in a private field. The automatic form variables encourage some bad programming practices (like accessing controls on another form directly) and become worse than useless if you have to have more than one instance of a given form class open at the same time. 1 1 Share this post Link to post
David Schwartz 426 Posted January 31, 2019 I did a CodeRage 9 talk on a topic that might help: https://www.youtube.com/watch?v=qqKx8fQTTfI 1 Share this post Link to post