Thank you very much
wp for your explanations and examples and the demo. Again I learned some more things I did not know before or could only assume, but was not sure.
Option (b) has the risk that the user closes the form by means of the "x" button in the corner. In this case your explicit call to Form.Free is not executed. The form, by default, is only hidden (CloseAction = caHide by default; see below), and you have the memory leak mentioned in my previous post. (Note that this memory leak is not detected by HeapTrc because the closed form still exists in the Application.Components and thus is destroyed by the application at the end).
Therefore you should provide an OnClose handler which sets CloseAction to caFree.
This is very important to know. Meanwhile I found, that
some of my non modal Forms do have an Event handler for 'OnClose', which sets 'CloseAction:=caFree', but not all. I will change that.
But now you have the problem that the variable which refers to the destroyed form is not set to nil.
When I created my first non modal Forms, I had the same problem: I needed some kind of variable to know, whether a non modal Form currently is opened or not. Because if e.g. the user presses a button to open the Form, although it is already open, it would be wrong to create it again. Instead self.BringToFront should be called.
- I found no solution by using a boolean property inside the Form, because this is lost, after the Form is free'd.
- And I did not manage this by setting the Form variable itself to 'nil' after closing it. Because it is possible to close a Form by the "X" in the upper right corner, it would have been done in the OnDestroy Event handler, but a 'self:=nil' does not work there.
My solution was to use 1 separate exclusive global boolean variable for each non modal Form and to reset it in the OnClose Event handler. Works of course only, if this Class has never more than 1 instance at the same time.
For those Form classes, where more than 1 instance at the same time are needed, I added a pointer to an exclusive global boolean variable to the class properties and in the OnClose Event handler this pointer is used to set this global variable to False.
I didn't expect to win a price for maximum elegance, but this works now for many years.
Therefore, I would not implement the OnClose handler of TSettingsForm as a method of TSettingsForm itself, but as a method of TMainForm which knows about the name of the instance:
This is an interesting approach. However I use a couple of non modal Forms in and out of
common units (which can be used by many programs), which have no access to a MainForm. For them I will stay with my 'old' solution.
I already had an event handler TForm1.FormClose(). Inside I did never change var 'CloseAction'. I printed it and it contains 'caFree'.
This is strange. Look at the sources of TCustomForm.Close: CloseAction is caFree only for the MainForm.
Form1 is here the 'MainForm', as far as I understand, because it is created in the main source file via 'Application.CreateForm(TForm1, Form1)'.
Hello
alpine and
440bx,
because I know, how much I don't know, especially about free'ing classes or Forms, I want to dig some more time...
But of course it can't be bad to do a memory test as you described: I will create a large zip or 7zip archive with >= 600 MB and then verify this archive by the zip or 7zip program >= 6 times.