我创建了以下函数,用于创建
TWebFrame
并将其加载到我的表单中:
procedure LoadHomePage();
var
FramePage: TWebFrame;
begin
FramePage := TFrame_Home.Create(Self);
FramePage.Name := 'layHome';
FramePage.Visible := False;
FramePage.Parent := LayoutContainer;
FramePage.Align := alClient;
FramePage.LoadFromForm;
end;
这可以正常工作,但我可能并不总是知道该页面的类是什么。假设我不知道该类是
TFrame_Home
,但我可以从某处以字符串形式获取 TFrame_Home
。如何在不知道类名是 TFrame_Home
的情况下动态创建同一页面?
GetClass
函数来做到这一点,但它并没有真正起作用。这是我尝试过的:
procedure LoadHomePageDynamically();
var
FrameClass: TPersistentClass;
FramePage: TWebFrame;
begin
FrameClass := GetClass('TFrame_Home');
FramePage := TWebFrame(FrameClass.Create);
FramePage.Name := 'layHome';
FramePage.Visible := False;
FramePage.Parent := LayoutContainer;
FramePage.Align := alClient;
FramePage.LoadFromForm;
end;
代码编译没有任何错误,但在运行时调用该函数时,出现以下错误:
未捕获的类型错误:无法读取 null 的属性(读取“appendChild”)| TypeError:无法在 Object.UpdateElement (http://localhost:8000/DelphiWebsite/DelphiWebsite.js:68452:32) 处读取 null 属性(读取“appendChild”)在 Object.EndUpdate (http://localhost:8000/DelphiWebsite) /DelphiWebsite.js:36935:43) 在 Object.EndUpdate (http://localhost:8000/DelphiWebsite/DelphiWebsite.js:37513:31) 在 Object.AfterLoadDFMValues (http://localhost:8000/DelphiWebsite/DelphiWebsite.js) :15413:12)在Object.LoadDFMValues(http://localhost:8000/DelphiWebsite/DelphiWebsite.js:85042:26)在Object.LoadFromForm(http://localhost:8000/DelphiWebsite/DelphiWebsite.js:45329:12) )在LoadHomePageDynamically(http://localhost:8000/DelphiWebsite/DelphiWebsite.js:101898:19)在Object.CreatePages(http://localhost:8000/DelphiWebsite/DelphiWebsite.js:101912:7)在Object.WebFormCreate( http://localhost:8000/DelphiWebsite/DelphiWebsite.js:101831:12) 在 Object.cb (http://localhost:8000/DelphiWebsite/DelphiWebsite.js:245:19) 在http://localhost:8000/DelphiWebsite/DelphiWebsite.js [68452:32]
因此,错误似乎来自
FramePage.LoadFromForm
代码,但我需要此代码才能加载框架并将其显示在表单上。
我还使用以下代码在框架的
.pas
文件底部注册了框架的类名:
initialization
RegisterClasses([TFrame_Home]);
GetClass
、FindClass
和 RTTI 非常陌生。我还没有用它做很多事情。我也不确定我正在做的事情是否正确或可能。
我想使用
GetClass
这样做的原因是因为我可能有数百个不同的框架,并且我不想单独“硬编码”创建它们。因此,如果我可以使用类名来创建它们,那就完美了。
那么如何在不知道类名的情况下动态创建
TWebFrame
呢?
您的
LoadHomePage
和 LoadHomePageDynamically
正在调用不同的构造函数。第一个是从 TComponent
(或类似的类层次结构)调用虚拟构造函数,该构造函数将所有者作为参数,第二个是调用基类 TObject
构造函数,因为 TPersistent
类没有任何其他构造函数。
因此,当您调用
TWebFrame(FrameClass.Create)
时,您最终会得到不正确初始化的 TWebFrame
实例,因为您不会调用适当的虚拟构造函数,因此会出现您所看到的错误。
要调用适当的构造函数,您需要声明
TWebFrameClass
元类,它将能够调用适当的构造函数并正确初始化您的 Web 框架实例。
type
TWebFrameClass = class of TWebFrame;
procedure LoadHomePageDynamically();
var
FrameClass: TWebFrameClass;
FramePage: TWebFrame;
begin
FrameClass := TWebFrameClass(GetClass('TFrame_Home'));
FramePage := FrameClass.Create(Self);
FramePage.Name := 'layHome';
FramePage.Visible := False;
FramePage.Parent := LayoutContainer;
FramePage.Align := alClient;
FramePage.LoadFromForm;
end;
如果
TWebFrame
是 TComponent
后代,您也可以使用 TComponentClass
,而不是声明 TWebFrameClass
。但是,在这种情况下,您将需要在 FrameClass.Create(Self);
周围使用类型转换。将框架实例分配给 FramePage
变量时。