DELPHI. 如何在调用另一个模态窗口后关闭当前模态窗口?

3

在MDI应用程序中,有一个打开的模态窗体A。从窗体A中以模态方式显示了窗体B。 如何在调用模态窗体B后立即关闭模态窗体A?


你可以尝试调用FormA.Hide; 它会隐藏窗体,但不会关闭,就好像FormB是FormA的子窗体一样,我认为你不能关闭父窗体。 - AirWolf
也许在这里使用向导比使用孤立但顺序的模态表单更好? - Arioch 'The
你不能这样做 - 模态窗体的整个意义在于用户必须在继续之前完成它(即提供ModalResult)。如果你发现自己不得不玩一些技巧来使它表现不同,那么我建议你需要重新审视你的设计。 - Hugh Jones
@Hugh:问题通常不是用户是否完成了第一个模态表单,而是第一个表单中的逻辑需要控制显示下一个模态表单的顺序。虽然有许多方法来控制它,但往往要求在应用程序结构定义之后才会出现,并且没有能力重新审视结构决策…直到下一个主要版本等。 - Mark Wilsdorf
@Mark - 当然没问题。我回答这个问题是基于提问者另一个问题的背景,我认为那个问题显示出我们处于设计的早期阶段。 - Hugh Jones
4个回答

7

模态意味着终身嵌套。当一个模态表单打开另一个模态表单时,第一个表单需要在第二个模态表单的整个生命周期内保留。

因此,您需要在显示第二个模态表单之前 关闭 第一个模态表单。由于从第一个模态表单内部执行此操作有些棘手,因此最好向主表单请求帮助。主表单可以:

  1. 对第一个模态表单调用 Free
  2. 创建并显示第二个模态表单。

如果第一个模态表单需要从其自己的事件处理程序触发此操作,则向主表单排队消息是向前迈出的最佳方法。例如使用 PostMessage 或者 TThread.Queue


在第一个模态窗体中,PostMessage(Self.Handle,wm_close,0,0)仅在第二个模态窗体关闭后才会关闭第一个模态窗体;请将翻译文本返回。 - Avrob
@Arioch'The 这取决于您是否正确获取了表单的生命周期! - David Heffernan
如果表单是自动创建的,并且直到应用程序退出才被释放,只显示和隐藏 - 这有什么问题吗? - Arioch 'The
嗯,在这种特定的工作流程中,XE5 ShowModal 的 CPS 风格重载可能会更好地发挥作用 :-D - Arioch 'The
当我使用Hide命令来隐藏第一个模态窗体时,当第二个模态窗体关闭后,应用程序停止响应键盘和鼠标,因为有一个打开的模态窗体。 - Avrob
显示剩余6条评论

3

将以模态显示的窗体的ModalResult属性设置为非mrNone值将导致该窗体被关闭。

procedure TFormA.Button1Click(Sender: TObject);
begin
  ShowFormBModal;
  ModalResult := mrCancel; // this will close Form A if it's being shown modally
end;

根据您的需求,ModalResult 的实际值可能取决于表单 B 的模态结果或其他条件。


问题的措辞很糟糕,但在 Dvid 的答案下面的讨论表明他是正确的:原始提问者并不需要在两个表格都显示后将 A 和 B 关闭在一起,他想要当用户使用 B 时 A 被关闭。 - Arioch 'The
@Arioch'The 我认为问题很清楚,答案也很明确。 - Ondrej Kelle
任何涉及“调用表单”的编程内容都不能过于死板,因此不可能清晰明了 :-) - Arioch 'The
@AlexSC 模态显示表单 B。 - Ondrej Kelle
这个关闭窗体A的解决方案会等待窗体B关闭。我认为OP想立即关闭窗体A。 - NGLN
显示剩余6条评论

1

在显示模态FormB之前,我会隐藏FormA。然后根据FormB的ModalResult来显示或关闭FormA。

Hide; 
FormB.ShowModal; 
if FormB.ModalResult <> mrOK then Close; 

ModalResult = mrOK 表示 Formb 已经打开了一个 MDIchild 窗体并已关闭。


0
在关闭第一个模态窗体之前,我会向应用程序的主窗体(或其他窗体)发布自定义消息,从而导致它显示第二个模态窗体。我更喜欢两个窗体的“所有者”控制这个想法。
PostMessage(Application.Mainform.Handle, DO_OPEN_2ND_MODALFORM, 0, 0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接