德尔福 – 从外部关闭模态形式并打开一个新的模态形式
发布时间:2020-12-15 09:23:28 所属栏目:大数据 来源:网络整理
导读:在我的主要表单中,我有一个按钮,打开一个模态Form2(可能会打开其他模态形式).在打开Form2之前我正在设置一个计时器,它将以编程方式关闭所有活动的模态表单(Form2.Close)并打开一个新的模态Form3. 问题是当Form3以模态方式打开时,Form2保持(可见)并且只有当我
在我的主要表单中,我有一个按钮,打开一个模态Form2(可能会打开其他模态形式).在打开Form2之前我正在设置一个计时器,它将以编程方式关闭所有活动的模态表单(Form2.Close)并打开一个新的模态Form3.
问题是当Form3以模态方式打开时,Form2保持(可见)并且只有当我通过单击X关闭Form3时才会关闭Form2. 要重现向项目添加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是一个阻止调用来显示表单.如果您只显示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; 注意上面简单地说明了这个概念.您需要根据您的最终目标设计更强大的方法. 但是,我建议过度使用模态表单通常被认为在用户体验方面不友好. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |