As a hint, the right way to do this in some special cases is to create a timer that assigns zero to the variable.
I will explain this (somehow complicated) if you create your form inside your own code MyForm:=TMyForm.Create and you have MyFrom.Close , it is very simple, just add MyForm:=nil or it is also better MyForm.FreeAndNil ... but sometimes the link is no problem.
Sample: you create inside a procedure, in a cycle there are many copies of the same form (or only one), let the form open and end this procedure, now the link to the open form does not exist anywhere, so you can not assign nil or do freeandnil, etc. .d. in the usual way.
In this case, the trick is to use a timer (just one millisecond), which does this, this timer needs a link, so you should store at the global level, as a link to Self, everything that can be done on closing the event.
The easiest way to make free (when there is no link anywhere) is to create a TObjectList in the main form, so it will store all the links to the forms that should be free, and define a timer (one millisecond) that will go through this list, doing freeandnil; then in onlcose you add Self to this list and enable this timer.
Now in the other part, you have a normal form that is automatically created at startup, but you need to set it to zero and recreate it on your own code.
In this case, the global dot points to this form, so you only need to free it, but NOT, but NOT (I say it loudly) on any part inside the form’s own code, you must do this OUT (I say if loudly) the form code .
Several times you will need to free the form when the user closes it and it is not shown in modal mode, this case is complicated, but again the same trick is valid, in the onclose event you turn on the timer (i.e. from this form, as a rule, on the main form), and the timer will be free and equal to zero. This timer interval can be set as one millisecond, it will not work until the form is completely closed (please remember that do not use Application.ProcessMessages, this is usually a very bad idea).
If you install Self on nil, free or something else inside your own form, you can damage the memory of your application (this is absolutely unsafe, not to mention that it can eat a ram).
The only way to free the form (and nil its link), a form that is not shown as modal and is the user who closes it, is to program a trigger that does this after the form is completely closed.
I know about setting up an action to make it free, but to set it to zero, there is no other safe way.
I must say: if you use timers in your main form, run Enabled:=False on all of them in the Onclose event ... otherwise strange things may happen (not always, but sometimes ... race conditions for destroying the application and executable code on these timers), and couse, if someone was turned on, they act correctly to finish it correctly or to interrupt it, etc.
Your question is one of the most difficult tasks ... free and nil form, closed not by code, but by user action.
For everyone else: think that if the application opens many forms at the same time, and everyone can interact with the user at the same time (someone is modal), and you have code that refers to some of them: others ... you need to know what user f closed any form in order to avoid access to this form from code. It is not so simple if you do not use timers.
If you have a “central” form (for example, an MDI application), you can put this timer in the main MDI form, so any child form that is closed can be freed and equal to zero, the trick is again a timer on this main form.
Only if you are sure that you can free all non-innocent forms, but you can have a timer in the main form passing through all the forms, and if Visible is false, then call FreeAndNil, I believe that these are errors, since if you add to the future a form that should not be released, but may remain hidden ... this code will be invalid.
Everyone remembers that if the user is onw, which closes the form, which must be freed and equal to zero, there is no way for the code to detect and act, no events are triggered (after the form is completely closed) and before the form is completely closed, you don’t even have to try to free it, or not its links, strange things may occur (more prone to this if the motherboard has more than one socket, and also more if your application uses streams, etc.).
So, for streaming applications (and also not for streaming) I use another method that works fine and does not need timers, but for every ThatForm.* Check, a double check is required, the trick is to define a public variable Form bolean, for example, like PleaseFreeAndNilMe in the public section of the form, then in onclose (like the last line) set the value to True and OnCreate set it to False.
This way, you will know if this form was closed or just hidden (to hide the form, never call it close, just call hide).
This will look like an encoding (you can use this as a warper, instead of defining forms, since TForm defines them as TMyform, and it is also better to use a hack, for example type TForm=class(Forms.TForm) instead of TMyForm=class(TForm) , to add this variable for all forms):
TMyForm=class(TForm) ... public PleaseFreeAndNilMe:=Boolean; ... procedure TMyForm.FormCreate(Sender: TObject); begin PleaseFreeAndNilMe:=False; ... end; procedure TMyForm.FormClose(Sender: TObject; var Action: TCloseAction); begin ... PleaseFreeAndNilMe:=True; end;
If you prefer a hacked version:
TForm=class(Froms.TForm) public PleaseFreeAndNilMe:=Boolean; end; procedure TForm.FormCreate(Sender:TObject); begin inherited Create(Sender); PleaseFreeAndNilMe:=False; end; procedure TForm.FormClose(Sender:TObject;var Action:TCloseAction); begin PleaseFreeAndNilMe:=True; inherited FormClose(Sender,Action); end;
But, as I said, before accessing any member (or just where you compare null) just call the "global" passign reference function (whether it was null or not), encoded as:
function IsNilTheForm(var TheForm: TMyForm); begin if nil=TheForm then begin // The form was freed and nil IsNilTheForm:=True; // Return value end else begin // The form refence is not nil, but we do not know is it has been freed or not try if TheForm.PleaseFreeAndNilMe then begin // The form is not freed but wants to try TheForm.Free; except end; try TheForm:=Nil; except end; IsNilTheForm:=True; // Return value end else begin // The form is not nil, not freed and do not want to be freed IsNilTheForm:=False; // Return value end; except // The form was freed but not set to nil TheForm:=Nil; // Set it to nil since it had beed freed IsNilTheForm:=True; // Return value end; end; end;
So where do you do if nil=MyForm then ... , now you can do if (IsNilTheForm(MyForm)) then ...
That's all.
A better timer solution is because the form is freed as quickly as possible (ram is used less), PleaseFreeAndNilMe trick the form is not freed until IsNilTheForm is called (unless you free it where else).
This IsNilTheForm so complex that it examines all the states (for a multi-platform motherboard and streaming applications) and allows the code to be free / nil elsewhere.
Of course, this function should be called in the main thread and in atomic exception.
Free form and its nil pointer is not a trivial thing, most when the user can close it at any time (since no code from the form is running).
The big problem: when the user closes the form, there is no way to get an event handler that is called from this form, and after the form finishes everything that it does.
Now show that the encoder has supplied a lot of Application.ProcessMessages; every time the application, as well as on this form, etc .... and did not care about the racing conditions ... try to free and fill out such a form after the user asks to close it ... this is a nightmare, but can be solved with a hacked version of TForm, which has a variable that reports that the form has not been freed, but wants it.
Now imagine that you are using hacked TForm and want a normal TForm, just define it as ...= class(Forms.TForm) , so it will now have this extra variable. so the call to IsNilTheForm will act as compared to nil.
We hope that this will help VCL codes fix things like raising an event when an object is destroyed, freed, hidden, hidden, etc. from the code of this object, for example, in the main form, etc. Does it make life easier ... or just fix it ... Close and Free involves setting Nil to all refractions pointing to it.
There is one more thing that can be done (but I try to avoid it): to have several variables that point to the same form (not a copy) that is prone to many errors, you are free one, and you need all of them were nil etc. The code I will show is also compatible with this.
I know that the code compiles ... but the Free and Nil form is more complex than my code.