Delphi表单所有者跳过组件中的ShowMessage/Dialog调用';s FormClose

Delphi表单所有者跳过组件中的ShowMessage/Dialog调用';s FormClose,delphi,delphi-2010,Delphi,Delphi 2010,我的Delphi2010应用程序有许多由mainform创建和拥有的非模式表单。其中一个表单有一个formclose过程,它会弹出一个对话框,询问用户是否要保存更改。如果用户关闭mainform,则会调用“owned”窗体的FormClose过程,但不会显示对话框,用户没有机会保存 有什么建议吗?我可以看到该过程正在调试器中被调用,但它似乎只是跳过了对话框。showmessage也会发生同样的情况。所有者窗体是否以某种方式覆盖了这些对话框的实际显示 谢谢 Rusty这种事情应该出现在OnClos

我的Delphi2010应用程序有许多由mainform创建和拥有的非模式表单。其中一个表单有一个formclose过程,它会弹出一个对话框,询问用户是否要保存更改。如果用户关闭mainform,则会调用“owned”窗体的FormClose过程,但不会显示对话框,用户没有机会保存

有什么建议吗?我可以看到该过程正在调试器中被调用,但它似乎只是跳过了对话框。showmessage也会发生同样的情况。所有者窗体是否以某种方式覆盖了这些对话框的实际显示

谢谢


Rusty

这种事情应该出现在OnCloseQuery事件中。在处理程序中将CanClose设置为false以中止关闭(这或多或少是标准的:在这些情况下,Yes、No和Cancel是通常的答案,Cancel中止关闭过程)。

当主窗体关闭时,应用程序终止,从而释放主窗体,从而释放它所拥有的窗体。拥有的表单不是关闭的,而是释放的,因此它们的
OnClose
事件通常根本不会触发

如果看到从所属表单的
OnClose
事件调用
ShowMessage
,但对话框没有显示,可能是因为应用程序已终止,不再处理消息。这意味着拥有的表单的
OnClose
事件是由您自己的代码中的某个地方触发的,但为时已晚

重现此行为的一种方法是从主窗体的
OnClose
事件将
WM_CLOSE
消息发布到所属窗体。然后,当应用程序已经终止时,拥有的表单将处理该消息。任何调用ShowMessage的尝试或任何模式表单都不再有效

我同意Michael的观点,
OnCloseQuery
更适合向用户显示提示。不幸的是,这本身并没有帮助,因为所拥有的表单正在被释放而不是关闭。您必须手动调用他们的
OnCloseQuery
事件,例如:

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;

我最近遇到了类似的事情。我发现只需添加代码:

if not Visible then
  Show;
BringToFront;

在显示“保存更改”对话框之前结束所有混淆。如果父窗体不可见,则会显示它,并以zorder的形式向上移动到堆的前面,然后在上面显示对话框。

谢谢,这似乎很有效。以前我使用的是FormClose过程,但相应地更改了“Action”(TCloseAction)参数。显然,这并不总是有效的,否则我不知道如何正确使用它!您的代码中肯定还有其他内容,因为只需关闭主窗体,就不会自动为拥有的窗体调用OnClose或OnCloseQuery。正确-在mainform.formclose过程中,我明确地说是OwnedForm.Close以触发其formclose。。。更具体地说,我会这样做:对于i:=0到ComponentCount-1,如果Components[i]是TForm,那么我会这样做(Components[i]是TForm);这基本上就是我首先要做的,以使ownedform.formclose成为触发器。我猜如果从FormCloseQuery而不是FormClose调用,应用程序将允许消息。当您关闭任何表单时,首先调用其OnCloseQuery,然后(如果OnCloseQuery允许关闭)OnClose,然后(如果它是主表单且OnClose返回caNone以外的任何内容)终止应用程序(请参阅TCustomForm.Close)。无论您使用的是主窗体的OnCloseQuery还是OnClose,应用程序此时仍应处理消息。您的代码中一定有其他内容;在应用程序终止后,您可以使用其他事件或其他技术关闭所拥有的表单。