Up to now I have ignored the issue of form creation. You know that when the form is created, you receive the OnCreate event and can change or test some of the initial form's properties or fields. The statement responsible for creating the form is in the project's source file:
begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end .
To skip the automatic form creation, you can either modify this code or use the Forms page of the Project Options dialog box (see Figure 7.10). In this dialog box, you can decide whether the form should be automatically created. If you disable automatic creation, the project's initialization code becomes the following:
Figure 7.10:
The Forms page of the Delphi Project Options dialog box
begin Applications.Initialize; Application.Run; end .
If you now run this program, nothing happens. It terminates immediately because no main window is created. The call to the application's
CreateForm
method creates a new instance of the form class passed as the first parameter and
Something else happens behind the scenes. When CreateForm is called, if there is currently no main form, the current form is assigned to the application's MainForm property. For this reason, the form indicated as Main Form in the dialog box shown in Figure 7.10 corresponds to the first call to the application's CreateForm method (that is, when several forms are created at startup).
The same holds for closing the application. Closing the main form terminates the application, regardless of the other forms. If you want to perform this operation from the program's code, call the Close method of the main form, as you've done several times in past examples.
Regardless of the manual or automatic creation of forms, when a form is created, you can intercept many events. Form-creation events are
OnCreate indicates that the form is being created.
OnShow indicates that the form is being displayed. Besides main forms, this event happens after you set the Visible property of the form to True or call the Show or ShowModal method. This event is fired again if the form is hidden and then displayed again.
OnActivate indicates that the form becomes the active form within the application. This event is fired every time you move from another form of the application to the current one.
Other events, including
OnResize
and
OnPaint
,
| Note |
In Qt, the
OnResize
event won't fire as it does in
|
As you can see in the previous list, every event has a specific role apart from form initialization, except
OnCreate
, which is
However, there is an alternative approach to adding initialization code to a form: overriding the constructor. This is usually done as
constructor TForm1.Create(AOwner: TComponent); begin inherited Create (AOwner); // extra initialization code end;
Before the call to the
Create
method of the base class, the properties of the form are still not loaded and the internal
| Note |
Up to version 3, Delphi used a different creation order, which has led to the OldCreateOrder compatibility property of the VCL. When this property is set to the default value of False, all the code in a form constructor is executed before the code in the OnCreate event handler (which is fired by the special AfterConstruction method). If you enable the old creation order, instead, the constructor's inherited call leads to the call of the OnCreate event handler. You can examine the behavior of the CreateOrd example using the two values of the OldCreateOrder property. |
When you close the form using the
Close
method or by the usual means (Alt
+
F4, the system menu, or the Close button), the
OnCloseQuery
event is called. In this event, you can ask the
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin if MessageDlg ( 'Are you sure you want to exit?' , mtConfirmation, [mbYes, mbNo], 0) = mrNo then CanClose := False; end;
If
OnCloseQuery
indicates that the form should still be closed, the
OnClose
event is called. The third step is to call the
OnDestroy
event, which is the
| Note |
To be more precise, the BeforeDestruction method generates an OnDestroy event before the Destroy destructor is called. That is, unless you have set the OldCreateOrder property to True, in which case Delphi uses a different closing sequence. |
So, what is the use of the intermediate OnClose event? In this method, you have another chance to avoid closing the application, or you can specify alternative "close actions." The method has an Action parameter passed by reference. You can assign the following values to this parameter:
caNone The form is not allowed to close. This corresponds to setting the CanClose parameter of the OnCloseQuery method to False.
caHide The form is not closed, just hidden. This makes sense if there are other forms in the application;
otherwise , the program terminates. This is the default for secondary forms, and it's the reason I had to handle the OnClose event in the previous example to close the secondary forms.caFree The form is closed, freeing its memory, and the application eventually terminates if this was the main form. This is the default action for the main form and the action you should use when you create multiple forms dynamically (if you want to remove the windows and destroy the corresponding Delphi object as the form
closes ).caMinimize The form is not closed but only minimized. This is the default action for MDI child forms.
| Note |
When a user shuts down Windows, the OnCloseQuery event is activated, and a program can use it to stop the shutdown process. In this case, the OnClose event is not called even if OnCloseQuery sets the CanClose parameter to True. |