Communicating Between Forms

Finding out how a modal form was closed

woman using laptop
Hero Images/Getty Images

Finding out how a modal form was closed

Modal forms offer specific features that we cannot have when displaying non-modally. Most commonly, we will display a form modally to isolate its processes from anything that might otherwise happen on the main form. Once these processes complete, you might want to know whether the user pressed the Save or Cancel button to close the modal form. You can write some interesting code to accomplish this, but it does not have to be difficult.

Delphi supplies modal forms with the ModalResult property, which we can read to tell how the user exited the form.

The following code returns a result, but the calling routine ignores it:

var
  F:TForm2;
begin
 F := TForm2.Create(nil);
 F.ShowModal;
 F.Release;
 ...

The example shown above just shows the form, lets the user do something with it, then releases it. To check how the form was terminated we need to take advantage of the fact that the ShowModal method is a function that returns one of several ModalResult values. Change the line

F.ShowModal

to

if F.ShowModal = mrOk then

We need some code in the modal form to set up whatever it is we want to retrieve. There is more than one way to get the ModalResult because TForm is not the only component having a ModalResult property - TButton has one too.

Let us look at TButton's ModalResult first. Start a new project, and add one additional form (Delphi IDE Main menu: File -> New -> Form).

This new form will have a 'Form2' name. Next add a TButton (Name: 'Button1') to the main form (Form1), double click the new button and enter the following code:

procedure TForm1.Button1Click(Sender: TObject);
var f : TForm2;
begin
  f := TForm2.Create(nil);
  try
    if f.ShowModal = mrOk then
      Caption := 'Yes'
    else
      Caption := 'No';
  finally
      f.Release;
  end;
end;

 

Now select the additional form. Give it two TButtons, labelling one 'Save' (Name : 'btnSave'; Caption: 'Save') and the other 'Cancel' (Name : 'btnCancel'; Caption: 'Cancel'). Select the Save button and press F4 to bring up the Object Inspector, scroll up/down until you find the property ModalResult and set it to mrOk. Go back to the form and select the Cancel button, press F4, select the property ModalResult, and set it to mrCancel.

 

It's as simple as that. Now press F9 to run the project. (Depending on your environment settings, Delphi may prompt to save the files.) Once the main form appears, press the Button1 you added earlier, to show the child form. When the child form appears press the Save button and the form closes, once back to the main form note that it's caption says "Yes". Press the main form's button to bring up the child form again but this time press the Cancel button (or the System menu Close item or the [x] button in the caption area). The main form's caption will read "No".

How does this work? To find out take a look at the Click event for TButton (from StdCtrls.pas):

procedure TButton.Click;
var Form: TCustomForm;
begin
  Form := GetParentForm(Self);
  if Form  nil then 
    Form.ModalResult := ModalResult;
  inherited Click;
end;

What happens is that the Owner (in this case the secondary form) of TButton gets its ModalResult set according to the value of the TButton's ModalResult. If you don't set TButton.ModalResult, then the value is mrNone (by defaolt). Even if the TButton is placed on another control the parent form is still used to set its result. The last line then invokes the Click event inherited from its ancestor class.

To understand what goes on with the Forms ModalResult it is worthwhile reviewing the code in Forms.pas, which you should be able to find in ..\DelphiN\Source (where N represents the version number).

In TForm's ShowModal function, directly after the form is shown, a Repeat-Until loop starts, which keeps checking for the variable ModalResult to become a value greater than zero. When this occurs, the final code closes the form.

You can set ModalResult at design-time, as described above, but you can also set the form's ModalResult property directly in code at run-time.

A Beginner’s Guide to Delphi Programming