Delphi:关闭所有表单(MainForm除外),但忽略任何OnCloseQuery对话框

Delphi:关闭所有表单(MainForm除外),但忽略任何OnCloseQuery对话框,delphi,delphi-7,Delphi,Delphi 7,基本上,我使用TTimer事件关闭所有打开的表单,并将用户带回主表单。 我可以反复浏览屏幕。表单: for i := 0 to Screen.Formcount - 1 do Screen.Forms[i].close; 问题在于其中一些表单上的OnCloseQuery事件-它们会弹出MessageDlg,从而中断此过程:(您可以在主表单中使用一个标志,其他表单会在询问用户是否继续之前检查该标志。类似如下: 第一单元 第二单元: implementation uses unit1;

基本上,我使用
TTimer
事件关闭所有打开的表单,并将用户带回主表单。 我可以反复浏览
屏幕。表单

for i := 0 to Screen.Formcount - 1 do
  Screen.Forms[i].close;

问题在于其中一些表单上的
OnCloseQuery
事件-它们会弹出
MessageDlg
,从而中断此过程:(

您可以在主表单中使用一个标志,其他表单会在询问用户是否继续之前检查该标志。类似如下:

第一单元

第二单元:

implementation

uses
  unit1;

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := unit1.Form1.UnconditinalClose;
  if not CanClose then
    // ask the user if he/she's sure he/she wants to close
end;

另一种解决方案可能是分离其他表单的
OnCloseQuery
事件处理程序。这只有在关闭时释放(释放)这些其他表单,而不是隐藏(编辑以反映Rob的评论)时才可行:

程序TForm1.Timer1Timer(发送方:TObject);
变量
i:整数;
SaveHandler:TCloseQueryEvent;
开始
对于i:=0到Screen.Formcount-1 do
如果Screen.Forms[i]Self,则开始
SaveHandler:=Screen.Forms[i].OnCloseQuery;
Screen.Forms[i].OnCloseQuery:=nil;
Screen.Forms[i].关闭;
Screen.Forms[i].OnCloseQuery:=SaveHandler;
结束;
结束;

用1而不是0初始化值i。

我试图避免对所有表单的“OnCloseQuery”事件进行“黑客攻击”。此外,当弹出MessageDlg时,这可以算作“新”表单,而不在“close”中循环之前,因此必须手动关闭。如果他们出于某种原因中断流程,则不应关闭。如果他们没有理由不关闭,则不应中断流程(不应设置“CanClose”)。OnCloseQuery事件通常包含以下消息:“是否确实要取消此活动?“是/否--我甚至不想给他们这样的选择--我想关闭,而不使用OnCloseQuery。因此,你在问用户是否有不关闭的理由。我只想确保有一个视觉迹象表明存在活动,其余的留给用户。但可能只有我。看起来你需要重构你的应用程序。“紧密处理逻辑"可以被委托到一个地方,那里有它所需要的所有信息。比全局布尔黑客好得多。这是一个有用的、实用的答案,谢谢,但它确实需要我检查每个表单的每一个OnCloseQuery事件——这是我想要避免的。我不能以OnCl从来没有使用过oseQuery事件?Re:您的替代解决方案:看起来不错!…有趣的是,我在回复您后几乎想到了它,并且我已经处理这个问题大约5个小时了!这就是为什么“成对编程”工作:人们在与他人互动时会思考得更好。让我试试看,然后再回复你,这可能正是我目前所需要的,工作得很好,谢谢!!!就像你说的,表单必须在之后释放,并且这个应用程序已经如此编写,所以它应该工作得很好。基于我的谷歌搜索,我相信这个解决方案也会很好对未来的其他人很重要。再次感谢:D@Richard-不客气!我希望我没有冒犯您质疑您的设计。:)第二个建议,分离事件处理程序,即使在表单未被释放的情况下也是可行的。调用
Close
后,只需重新连接事件处理程序。即使关闭操作是
caFree
,这也是安全的,因为表单实际上不会立即被释放。在程序开始处理
cm\u Release
消息之前,它不会被释放,我们已经知道程序不会这样做,因为
Screen.FormCount
在循环过程中不会改变。请详细说明您的答案好吗?特别解释为什么以1开头。@UwePlonus我想这将关闭除主窗体(Screen.forms[0])之外的所有窗体。如果关闭man窗体,程序将终止,这不是您想要的。另一方面,这并不能回答问题,因为它仍然调用OnCloseQuery事件。第一个窗口是主窗体,值索引是0,第二个窗体是1,第三个窗体是2。。。
implementation

uses
  unit1;

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := unit1.Form1.UnconditinalClose;
  if not CanClose then
    // ask the user if he/she's sure he/she wants to close
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
  i: Integer;
  SaveHandler: TCloseQueryEvent;
begin
  for i := 0 to Screen.Formcount - 1 do
    if Screen.Forms[i] <> Self then begin
      SaveHandler := Screen.Forms[i].OnCloseQuery;
      Screen.Forms[i].OnCloseQuery := nil;
      Screen.Forms[i].Close;
      Screen.Forms[i].OnCloseQuery := SaveHandler;
    end;
end;
for i := 1 to Screen.Formcount - 1 do
  Screen.Forms[i].close;