1

I have a main form and another, "secondary" form. If I close the secondary first, its OnClose handler is called. Unfortunately if I close the main form first, the application terminates and the OnClose of the secondary is not called. This is a problem because I'd like to save the position and size of every form before they are closed. How can I solve this?

kol
  • 27,881
  • 12
  • 83
  • 120

2 Answers2

3

You can use OnDestroy instead of OnClose to save that. And you should probably destroy your secondary form after it is closed (creating before opening):

Form2 := TForm2.Create(Application);
Form2.Open;

And in Form2.OnClose:

Action := caFree;

You will also want to remove the lines in the .dpr that creates secondary forms automatically:

Application.CreateForm(TForm2, Form2);

And maybe disable this autocreation. In D7: Tools >> Environment Options >> Designer >> Disable "Auto-create ..."

Doing all this will save you some memory. Also consider using ShowModal, instead of Show, when you expect the user to close your secondary form before going back to the main one.

GabrielF
  • 2,071
  • 1
  • 17
  • 29
  • Thanks, `OnDestroy` always gets called. The only problem is I want to save visibility too, but `Visible` is always `False` in `OnDestroy` :( – kol Jan 21 '14 at 21:12
  • There is no guaranty that OnDestroy will be called. Details: https://groups.google.com/forum/#!msg/borland.public.delphi.objectpascal/82AG0_kHonU/ft53lAjxWRMJ – Gabriel Mar 01 '17 at 12:17
3

A tidy place to handle this would be the OnCloseQuery event of the main form.

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var i : integer;
begin
  CanClose := true;
  if Application.MainForm = self then begin
    CanClose := MessageDlg('Close the application?', mtConfirmation,
                                          [mbYes, mbNo], 0) = mrYes;
    if CanClose then
      for i := 0 to Screen.FormCount - 1 do
        if Screen.Forms[i] <> self then Screen.Forms[i].Close;
  end;
end;

The first check suggested above is only useful if you have multiple instances of the main form in use. The second check for self is necessary to prevent re-entry.

J...
  • 30,968
  • 6
  • 66
  • 143
  • Thank you, I chose this approach because I have to save the `Visible` property too. It's always `False` in `OnDestroy`, but it has the correct value when the `OnCloseQuery` handler of the main form is called. – kol Jan 21 '14 at 21:15
  • There is no guaranty that OnCloseQuery will be called. Details: https://groups.google.com/forum/#!msg/borland.public.delphi.objectpascal/82AG0_kHonU/ft53lAjxWRMJ – Gabriel Mar 01 '17 at 12:16
  • @NAZCA No, it won't be called if the program calls `Application.Terminate` - presumably if you're doing this it's because you actually want the application to immediately terminate. Dealing with forced termination during windows shutdown is a different issue altogether and should be handled separately. See : http://stackoverflow.com/q/10745151/327083 – J... Mar 01 '17 at 12:23