To program our previous programs user interface for creating (and freeing) the auxiliary form, add a GroupBox to the form and then add Create and Free buttons to the GroupBox.
Change unit MainForm to the following:
20 implementationSince at any particular moment frmAuxiliary may or may not exist, at each stage we need to test for frmAuxiliarys existence before trying to carry out any operations on it.
21 uses AuxForm;
22 {$R *.dfm}
23 procedure TfrmMain.radAuxShowClick(Sender: TObject) ;
24 begin
25 try
26 frmAuxiliary.Show;
27 except
28 ShowMessage ('Aux. Form does not exist') ;
29 radAuxShow.Checked := False;
30 end;
31 end;
32 procedure TfrmMain.radAuxHideClick(Sender: TObject) ;
33 begin
34 try
35 frmAuxiliary.Hide;
36 except
37 ShowMessage ('Aux. Form does not exist') ;
38 radAuxHide.Checked := False;
39 end;
40 end;
If we try to show a non-existent frmAuxiliary, line 26 throws an exception that is then caught by lines 28 and 29. Similarly, if we try to hide a non-existent form, line 35 throws an exception that is caught by lines 37 and 38. If we try to free a non-existent form (line 51) line 55 takes care of the required exception handling. Exception handling will not catch an attempt to create another frmAuxiliary should one already exist, so we use a different approach when instantiating frmAuxiliary. Line 43 tests whether the name frmAuxiliary refers to a valid object. If it doesnt, line 44 creates it. If it does, line 46 issues a message to the user and there is no attempt to instantiate a second TfrmAuxiliary object.
41 procedure TfrmMain.btnCreateClick(Sender: TObject) ;
42 begin
43 if frmAuxiliary = nil then
44 frmAuxiliary := TForm.Create(nil) ;
45 else
46 ShowMessage ('Aux. Form already exists') ;
47 end;
48 procedure TfrmMain.btnFreeClick(Sender: TObject) ;
49 begin
50 try
51 frmAuxiliary.Hide;
52 frmAuxiliary.Free;
53 frmAuxiliary := nil;
54 except
55 ShowMessage ('Form does not exist') ;
56 end;
57 end;
58 end.
Well use this example to look a little more closely at an objects life cycle and at the way it can be referenced by other objects. Line 21 is a local uses clause stating that this unit has access to the public sections of unit AuxForm. Unit Auxform declares a public variable (ie an object reference) frmAuxiliary of type TfrmAuxiliary (step 2, lines 10 & 11). Thus reference frmAuxiliary is visible to unit MainForm. If an object reference has the value nil it is not currently referring to any object: any other value is a reference to an object. When the user clicks btnCreate, its OnClick event handler runs. This first checks whether reference frmAuxiliary refers to a valid object (line 43 above). If not, it moves to line 44:
frmAuxiliary := TfrmAuxiliary.Create(nil)
This invokes TfrmAuxiliarys Create method, sending it the value Self. TfrmAuxiliary is declared publicly in unit AuxForm, and unit MainForm has access to AuxForm through its local uses clause (line 21 above). TfrmAuxiliary is derived from TForm (step 2 line 7). TForm has a method called Create, and so TfrmAuxiliary inherits Create from TForm: an example of how inheritance facilitates reuse. Create is a special kind of method called a Constructor. A Constructor creates an object from the template provided in a class definition. For VCL classes, this constructor requires an owner of the object as an input parameter. Here we give nil as the owner. The constructor returns a reference to the newly created object. In line 44 this return value is assigned to frmAuxiliary.
Returning to the If statement in line 43, if frmAuxiliary refers to a valid object, line 46 issues a message stating that the object already exists and no attempt is made to create another instance of this object. Now that it exists, frmAuxiliary can be shown and hidden as often as required by the two RadioButton event handlers.
When the time comes to destroy frmAuxiliary, line 51 first Hides it. If frmAuxiliary exists, this statement will be successful and line 52 will then invoke frmAuxiliarys Release method. Release is a Destructor type method that TfrmAuxiliary has inherited from TForm. After freeing frmAuxiliary, it no longer exists and so we must then set its reference to nil (line 53). After this, btnFrees OnClick event handler terminates. The other possibility is that frmAuxiliary does not exist when line 51 executes. The attempt to refer to it then raises an exception and execution continues in the Except section of the Try Except End construct (ie at line 55).
Run and test this program. In the Delphi IDE a raised exception can optionally cause a break into the debugger at the point the exception is raised. To continue when this happens, press <F9> to resume running or <F7> or <F8> to single-step or step-over respectively.
Next Chapter... Methods, and event handler linking; Problems and Solutions, and more ... stay tuned.


