This depends entirely on how the form is used.
Modal forms
The simplest case is when the form is modal. Then you typically use the following idiom:
procedure TForm1.btnFrogPropertiesClick(Sender: TObject);
var
Frm: TFrogPropertiesForm;
begin
Frm := TFrogPropertiesForm.Create(Self);
try
Frm.ShowModal;
finally
Frm.Free;
end;
end;
Or, if you want to do some special processing if the user closes the dialog box by clicking the OK button (and not the Cancel button):
procedure TForm1.btnFrogPropertiesClick(Sender: TObject);
var
Frm: TFrogPropertiesForm;
begin
Frm := TFrogPropertiesForm.Create(Self);
try
if Frm.ShowModal = mrOk then
UpdateFrog;
finally
Frm.Free;
end;
end;
Notice that I use Self
as owner in both cases. That isn't necessary for the sake of ownership, since -- quite obviously -- we free the forms as soon as they are closed. But I often use Self
anyway, because I tend to use Position = poOwnerFormCenter
for my dialogs.
Independent windows that are freed when you close them
Another particularly simple case is when you dynamically create (possibly multiple) instances of a form class and want to display them on-screen in a non-modal fashion until the user closes them, in which case the instances are freed. If so, it is really simple:
procedure TForm1.Button1Click(Sender: TObject);
var
ImageViewer: TImageViewerFrm;
begin
ImageViewer := TImageViewerFrm.Create(nil);
ImageViewer.Image := 'flower.jpg';
ImageViewer.Show;
end;
assuming it has a public property named Image
that takes the file name of an image file to display.
This will create and show the form when you click the button. To make sure it is freed when you close it, just add an OnClose
handler to the TImageViewerFrm
and set the Action
parameter to caFree
:
procedure TImageViewerFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
Using this approach, you can create any number of image viewer forms with different images, and they will all live until the user closes them, or until the application is terminated.
Other approaches
Of course, there are many more possible scenarios, and, therefore, many more possible solutions. In some cases you might want to have full control over the forms of a particular type, and so you store them in an array. It is fine to free them using MyForm.Free
or FreeAndNil(ImageForms[4])
.
FreeAndNil(X)
effectively does X.Free; X := nil
(but in a safer manner), that is, it sets the variable to nil
after it has freed the object it used to point to. That way you avoid a dangling pointer. In some cases, you must do this. (But now I am digressing. This applies to Delphi objects in general, and has nothing to do with forms in particular.)
But in Delphi you never free an object (a form or not) by writing X.Destroy
. You use X.Free
which effectively does if X <> nil then X.Destroy
.
If you want to learn more about this, I strongly recommend buying a good textbook about Delphi programming. There's no more efficient way of really learning it.