使用STRING动态创建表单

its*_*ols 1 delphi lazarus dynamic-forms

我在设计时创建了5个表单.我需要动态创建每个表单的实例并放在一个选项卡上.

我的问题:如果表单名称在字符串数组中,我调用我的过程如下:

ShowForm(FormName[3]);// To show the 3rd form on a tab page.
Run Code Online (Sandbox Code Playgroud)

如何为每个表单定义和创建新实例?

这就是我现在所拥有的:

procedure TForm1.ShowFormOnTab(pProcName:String);
var
  NewForm: TfrmSetupItemCategories;//***HERE IS MY PROBLEM***

  NewTab: TTabSheet;
  FormName: String;

begin
  NewTab := TTabSheet.Create(PageControl1);
  NewTab.PageControl:= PageControl1;
  NewTab.Caption:='hi';
  PageControl1.ActivePage :=  NewTab;

  if pProcName='ProcfrmSetupItemCategories' Then
     begin
       NewForm:=TfrmSetupItemCategories.Create(NewTab);
       NewTab.Caption := NewForm.Caption;
     end;
  if pProcName='ProcfrmZones' Then
     begin
       NewForm:=TfrmZones.Create(NewTab);
       NewTab.Caption := NewForm.Caption;
     end;
.
.
.
end;
Run Code Online (Sandbox Code Playgroud)

" 我的问题就是这里"这一行是我需要帮助的地方.我不能以这种方式将NewForm重用为具有第二种形式的变量......

注意:我的问题不是标签.而是使用相同的变量名创建表单的新实例.

jac*_*ate 8

将NewForm变量声明为TForm:

var
  NewForm: TForm;
begin
  NewForm := TMyForm.Create(Tab1); //compiles OK
  NewForm := TMyOtherForm.Create(Tab2); //also compiles OK
end;
Run Code Online (Sandbox Code Playgroud)

我假设TMyForm和TMyOtherForm都是TForm的衍生物.

您还可以使用类引用变量减少重复代码,如下所示:

procedure TForm1.ShowFormOnTab(pProcName:String);
var
  NewForm: TForm;
  ClassToUse: TFormClass;
  NewTab: TTabSheet;
  FormName: String;

begin
  NewTab := TTabSheet.Create(PageControl1);
  NewTab.PageControl:= PageControl1;
  NewTab.Caption:='hi';
  PageControl1.ActivePage :=  NewTab;

  if pProcName='ProcfrmSetupItemCategories' then
    ClassToUse := TfrmSetupItemCategories
  else if pProcName='ProcfrmZones' then
    ClassToUse := TfrmZones
  else
    ClassToUse := nil;
  if Assigned(ClassToUse) then
  begin
    NewForm := ClassTouse.Create(NewTab);
    NewTab.Caption := NewForm.Caption;
    //if you access custom properties or methods, this is the way:
    if NewForm is TfrmZones then
      TfrmZones(NewForm).ZoneInfo := 'MyInfo';
  end;
end;
Run Code Online (Sandbox Code Playgroud)

注册您的类,然后从字符串创建表单

正如Rufo爵士在评论中指出的那样,你甚至可以进一步注册你的课程(我不确定这是否可以在Lazarus中完成,这项练习取决于你).

首先,在调用ShowFormOnTab方法之前,从类名注册要实例化的表单类,例如:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  RegisterClass(TfrmSetupItemCategories);
  RegisterClass(TfrmZones);
  //and other classes
end;
Run Code Online (Sandbox Code Playgroud)

然后,您可以更改代码以从类名字符串中获取类引用:

procedure TForm1.ShowFormOnTab(pProcName:String);
var
  NewForm: TForm;
  ClassToUse: TFormClass;
  ClassNameToUse: string;
  NewTab: TTabSheet;
  FormName: String;

begin
  NewTab := TTabSheet.Create(PageControl1);
  NewTab.PageControl:= PageControl1;
  NewTab.Caption:='hi';
  PageControl1.ActivePage :=  NewTab;
  //get rid of 'Proc' and add the T
  //or even better, pass directly the class name
  ClassNameToUse := 'T' + Copy(pProcName, 5, MaxInt);
  ClassToUse := TFormClass(FindClass(ClassNameToUse));

  if Assigned(ClassToUse) then
  begin
    NewForm := ClassTouse.Create(NewTab);
    NewTab.Caption := NewForm.Caption;
    //if you access custom properties or methods, this is the way:
    if NewForm is TfrmZones then
      TfrmZones(NewForm).ZoneInfo := 'MyInfo';
  end;
end;
Run Code Online (Sandbox Code Playgroud)

这样,代码对于任何数量的类都保持不变.

有关这方面的更多信息,请参阅delphi.about.com中的字符串创建Delphi表单.

  • 这很可能是真的.在这种情况下,应该有一个定制的方法,从文本转换为类引用.将它们混合在一个大块中是不好的形式.但我不是要你为此负责! (4认同)
  • 使用"从字符串中确定类"来加倍努力. (3认同)