gpt4 book ai didi

delphi - 从外部关闭模态表单并打开新的模态表单

转载 作者:行者123 更新时间:2023-12-03 15:26:40 27 4
gpt4 key购买 nike

在我的主表单中,我有一个按钮可以打开模态 Form2 (可以打开其他模态表单)。在打开 Form2 之前,我设置一个计时器,它将以编程方式关闭所有事件模式表单 (Form2.Close) 并打开一个新的模式 Form3 .

问题是,当 Form3 以模态方式打开时,Form2 仍然存在(可见),并且仅当我通过单击 关闭 Form3 时XForm2 关闭。

要重现将 3 个表单添加到项目中,请添加一个 TButton,并在 Form1(主表单)上放置一个 TTimer:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
public
end;

var
Form1: TForm1;

implementation

uses Unit2, Unit3;

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled := True;
with TForm2.Create(Application) do
try
ShowModal;
finally
Free;
end;
end;

procedure CloseActiveModalForms;
var
I: Integer;
F: TCustomForm;
L: TList; // list of modal forms
begin
L := TList.Create;
try
for I := 0 to Screen.CustomFormCount - 1 do
begin
F := Screen.CustomForms[I];
if (fsModal in F.FormState) then
L.Add(F);
end;
for I := 0 to L.Count - 1 do
TCustomForm(L.Items[I]).Close; // this sets ModalResult := mrCancel
finally
L.Free;
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
CloseActiveModalForms; // this should close TForm2 but it does not.

with TForm3.Create(Application) do // create new Modal TForm3
try
ShowModal;
finally
Free;
end;
end;

end.

为什么Form2没有关闭?为什么在我调用 CloseActiveModalForms 后,Form2 模态循环没有退出?

最佳答案

您的调用堆栈如下所示:

1 Form1.Button1Click
2 Form2.ShowModal //Local message processing loop until form closes
3 Form1.Timer1Timer //Here you attempt to close the form
//but it doesn't actually until ShowModal exits
4 Form3.ShowModal // Another message loop that doesn't return until form closes

所以基本上,在 Form3 关闭之前,您无法完成 Form2 的关闭。请注意,ShowModal 是显示表单的阻塞调用。如果您只是 Show Form3(即不是 ShowModal),则调用不会阻塞,并且您将看到 Form2 能够在调用堆栈展开时关闭。

<小时/>

您应该能够通过将显示 Form3 的调用延迟到 Form2 关闭之后来解决此问题。 OnFormDestroyEvent 应该足够了(不幸的是我无法测试它)。

procedure TForm1.ShowForm3(Sender: TObject);
var
LForm: TForm;
begin
LForm := TForm3.Create(Application); //as you created it, but nil owner should suffice
try
LForm.ShowModal;
finally
LForm.Free;
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
//You will need to figure out how you reference the Form2 instance.
Form2.OnFormDestroy := ShowForm3;
CloseActiveModalForms;
//Form2 will close after you backtrack up the call-stack.
//When it's destroyed, your event handler will create and show a TForm3 instance.
end;
<小时/>

请注意,上面只是演示了这个概念。您需要根据您的最终目标设计一种更强大的方法。

但是,我建议过度使用模态表单通常被认为对用户体验不友好。

关于delphi - 从外部关闭模态表单并打开新的模态表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40630931/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com