【问题标题】:Is the form already open?表格是否已经打开?
【发布时间】:2012-08-13 23:29:55
【问题描述】:

我一直在使用下面的代码来检查一个表单是否已经存在:

function FormExists(apForm: TObject): boolean;
var i: Word;
begin
  Result := False;
  for i := 0 to Application.ComponentCount-1 do
    if Application.Components[i] = apForm then begin
      Result := True;
      Break;
    end;
end;

几年前我从我参与的一个项目中得到它。这是我的第一个 Delphi 项目之一。

有效。

但是这周我想知道是否有更好、更快的方法来做到这一点。

【问题讨论】:

  • 这个函数有没有返回过假?如果是在什么条件下?询问是因为不清楚“存在”是什么意思。
  • 是的。如果没有创建表单。
  • 好吧,正如你在评论中已经提到的,只是测试分配。
  • @Sertac,但如果您不使用FreeAndNil,可以分配表单变量但可以破坏窗口。它还必须具有其存在的有效句柄。
  • @TLama - 我想我明白了。但我不会在悬空指针上测试窗口句柄。我自己将 nil 分配给 OnDestroy 中的全局变量。

标签: delphi


【解决方案1】:

您可以改用Screen.Forms。它减少了您正在迭代的项目:

function FormExists(apForm: TForm): boolean;
var 
  i: Word;
begin
  Result := False;
  for i := 0 to Screen.FormCount - 1 do
    if Screen.Forms[i] = apForm then 
    begin
      Result := True;
      Break;
    end;
end;

但是,值得注意的是,如果您已经拥有apForm,您就知道它存在,无需搜索它。

【讨论】:

  • 但就是这样。在某些情况下我不知道。其余的我使用“已分配”。
  • @Jlouro,然后简单地nilSertac said 这样的全局表单变量来使用Assigned 测试或使用这种迭代。请求已释放控件变量的有效句柄是不安全的。
【解决方案2】:

我发现最好的方法是询问表单本身是否打开。您可以使用 CLASS 过程/函数来执行此操作。调用表单的类过程/函数是安全的,即使它不存在。

在表单的公共声明中添加一个类函数。

  type
    TForm2 = class(TForm)
      ...
    private
      { Private declarations }
      ...
    public
      { Public declarations }
      class function FormExists:  Boolean;
    end;

  class function TForm2.FormExists: Boolean;
  var
     F: TForm2;
     I: Integer;
  begin
     F := nil;
     for i := Screen.FormCount - 1 DownTo 0 do
      if (Screen.Forms[i].Name = 'Form2') then
      begin
         F := Screen.Forms[I] As TForm2;
         break;
      end;
     Result :=  F <> nil;
  end;

所以在uses子句中有Form2的任何单元都可以调用

     if Form2.FormExists then
        ...

【讨论】:

  • -1。这是完全错误的解决方案。它将您的代码与特定的表单名称联系起来。你从不测试Name;它使一切都过于具体,并使您的代码无法在其他地方重用。
  • 除了Ken的评论,你不需要FF &lt;&gt; nil,你已经有了一个布尔值; Result。在开始时将 Result 设置为 False,在 'for' 循环中的 'if' 测试中,将 Result 设置为 True 并中断。
  • @KenWhite 它直接面向对象的方法。表单对象可以告诉您它是否打开。在您的方法中,您需要了解并提供有关相关表单的数据。我使用的这种方法的另一个好处是,如果 F 不是 nil,它是对表单本身的引用,您可以检查表单组件的状态。我使用它来了解我正在处理的文档是否已被修改,如果是,我将表单向前推进,并为用户提供保存选项。你的方法很难完成。
  • 硬编码对'Name = 'Form2'`的引用就像在你身体的私密部位纹身你第一个女朋友的名字。如果你总是和一个同名的女人约会,那很好,但否则真的很糟糕。您从不硬编码名称引用 - 永远。我有没有提到从来没有?你的代码是错误的。它与“面向对象”无关 - 硬编码对特定名称的引用是糟糕的代码。它中断了:var MyForm: TForm2; ... MyForm := TForm2.Create(nil); MyForm.Name := 'Mary';,您的代码不再有效。
  • 在我看来,问题不在于硬编码的名称,而在于您必须为每个需要此功能的表单类复制相同的代码。这就是恕我直言,在这种情况下,“程序”方法变得更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
  • 2019-04-29
相关资源
最近更新 更多