Recent

Author Topic: Closing a secondary form  (Read 2055 times)

PeterX

  • Sr. Member
  • ****
  • Posts: 404
Closing a secondary form
« on: January 19, 2019, 12:41:30 pm »
Hi,

I came across the code of an old program of mine,
opening an ABOUT box, in a method of the main form:

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.Info(Sender: TObject);
  2. begin
  3.   //  ( This form is NOT autocreated on program start )
  4.   AboutForm:= TAboutForm.Create( Self);
  5.   AboutForm.ShowModal;
  6. end;
  7.  

The var AboutForm is the global var being created automatically when doing "File/New Form"
( .. and renaming "Form1" to "AboutForm"... ) :

Code: Pascal  [Select][+][-]
  1. var
  2.   AboutForm: TAboutForm;
  3.  

Now I am not sure it that's correct.
So I added some code:

Code: Pascal  [Select][+][-]
  1.   AboutForm:= TAboutForm.Create( Self);
  2.   AboutForm.ShowModal;
  3.   AboutForm.Close;
  4.   AboutForm.Free;
  5.  

Is this okay ? ... to free the object / memory ?

The HELP says  "Close does not necessarily destroy the form."

I also found this code, in a tutorial:
Code: Pascal  [Select][+][-]
  1. FreeAndNil(MyForm);


So, what's the best way ? What happens behing the Scenes ?
« Last Edit: January 19, 2019, 01:59:11 pm by PeterX »
usually using latest Lazarus release version with Windows 10

HeavyUser

  • Sr. Member
  • ****
  • Posts: 397
Re: Closing a secondary form
« Reply #1 on: January 19, 2019, 01:21:49 pm »
Hi,

I came across the code of an old program of mine,
opening an ABOUT box, in a method of the main form:

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.Info(Sender: TObject);
  2. begin
  3.   //  ( This form is NOT autocreated on program start )
  4.   AboutForm:= TAboutForm.Create( Self);
  5.   AboutForm.ShowModal;
  6. end;
  7.  

The var AboutForm is the global var being created automatically when doing "File/New Form"
( .. and renaming "Form1" to "AboutForm"... ) :

Code: Pascal  [Select][+][-]
  1. var
  2.   AboutForm: TAboutForm;
  3.  

Now I am not sure it that's correct.
So I added some code:

Code: Pascal  [Select][+][-]
  1.   AboutForm:= TAboutForm.Create( Self);
  2.   AboutForm.ShowModal;
  3.   AboutForm.Close;
  4.   AboutForm.Free;
  5.  

Is this okay ? ... to free the object / memory ?

The HELP says  "Close does not necessarily destroy the form."

close is not needed but otherwise the code is correct. You can also add exception handling to avoid memory leaks in case of exception in which case the code should look like this.
Code: Pascal  [Select][+][-]
  1.   AboutForm:= TAboutForm.Create( Self);
  2.   Try
  3.     AboutForm.ShowModal;
  4.   Finally
  5.     AboutForm.Free;
  6.   end;
  7.  
farther more you can create a simple procedure to handle any kind of modal form along the lines of
Code: Pascal  [Select][+][-]
  1. function DoModal(const aFormClass:TFormClass):Integer;
  2. var
  3.   VForm :TForm;
  4. begin
  5.   vForm:= aFormClass.Create(nil);
  6.   Try
  7.     Result := vForm.ShowModal;
  8.   Finally
  9.     vForm.Free;
  10.   end;
  11. end;
  12.  

you use it like this
Code: Pascal  [Select][+][-]
  1.   DoModal(TAboutForm);
  2.  
« Last Edit: January 19, 2019, 01:24:11 pm by HeavyUser »

PeterX

  • Sr. Member
  • ****
  • Posts: 404
Re: Closing a secondary form
« Reply #2 on: January 19, 2019, 02:03:38 pm »
.. You can also add exception handling to avoid memory leaks in case of exception in which case the code should look like this.
Code: Pascal  [Select][+][-]
  1.   AboutForm:= TAboutForm.Create( Self);
  2.   Try
  3.     AboutForm.ShowModal;
  4.   Finally
  5.     AboutForm.Free;
  6.   end;
  7.  

I like this one, in my case.

Well, I didn't think about catching exceptions, so that's a good hint !

Thanks a lot !
usually using latest Lazarus release version with Windows 10

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Closing a secondary form
« Reply #3 on: January 19, 2019, 02:08:15 pm »
You can avoid having to do AboutBox.Free by adding an OnClose handler to TAboutBox such as:
Code: Pascal  [Select][+][-]
  1. procedure TAbouxBox.FormClose(Sender: TObject; var CloseAction: TCloseAction)
  2. begin
  3.   CloseAction := caFree;
  4. end;
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

furious programming

  • Hero Member
  • *****
  • Posts: 853
Re: Closing a secondary form
« Reply #4 on: January 19, 2019, 07:17:22 pm »
I also found this code, in a tutorial:
Code: Pascal  [Select][+][-]
  1. FreeAndNil(MyForm);

FreeAndNil should only be used when we check elsewhere in the code (for example, in other routine) if the variable is assigned. Otherwise, it is unnecessarily and incorrectly suggested that the variable must be nil.

If the form is created, shown and released in the same routine, I always use the try finally block (as shown by @HeavyUser). Thanks to this, you will not forget to release the form (or other object) and it is a protection against memory leaks.

So if the variable must contain the nil value after the routine, use FreeAndNil. Otherwise, use the Free method.
« Last Edit: March 02, 2019, 04:47:38 pm by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

HeavyUser

  • Sr. Member
  • ****
  • Posts: 397
Re: Closing a secondary form
« Reply #5 on: January 19, 2019, 07:51:25 pm »
.. You can also add exception handling to avoid memory leaks in case of exception in which case the code should look like this.
Code: Pascal  [Select][+][-]
  1.   AboutForm:= TAboutForm.Create( Self);
  2.   Try
  3.     AboutForm.ShowModal;
  4.   Finally
  5.     AboutForm.Free;
  6.   end;
  7.  

I like this one, in my case.

Well, I didn't think about catching exceptions, so that's a good hint !

Thanks a lot !
it is a bit outside my comfort zone but if you're comfortable with it, you are welcome.

PeterX

  • Sr. Member
  • ****
  • Posts: 404
Re: Closing a secondary form
« Reply #6 on: January 20, 2019, 06:11:57 pm »
it is a bit outside my comfort zone but if you're comfortable with it, you are welcome.

Currently this is the only modal form, in this program.
So I'd try to keep it simple.
usually using latest Lazarus release version with Windows 10

PeterX

  • Sr. Member
  • ****
  • Posts: 404
Re: Closing a secondary form
« Reply #7 on: January 20, 2019, 06:18:10 pm »
I also found this code, in a tutorial:
Code: Pascal  [Select][+][-]
  1. FreeAndNil(MyForm);

FreeAndNil should only be used when we check elsewhere in the code (for example, in other routine) if the variable is assigned. Otherwise, it is unnecessarily and incorrectly suggested that the variable must be nil.

To me it looks like "unfinished" to destroy an object (here: a form) but let the pointer remain on it's value.

One could try to access the (now invalid) pointer / memory / object ?

Or does this help here ?
Code: Pascal  [Select][+][-]
  1. if Assigned( MyForm) then ...
usually using latest Lazarus release version with Windows 10

HeavyUser

  • Sr. Member
  • ****
  • Posts: 397
Re: Closing a secondary form
« Reply #8 on: January 20, 2019, 06:23:05 pm »
it is a bit outside my comfort zone but if you're comfortable with it, you are welcome.

Currently this is the only modal form, in this program.
So I'd try to keep it simple.
no, that part is absolutely fine, its a bit silly to try to factor out 3 lines of code, the part I'm not fine with is using a global variable. Given the asynchronous nature of today's operating systems I'm always afraid I'll some how end up creating one instance and freeing an other instance that's created a bit later, creating a bit of a mess. Although that has yet to happen, it makes me uneasy.


 

TinyPortal © 2005-2018