Title: Delphi "problem": TForm.Create(?) Nil, Self or Application?
When creating Delphi objects dynamically, that inherit from TControl, such as a TForm (representing a form/window in Delphi applications), the constructor "Create" expects an "Owner" parameter. Should you use "nil", "self" or "Application"? Find the answer here...
Suppose you have a form TMyForm in an application, and you want to instantiate it at run-time. The TForm class has a "Create" constructor that creates and initializes a new TForm (or descendant) object:
constructor Create(AOwner: TComponent) ;
The AOwner parameter is the owner of the T(Custom)Form object. The owner of the form is responsible for freeing the form (memory allocated by the form) when needed. What's more the form created appears in the Components array of its owner. Second, the form is destroyed automatically when its owner is destroyed. For forms, the latter is usually more important.
Should you provide "nil", "self" or "Application"?
To understand the answer, you first need to know the meaning of "nil", "self" or "Application":
nil - specifies that no object owns the form - and therefore a developer (you) is responsible for freeing the created form (by calling myForm.Free when you no longer need the form)
Self - specifies the object in which the method is called. If, for example, you are creating a new instance of a TMyForm form from inside a Button's OnClick handler (where this button is placed on a MainForm) - self refers to "MainForm". Thus, when the MainForm is freed - it will also free "MyForm".
Application - specifies a global TApplication type variable created when you run your application. "Application" encapsulates your application as well as providing many functions that occur in the background of the program.
Examples:
Modal forms. When creating a form to be displayed modally and freed when the user closes the form, you use "nil" as the owner, as in:
~~~~~~~~~~~~~~~~~~~~~~~~~
var
myForm : TMyForm;
begin
myForm := TMyForm.Create(nil) ;
try
myForm.ShowModal;
finally
myForm.Free;
end;
end;
~~~~~~~~~~~~~~~~~~~~~~~~~
Modeless forms. You can use "Application" as the owner here:
~~~~~~~~~~~~~~~~~~~~~~~~~
var
myForm : TMyForm;
...
myForm := TMyForm.Create(Application) ;
~~~~~~~~~~~~~~~~~~~~~~~~~
Now, when you terminate (exit) the application, the "Application" object will free the "myForm" instance.
Why and when is TMyForm.Create(Application) NOT recommended? If the form is a modal form (and will be destroyed "right away", as above) you should pass "nil" for the owner.
You could pass "Application", but the problem with this code is the time delay caused by the notification method being sent to every component and form owned or indirectly owned by the Application. If your application consists of many forms with many components (in the thousands), and the form you're creating has many controls (in the hundreds), the notification delay can be significant.
Passing nil as the owner instead of Application will cause the form to appear sooner, and will not otherwise affect the code.
When to use "Self"? If the form you need to create is not modal and is not created from the application's main form, if you use Self as the owner, closing the owner will free the created form.
In general, when creating new form instances, you should not use "Self", use "nil" or "Application" instead (modal/modeless).
So when to use "self"? "Self" can be used, as the owner, if you don't want the form to outlive its creator.
Warning: if you want to dynamically instantiate a Delphi component and explicitly free it sometime later, always pass nil as the owner. Failure to do so can introduce unnecessary risk, as well as performance and code maintenance problems. Read the article to learn more.
Note: in SDI applications, when a user closes the form (by clicking on the [x] button) the form still exists in the memory - it only gets hidden. In MDI applications, closing an MDI child form only minimizes it.
The OnClose event provides an Action parameter (of the TCloseAction type) you can use to specify what happens when a user attempts to close the form. Setting this parameter to "caFree" will free the form.