I have a MDI main (parent) form and a MDI child form. I create the child at runtime like this:
VAR
FrmDereplic: TFrmDereplic;
procedure TMainFrm.Button2Click(Sender: TObject);
begin
FrmDereplic:= TFrmDereplic.Create(MainFrm);
FrmDereplic.Show;
end;
Steps to reproduce the error:
I start the app, I press the button to create the child, I press the 'x' button on main (parent) form to close the application and I get an "Cannot create form. No MDI forms are currently active" error.
The line on which the error appears is in the child form:
procedure TFrmDereplic.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
end;
procedure TFrmDereplic.FormDestroy(Sender: TObject);
VAR MyIniFile: TCubicIniFile;
begin
MyIniFile:= TCubicIniFile.Create(AppINIFile);
TRY
with MyIniFile DO
begin
if WindowState<> wsMaximized then
begin
// save form's screen pos
...
end;
WriteInteger ('Dereplicator', 'fltExtensions', fltExtensions.ItemIndex); <----- HERE
FINALLY
FreeAndNil(MyIniFile);
END;
end;
I save lots of form's properties (and other's controls properties) to the INI file. But it only fails when I try to save fltExtensions.ItemIndex (which is a TFilterComboBox). If I comment that line it works perfectly.
Any idea why it tries to create a form when I actually closed the application?????????
I look on some web sites and just found the problem. It looks like it is preferably to have the Owner set to Application, instead of the main form. Remy Lebeau suggests that the real problem is in the OnDestroy of the the child form. There is no valid handle to the window that holds the filter then the OnDestroy is called. So, changing the destruction order gives a chance to TFrmDereplic.OnDestroy to execute properly.
So, here is the solution:
SOLUTION(S)
FrmDereplic:= TFrmDereplic.Create(Application);
or
Do not save form's properties in OnDestroy
The second one requires few extra lines of code as the OnClose even is not always called. This was extracted from Delphi HELP:
Note: When the application shuts down, the main form receives an OnClose event, but any child forms do not receive the OnClose event.
If you use Application.Terminate, then onCloseQuery and onClose will not be called. Same for Halt (but... this is way too extreme, right?).
The error occurs when reading the fltExtensions.ItemIndex
property because it requires fltExtensions
to have an HWND, which requires its parent TFrmDereplic form to have a HWND, which requires the project's MainForm to have an HWND. But the app is in a state of shutdown, and the MainForm cannot allocate its HWND anymore, so TFrmDereplic raises an exception when it cannot obtain an HWND for itself.
Saving your INI data in the form's OnDestroy
event is too late. You need to the OnClose
event instead.
If the code you provided in your question is the real one then I guess the error is in this line:
FrmDereplic:= TFrmDereplic.Create(TMainFrm);
I never tried this and I am not sure if the compiler really buys it (can't test it now), but you are trying to set a class as owner of the MDI child form. Instead of that you should do either
FrmDereplic:= TFrmDereplic.Create(Application);
or
FrmDereplic:= TFrmDereplic.Create(self);
The first option sets the application as owner of the MDI child form, while the second one sets the instance of the MDI main form as owner.
Hope that helps. :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With