Delphi form Owner Skips ShowMessage/Dialog call in component's FormClose
My Delphi 2010 application has a number of non-开发者_运维知识库modal forms that are created and owned by the mainform. One of these forms has a formclose procedure that pops up a dialog asking the user if they want to save changes. If the user closes the mainform, the "owned" form's FormClose procedure is called, however the dialog is not shown, and the user has no chance to save.
Any suggestions? I can see the procedure is being called in the debugger, but it seems to just skip the dialog. Same thing happens with a showmessage. Does the owner form somehow override the actual showing of these dialogs?
Thanks
Rusty
That kind of thing should go in the OnCloseQuery event. Set CanClose to false in the handler to abort the closing (which is more or less standard: in these situations, Yes, No and Cancel are the usual answers, with Cancel aborting the closing process).
When the main form is closed then the application terminates which frees the main form which in turn frees the forms owned by it. The owned forms are not closed, just freed, therefore their OnClose
event is normally not triggered at all.
If you see ShowMessage
being called from the owned form's OnClose
event but the dialog doesn't show up it's probably because the application is already terminated and no longer processing messages. This means that the owned form's OnClose
event is triggered by somewhere in your own code but too late.
One way to reproduce this behaviour is to post WM_CLOSE
message to the owned form from the main form's OnClose
event. The message is then processed by the owned form at a later moment when the application is already terminated any attempt to call ShowMessage or any modal form has no effect anymore.
I agree with Michael that OnCloseQuery
is better suited for the purpose of displaying a prompt to the user. Unfortunately this alone doesn't help since the owned forms are being freed not closed. You have to call their OnCloseQuery
event manually, for example:
procedure TFormMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
I: Integer;
begin
CanClose := False;
for I := 0 to ComponentCount - 1 do
if Components[I] is TCustomForm then
if not TCustomForm(Components[I]).CloseQuery then
Exit;
CanClose := True; // or another check if the main form can be closed, too
end;
I recently ran into something along these lines. I found that simply adding the code:
if not Visible then
Show;
BringToFront;
right before the save changes dialog is displayed ends all confusion. The parent form is displayed if its not visible, and brought upward in zorder to the front of the pile, then on top of that is displayed the dialog.
精彩评论