我在设计时创建了5个表单。我需要动态创建每个表单的实例并放在一个选项卡上。
我的问题:如果表单名称在字符串数组中,我会调用我的程序:
ShowForm(FormName[3]);// To show the 3rd form on a tab page.
如何为每个表单定义和创建新实例?
这就是我现在所拥有的:
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;
“ HERE IS MY BLBLEM ”这一行是我需要帮助的地方。我不能以这种方式将NewForm重用为具有第二种形式的变量......
注意:我的问题不是标签。而是使用相同的变量名创建表单的新实例。
答案 0 :(得分:8)
将NewForm变量声明为TForm:
var
NewForm: TForm;
begin
NewForm := TMyForm.Create(Tab1); //compiles OK
NewForm := TMyOtherForm.Create(Tab2); //also compiles OK
end;
我假设TMyForm和TMyOtherForm都是TForm的衍生物。
您还可以使用class reference变量减少重复代码,如下所示:
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;
正如Rufo爵士在评论中指出的那样,你甚至可以进一步注册你的课程(我不确定这是否可以在Lazarus中完成,这项练习取决于你)。
首先,在调用ShowFormOnTab方法之前,从类名注册要实例化的表单类,例如:
procedure TMainForm.FormCreate(Sender: TObject);
begin
RegisterClass(TfrmSetupItemCategories);
RegisterClass(TfrmZones);
//and other classes
end;
然后,您可以更改代码以从类名字符串中获取类引用:
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;
这样,代码对于任意数量的类都保持不变。
有关此内容的更多信息,请查看delphi.about.com中的Creating a Delphi form from a string。
答案 1 :(得分:3)
将您的变量声明为祖先类型:
var
NewForm: TForm;
或
var
NewForm: TCustomForm;
缺点:如果要调用自己声明的表单中的任何方法,则需要将变量强制转换为特定的类。
如果您希望编译器在运行时检查NewForm实际上是TMyForm,请使用'soft'强制转换:
(NewForm as TMyForm).MyMethod;
当你完全确定NewForm是TMyForm时(就像刚刚创建它一样),你也可以使用'hard'强制转换:
TMyForm(NewForm).MyMethod;
答案 2 :(得分:0)
对于已注册的类,在使用的表单的初始化中,您可以将其缩短为
Function CreateAndDock(pc:TPageControl;const FormName:String):Boolean;
begin
Result := false;
if Assigned(GetClass(FormName)) and GetClass(FormName).InheritsFrom(TCustomForm) then
With TFormClass( GetClass(FormName)).Create(pc.Owner) do
begin
ManualDock(pc);
Show;
Result := true;
end;
end;
procedure TForm4.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(Integer(CreateAndDock(pagecontrol1,'TDockForm'))));
ShowMessage(IntToStr(Integer(CreateAndDock(pagecontrol1,'TNotExists'))));
end;