奇怪的是"名为TFrm1的组件已存在"错误

WeG*_*ars 5 delphi


我想让用户创建同一表单的多个实例(让我们称之为Form1,这是一个MDI子表单).所以我有两个这样的程序,我创建表单.

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

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

什么可能导致上述错误?用户发送了该错误.它只发生一次,我无法重现它.


编辑:

  1. 该错误出现在"MyFrm:= TFrm1.create"行中.

  2. 有些人建议我需要以编程方式为动态创建的表单指定唯一的名称.我也想知道自己在创建表单时所采用的名称,因此我在调用MyProcedure1过程时进入了代码.
    Delphi自动提供唯一的名称,如
    MyFrm.name = MyFrm,然后是
    MyFrm.name = MyFrm_1,
    MyFrm.name = MyFrm_2,
    MyFrm.name = MyFrm_3,依此类推.

  3. LoadFromFile中未更改MyFrm.Name.我在程序MyProcedure1的末尾检查了(断点)'MyFrm.Name'的值; 在LoadFromFile之后.这个名字很独特.

  4. 正如一些人建议的那样,我重写了SetName过程并检查了TMyFrm的名称.确实,每个表格都有一个独特的名称

    procedure TMyFrm.SetName(const Value:TComponentName);
    开始
    ShowMessage(Value);
    遗传;
    结束;

  5. 我在这个应用程序中有许多表单,但只有MainForm是自动创建的.

  6. 我不使用线程.无论如何,这是不相关的,因为表单是由用户创建的(因此多线程是无关紧要的,除非用户可以同时创建2个表单).

Uwe*_*abe 8

MainForm作为TFrm1.Create中的所有者将在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;
Run Code Online (Sandbox Code Playgroud)


Mar*_*ema 7

导致该消息是因为每个表单必须唯一命名.

在两次创建表单时,需要确保每个实例都具有唯一的名称,或者将Name设置为空字符串.后者也是使用数据模块的多个实例时的技巧,因此数据感知控件的自动链接不会总是使用第一个实例.

MyFrm.Name := MyFrm.Name + <something unique>;
Run Code Online (Sandbox Code Playgroud)

MyFrm.Name := '';
Run Code Online (Sandbox Code Playgroud)

在Create调用之后,你应该没问题

  • 名称必须是唯一的或没有.`MyFrm.Name:=''`如果你不关心这个名字会更好,因为你不需要找出一个新的名字而且VCL会跳过检查名称的唯一性. (5认同)

Jør*_*eit 3

MyFrm.Name两种情况都是一样的...

确保比MyFrm.Name是唯一的...