开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜