5,927
社区成员




IDE事先(IDE本身被编译发布时)不认识该控件,不知道控件的类型信息。控件被放到窗体上,在设计时就可以实例化运行(不是项目编译以后运行),所以可以设置属性(属性其实是调用成员函数),使控件运行(改变外观,加载图片显示,连接数据库获取数据并显示等),与通过代码编译后运行效果一样,真正的“所见即所得”。
但是我有点不清楚这是如何做到的,好像跟TClass以及虚构造函数有关?还有,IDE如何得知获取三方控件具体的属性和事件信息显示在对象检视器里?
关系就是这样的:
function CreateObject(AClass: TClass; AOwner: Tcomponent = nil): TObject;
begin
Result := AClass.NewInstance;
if Result.InheritsFrom(TComponent) then
TComponent(Result).Create(AOwner)
else
Result.Create;
end;
编译器会生成rtti信息,然后ide可以通过反射机制获取控件的详细信息,比如类型,属性,成员函数等,然后自然就能实例化控件了。
IDE通过包中的RTTI获得组件的信息(类名,属性名、类型,方法/事件名、原型等等),所以安装组件可以不需要源码,只需要安装二进制包即可(有源码也要先编译成包)。能设计时实例化是因为Delphi类支持虚构造函数,构造函数的地址可以在运行时确定(非虚函数的地址是在编译时确定的,所以无法实例化在程序自己,比如IDE,编译时未知的类)。
Qt的plugin能够设计时实例化是因为它要求plugin引用它的接口类,Qt设计器通过接口方法间接让组件自己来实例化、析构、设置属性等等),这要求plugin有源码(除非保证下一条),而且plugin和IDE要用同一编译器的同一版本编译(意思是如果安装Qt Creator之后升级了工具链,安装plugin需要Qt Creator本身也重新编译)。
这个其实就是插件与接口处理的,IDE本身有很多接口,控件本身也分为运行时与设计时,他通过接口注册告诉IDE现在多了一个可以使用的东西。然后IDE就可以调用并运行。
IDE本身也是一个程序,IDE程序运行要实例化一个类的对象(就是设计时实例化),必须在IDE本身程序被编译时知道该类的类型信息。但是IDE本身被编译时不知道哪些三方控件的类型信息。