Forms Delphi表单继承,可视化bug

Forms Delphi表单继承,可视化bug,forms,delphi,Forms,Delphi,我在delphi中有一个bug,我从不同的表单3中输入,当我创建最后一个子元素时,它会创建每个组件3次。它是dll项目,dll生成不同的形式。我有一个测试dll的启动器。在调用创建所需表单的函数时,它会在下面的一个窗口屏幕中创建所有3个表单。我试着给我的组件起相同的名字。它在编译dll时没有显示任何错误,但是在从启动器调用函数时,它会说这个或那个组件已经存在,所以我必须给所有组件指定不同的名称。如果不清楚,请问我一些问题,我不知道如何更清楚地解释 以下是我的表单定义: TFrmReserve

我在delphi中有一个bug,我从不同的表单3中输入,当我创建最后一个子元素时,它会创建每个组件3次。它是dll项目,dll生成不同的形式。我有一个测试dll的启动器。在调用创建所需表单的函数时,它会在下面的一个窗口屏幕中创建所有3个表单。我试着给我的组件起相同的名字。它在编译dll时没有显示任何错误,但是在从启动器调用函数时,它会说这个或那个组件已经存在,所以我必须给所有组件指定不同的名称。如果不清楚,请问我一些问题,我不知道如何更清楚地解释

以下是我的表单定义:

  TFrmReserve007 = class(TfrmRsrvExtended)
  private
    { Private declarations }
    [...]
  protected
    { Protected declarations }
    [...]
  public
    { Public declarations }
    [...]
  end;

TfrmRsrvExtended = class(TfrmRsrv)
    Act_Browse2: TAction;
    Act_SaveAs2: TAction;
    Act_LoadDefault2: TAction;
    ImageListToolbar2: TImageList;
    PSCMandatoryObjects2: TPSCMandatoryObjects;
    ImageListMouvement2: TImageList;
    [...More components...]
    TopPanel2: TPSCTopPanel;
    procedure Act_BrowseExecute(Sender: TObject);
    procedure Act_LoadDefaultExecute(Sender: TObject);
    procedure Act_loadSenderExecute(Sender: TObject);
    procedure bbtn_Browse2Click(Sender: TObject);
  private
    { Private declarations }
    [...]
  protected
    [...]
  public
    { Public declarations }
    [...]
  end;

TFrmRsrv = class(TForm)
    PSCButtonPanel1: TPSCButtonPanel;
    PageControl: TPageControl;
    TabSheeta: TTabSheet;
    [.. More components...]
    Act_LoadKeyWord1: TAction;
    Act_LoadStorage1: TAction;
    Mandatory1: TPSCMandatoryObjects;
    PSCHint: TPSCHint;
    {$ENDREGION}
  private
    { Private declarations }
  protected
    { Protected declarations }
    [...]
  public
    { Public declarations }
    [...]
  end;
这[…]意味着那里有功能和程序

这是我调用使用TFrmReserve007.Createnil创建表单时的屏幕

MCVE 发射装置

procedure setLXCom;
begin
  if lxPom59Svc = nil then
  begin
    ClassID := ContractIDToClassID('pom59PumaToRio@dtad');
    IU := CreateLynxObject( ClassID);

    if IU = Nil then begin
      raise Exception.Create( 'CreateLynxObject failed');
    end;

    IU.QueryInterface( Ipom59Svc, lxPom59Svc);

    if lxPom59Svc = nil then
    begin
      raise Exception.Create( 'QueryInterface ILynxRio failed');
    end;
  end;
end;

procedure TForm1.Button11Click(Sender: TObject);
begin
  setLxCom;
  lxPom59Svc.RioSvcGui007V2(
  LxPom59Svc.RioGetDataPCE007V2('9051','2010010281',false),lgFRENCH)
end;
动态链接库


听起来你就是这么做的-让我猜猜重现这个问题的步骤:

创建了一个基本正则形式-我们称之为TForm1 向TForm1添加了许多控件 创建了第二个正则形式-我们称之为TForm2 然后编辑包含TForm2的.pas文件,使其从TForm1继承,即:TForm2=classTForm1 您发现TForm2不包含TForm1中的任何控件,即使您继承了TForm1。 因此,您将控件从TForm1设计器复制并粘贴到TForm2设计器。 这创建了一个运行时错误,指示具有相同名称的控件已存在。不是猜测-你指出了这一点 然后,您以子代形式重命名了所有重复控件—这不是猜测—您指出了这一点 现在,在运行时,您拥有了来自基本表单的所有控件,以及复制、粘贴并重命名为子表单的所有控件。但是,子窗体的窗体设计器在设计时不显示任何祖先控件,只显示您粘贴的新控件。 这是使用可视化设计器创建继承表单的错误方法

要使用设计时编辑创建继承表单,必须选择

文件->新建->其他

从这里开始,这取决于Delphi版本,但对于任何合理的现代。。。你选择

Delphi项目->可继承项->表格1

其中Form1是您希望继承的基本表单。这将生成一个新单元,该单元的表单继承了类代码和基本表单的DFM。如果在表单的设计器中将.dfm文件视为text-push Alt+F12,则在顶部以错误的方式创建表单:

 object Form2: TForm2
   ...[etc]
然而,如果您按照上述方式正确继承,您将看到.dfm文件的开头是:

 inherited Form2: TForm2
   ...[etc]
或者,您可以创建一个常规表单并修改类型声明以从基表单继承:

 TForm2 = class(TForm1)
  ...[etc]
但您还必须确保将.dfm文件从对象修改为继承。这可确保表单设计器正确导入属于祖先表单的控件

这里的教训是,设计时表单包含两段关键代码

.pas文件中的类代码 .dfm文件中的组件设计和布局信息
这里的错误是您只继承了类代码功能,而没有继承设计和布局信息内容

你在这里干什么真的一点也不清楚。我们不能有一个MCVE吗?您还应该澄清DLL和主机可执行文件之间的关系。如果它们都是VCL应用程序,那么您的设计将永远无法工作。您将有两个VCL实例,这太多了。这就是运行时包存在的原因。@DavidHeffernan不,它们并非都是VCL应用程序。一个是VCL,另一个是dll。我用com来做这个。我的启动器只是创建带有dll的链接,并调用创建表单的函数。函数本身只调用.createnil,其他什么都不调用。如果DLL是在Delphi中编码的,那么就有两个VCL实例。一个在主机可执行文件中,一个在DLL中。无论这是否是一个问题,我们无法从这里确定,因为你没有包括足够的细节。这很可能是个问题。请出示MCVE。你到底想要什么?Launche调用函数blabla,函数blabla does form.createnil。我没有编写创建函数,它是一个delphi类。。。我不知道你到底想从中得到什么。没有什么可以展示的了,它只是创造了一切。它就像显示一个ShowMEssage函数的mcve。。。只显示一个文本,甚至不调用另一个函数。是的,我就是这么做的。我刚检查过,项目中没有不可继承的项目。顺便说一句,我在网上没有找到任何东西:@MarioR。可继承项仅在项目处于打开状态时可用。
 TForm2 = class(TForm1)
  ...[etc]