我想让用户创建同一表单的多个实例(我们称它为MDI子表单Form1)。因此,在创建表单的过程中,我有两个这样的过程。

procedure MyProcedure1;           // procedure 2 is similar. it also has a var called MyFrm
var MyFrm: TFrm1;
begin
  ...
  MyFrm:= TFrm1.create(MainForm);
  MyFrm.BringToFront;
  MyFrm.LoadFromFile(someFile);
end;

如您所见,MyFrm是本地变量。这对我来说是可以的,因为在创建表单后,我不需要以编程方式访问该表单。没有其他名为Frm1的全局变量。在MyFrm的OnClose事件中,我有Action:= caFree;

是什么原因导致上述错误?
用户发送了该错误。它只发生了一次,我无法复制。

编辑:
  • 错误出现在“MyFrm:= TFrm1.create”行中。
  • 有人建议我需要以编程方式为动态创建的表单赋予唯一名称。我也想知道自己创建表单时会使用什么名称,因此我在调用MyProcedure1过程时进入了代码。
    Delphi自动给出唯一的名称,例如
    MyFrm.name = MyFrm,然后
    MyFrm.name = MyFrm_1,
    MyFrm.name = MyFrm_2,
    MyFrm.name = MyFrm_3,依此类推。
  • MyFrm.Name不会在LoadFromFile中更改。我已在过程MyProcedure1的末尾检查(断点)“MyFrm.Name”的值;在LoadFromFile之后。这个名字是唯一的。
  • 正如某些人建议的那样,我重写了SetName过程并检查了TMyFrm的名称。实际上,每种形式都有一个唯一的名称。

    过程TMyFrm.SetName(const Value:TComponentName);
    开始
    ShowMessage(Value);
    遗传;
    结尾;
  • 我在这个应用程序中有很多表格,但是只有MainForm是自动创建的。
  • 我不使用线程。无论如何,这将是无关紧要的,因为表单是由用户创建的(因此多线程无关紧要,除非用户可以同时创建2个表单)。
  • 最佳答案

    在TFrm1.Create中将MainForm设置为所有者将在MainForm的组件列表中包括新创建的表单。一个组件确保此列表不包含任何两个具有相同非空名称的组件(否则FindComponent将不起作用)。当组件更改其名称时,此机制也适用。

    只要您没有在TFrm1.Create中指定名称,它很可能是由LoadFromFile方法设置的,这意味着除非更改文件的内容,否则对名称的影响不大。

    一个有效的解决方法是使用nil作为所有者创建表单,从文件中加载表单,将名称更改为唯一值或为空字符串,最后调用MainForm.InsertComponent。

    procedure MyProcedure1;
    var MyFrm: TFrm1;
    begin
      ...
      MyFrm:= TFrm1.create(nil);
      MyFrm.BringToFront;
      MyFrm.LoadFromFile(someFile);
      MyFrm.Name := ''; // or some unique name
      MainForm.InsertComponent(MyFrm);
    end;
    

    10-07 19:09