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

Ric*_*olf 4 delphi delphi-7

基本上,我正在使用一个TTimer事件来关闭所有打开的表单并将用户带回主表单.我可以迭代Screen.Forms:

for i := 0 to Screen.Formcount - 1 do
  Screen.Forms[i].close;
Run Code Online (Sandbox Code Playgroud)

问题是OnCloseQuery某些形式的事件 - 它们弹出MessageDlg中断这个过程:(

Ser*_*yuz 7

在询问用户是否继续之前,您可以在主表单中使用其他表单将检查的标记.像这样的东西:

单元1

type
  TForm1 = class(TForm)
    ..
  public
    UnconditinalClose: Boolean;
  end;

..

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  UnconditinalClose := True;
end;
Run Code Online (Sandbox Code Playgroud)

单元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;
Run Code Online (Sandbox Code Playgroud)


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

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;
Run Code Online (Sandbox Code Playgroud)

  • 即使表单没有被释放,第二个建议,即分离事件处理程序,也是可行的.您只需在调用"Close"后重新附加事件处理程序.即使关闭动作是"caFree",这也是安全的,因为表单实际上不会立即释放.在程序到达处理`cm_Release`消息之前它不会被释放,并且我们已经知道程序没有这样做,因为`Screen.FormCount`在循环期间没有改变. (2认同)