Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何检查表单是否已关闭?_Delphi_Forms_Vcl - Fatal编程技术网

Delphi 如何检查表单是否已关闭?

Delphi 如何检查表单是否已关闭?,delphi,forms,vcl,Delphi,Forms,Vcl,我看到的唯一方法是为这个添加标志,但这是最好的方法吗 当表格被销毁,我检查(分配(表格2))结果是否为真?为什么? 这样做的方法是什么?哇,过去的爆炸:) Assigned()的工作方式是,它基本上对指针执行nil检查。如果销毁form2,form2仍将指向一个内存地址 我已经有很长一段时间没有做任何Delphi了,但是从内存来看,当form2var被销毁时,您需要手动将它设置为nil。如果您有一个创建和销毁表单的中心位置(例如表单代理?),这应该很容易。如果您使用Form1.Free或Form

我看到的唯一方法是为这个添加标志,但这是最好的方法吗

当表格被销毁,我检查(分配(表格2))结果是否为真?为什么?


这样做的方法是什么?

哇,过去的爆炸:)

Assigned()的工作方式是,它基本上对指针执行nil检查。如果销毁form2,form2仍将指向一个内存地址


我已经有很长一段时间没有做任何Delphi了,但是从内存来看,当form2var被销毁时,您需要手动将它设置为nil。如果您有一个创建和销毁表单的中心位置(例如表单代理?),这应该很容易。

如果您使用
Form1.Free
Form1.destroy
,Delphi将销毁对象,但不会将对象引用设置为零。因此,请改用
FreeAndNil


有关详细信息,请检查Andreas Rejbrand answer in

您可以使用Form1.Showing查看表单是否已关闭


仅关闭表单不会释放它,除非在
OnClose
事件中设置
Action:=caFree
。默认设置为在关闭应用程序时执行某些例程时遇到相同问题。在这种情况下,所有表单都会在后台销毁,但指针不会设置为nil。此代码帮助我:

procedure TMyForm.FormDestroy(Sender: TObject);
begin
  MyForm:=nil;
end;

指针变为nil,我可以用
Assigned
检查它,或者与
nil
进行比较。作为提示,在某些特殊情况下,正确的方法是创建一个计时器,将nil赋值给变量

如果你在自己的代码中创建表单
MyForm:=TMyForm.create
并且你有一个
MyFrom.Close
这很简单,只需添加一个
MyForm:=nil
或者更好的
MyForm.FreeAndNil
。。。但有时参考资料是不存在的

示例:在过程内部,在循环中创建同一表单的许多副本(或仅一个),让表单打开并结束该过程,现在对打开表单的引用不存在,因此不能以正常方式指定nil或执行freeandnil等操作

在这种情况下,诀窍是使用一个计时器(只有一毫秒)来完成,该计时器需要引用,因此您必须存储在全局上,就像对Self的引用一样,所有这些都可以在on close事件上完成

执行free(在任何地方都没有引用)的最简单方法是在主窗体上创建一个TObjectList,这样它将保存所有需要释放的窗体引用,并定义一个计时器(一毫秒),该计时器将通过该列表执行freeandnil;然后在oncose上,将
Self
添加到该列表并启用该计时器

现在,在另一部分中,您有一个在开始时自动创建的普通表单,但是您需要将其设置为nil,并在您自己的代码中重新创建它

这种情况下有一个指向该表单的全局变量,所以您只需要释放和置零它,而不是(我大声说)在自己的表单代码中的任何部分,您必须在表单代码中执行(我说如果大声的话)

有时您需要释放窗体,当用户关闭窗体时,它不会显示在模式中,这种情况很复杂,但同样的技巧也是有效的,在onclose事件中,您启用一个计时器(在该窗体之外,通常在主窗体上),该计时器将释放且为零。计时器间隔可以设置为一毫秒,直到窗体完全关闭后才会运行(请记住不要使用Application.ProcessMessages,这通常是一个非常糟糕的主意)

如果您将Self设置为nil、free或自己表单中的任何内容,则可能会损坏应用程序内存(这样做完全不安全,更不用说它会吃掉ram)

释放表单(及其引用为零)的唯一方法是编写一个触发器,该触发器在表单完全关闭后执行此操作。该表单未显示为模态,是关闭它的用户

我知道如何设置操作来实现自由,但如果将其设置为零,则没有其他安全的方法

必须说明:如果在主窗体上使用计时器,请在Onclose事件中对所有计时器运行
Enabled:=False
。。。否则,可能会发生奇怪的事情(不是所有情况,但有时……关于销毁应用程序和在该计时器上运行代码的竞争条件),当然,如果启用了某个计时器,则可以正确地终止或中止该计时器,等等

你的问题是一件复杂的事情。。。free和nil不是通过代码而是通过用户操作关闭的窗体

对于所有其他方面:想象一下,如果应用程序在同一时间打开了许多表单,并且所有表单都可以在同一时间与用户交互(任何人都是模态的),并且您的代码引用了其中一些表单和其他表单。。。您需要知道f用户已关闭任何表单,以避免从代码中访问该表单。除非您使用计时器,否则这不是一件小事

如果您有一个“中心”窗体(如MDI应用程序),您可以将该计时器放在主MDI窗体上,这样任何关闭的子窗体都可以被释放并为零,诀窍还是在主窗体上设置计时器

只有当你确信你可以释放所有的不可见的形式,你可以有一个定时器在主窗体上,通过所有的表单,如果可见是假的,然后调用FreeAndNil,我认为这种方式容易出错,因为如果你添加一个未来的形式,它不能被释放,而是可以隐藏…此代码将无效

始终记住,如果用户是关闭必须释放的表单的onw且为零,则代码无法检测和执行,不会启动任何事件(在表单完全关闭之后),并且在表单完全关闭之前,您甚至不能尝试释放它或取消其引用,奇怪的事情可能会发生(如果主板有多个插座,则更容易出现这种情况,如果应用程序使用线程等,也更容易出现这种情况)

所以,对于线程化的应用程序(也不是线程化的),我使用了另一种非常有效的方法,不需要定时器,但需要doubl
TMyForm=class(TForm)
...
public
      PleaseFreeAndNilMe:=Boolean;
...
procedure TMyForm.FormCreate(Sender: TObject);
begin
     PleaseFreeAndNilMe:=False;
     ...
end;
procedure TMyForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
     ...
     PleaseFreeAndNilMe:=True;
end;
TForm=class(Froms.TForm)
public
      PleaseFreeAndNilMe:=Boolean;
end;
procedure TForm.FormCreate(Sender:TObject);
begin
     inherited Create(Sender);
     PleaseFreeAndNilMe:=False;
end;
procedure TForm.FormClose(Sender:TObject;var Action:TCloseAction);
begin
     PleaseFreeAndNilMe:=True;
     inherited FormClose(Sender,Action);
end;
function IsNilTheForm(var TheForm: TMyForm);
begin
     if nil=TheForm
     then begin // The form was freed and nil
               IsNilTheForm:=True; // Return value
          end
     else begin // The form refence is not nil, but we do not know is it has been freed or not
               try
                  if TheForm.PleaseFreeAndNilMe
                  then begin // The form is not freed but wants to
                            try
                               TheForm.Free;
                            except
                            end;
                            try
                               TheForm:=Nil;
                            except
                            end;
                            IsNilTheForm:=True; // Return value
                       end
                  else begin // The form is not nil, not freed and do not want to be freed
                            IsNilTheForm:=False; // Return value
                       end; 
               except // The form was freed but not set to nil
                    TheForm:=Nil; // Set it to nil since it had beed freed
                    IsNilTheForm:=True; // Return value
               end;
          end;         
end;