来自:http://blog.csdn.net/lailai186/article/details/7442385
-----------------------------------------------------------------------
学习DELPHI最好的方法是看DELPHI的VCL原代码爱看他的机制本文就类TComponent的原代码来看他的机制.
{ TComponent } constructor TComponent.Create(AOwner: TComponent); begin FComponentStyle := [csInheritable]; if AOwner <> nil then AOwner.InsertComponent(Self); end; procedure TComponent.InsertComponent(AComponent: TComponent); begin AComponent.ValidateContainer(Self); ValidateRename(AComponent, , AComponent.FName);//看是否有重名的对象如果有则发异常 Insert(AComponent);//在自己的子组件列表里加入AComponent的引用 AComponent.SetReference(True); if csDesigning in ComponentState then AComponent.SetDesigning(True); Notification(AComponent, opInsert);//给自己发一个通知消息 end; procedure TComponent.ValidateRename(AComponent: TComponent; const CurName, NewName: string); begin if (AComponent <> nil) and not SameText(CurName, NewName) and (AComponent.Owner = Self) and (FindComponent(NewName) <> nil) then raise EComponentError.CreateResFmt(@SDuplicateName, [NewName]); if (csDesigning in ComponentState) and (Owner <> nil) then Owner.ValidateRename(AComponent, CurName, NewName);//递归调用查是否有重名的组件 end; procedure TComponent.ValidateContainer(AComponent: TComponent); begin AComponent.ValidateInsert(Self); end; procedure TComponent.ValidateInsert(AComponent: TComponent); begin end; procedure TComponent.Insert(AComponent: TComponent);//我们可以看到他的子组件的引用是用TLIST来保存的 begin if FComponents = nil then FComponents := TList.Create; FComponents.Add(AComponent); AComponent.FOwner := Self;//给刚刚加上的主件赋上拥有者属性 end; destructor TComponent.Destroy; file://可以看到每一个组件都维护一个FFREENOTIFILES的列表 begin Destroying; if FFreeNotifies <> nil then begin while Assigned(FFreeNotifies) and (FFreeNotifies.Count > 0) do TComponent(FFreeNotifies[FFreeNotifies.Count - 1]).Notification(Self, opRemove); FreeAndNil(FFreeNotifies);//如果自己析构的时候,对自己FFREENOTIFILES里面引用的对象调用Notification,把自己析构造的事件告诉他们 end; DestroyComponents; if FOwner <> nil then FOwner.RemoveComponent(Self); inherited Destroy; end; procedure TComponent.FreeNotification(AComponent: TComponent);//通过这个过程可以证实FFREENOTIFILES是一个列表这个列表维护自己析构的时候给那些对象通知 begin if (Owner = nil) or (AComponent.Owner <> Owner) then begin // Never acquire a reference to a component that is being deleted. assert(not (csDestroying in (ComponentState + AComponent.ComponentState))); if not Assigned(FFreeNotifies) then FFreeNotifies := TList.Create; if FFreeNotifies.IndexOf(AComponent) < 0 then begin FFreeNotifies.Add(AComponent); AComponent.FreeNotification(Self); end; end; Include(FComponentState, csFreeNotification); end;
2.7 TComponent分枝
TComponent分枝包含了所有从TComponent而不是TControl继承下来的VCL&CLX类。对于这个分枝中的对象,你在设计时刻可以直接在窗体重操作它们,但是在运行时刻它们不会为用户所见。它们是持续的对象,具有以下功能:
n 出现在组件面板中,并且在窗体重可以被改变
n 拥有和操作其它组件
n 加载和保存它们本身
TComponent引入的几个方法指明了组件在设计时刻的行为和随着组件保存哪些信息。流功能(保存窗体中对象属性的窗体文件的加载和保存)在这个分枝中出现。组件的发布属性被规定为持续的并且将自动被“流”。
TComponent分枝也引入了所有权的概念,该概念取自组件库。有两个属性支持所有权:Owner和 Components。每个组件都含有一个Owner属性指定其所有者。
一个组件可能会拥有另外的组件,在这种情况下,所有被包含组件都会出现在该组件的Components属性中。
每个组件的构造器都会包含一个参数指定新组件的所有者。
如果该引入的所有者存在,那么这个组件就会自动被添加到所有者的Components属性中。
Components属性除了用来存储所包含组件列表外,还可以提供自动释放其所有的组件。一旦一个组件有了一个所有者,那么当其所有者被释放是,它也会自动释放。
例如,因为TForm继承自TComponent,所以当一个窗体被销毁时,其所包含的所有组件都会被自动销毁并且释放其所占用的内存(当然,每个组件必须正确地设计其析构器使其能够被自动的清除)。
如果一个属性类型是Tcomponent或者其后裔,当流系统读入它时会自动创建一个其实例。如果一个属性类型是TPersistent而不是TComponent,那么流系统会通过该属性使用一个已经存在的该类型实例,并且为这个实例属性读取值。
下面是TComponent分枝的某些类:
n TActionList,维护一个动作列表,这个动作列表提供了一系列使你的程序可以对用户输入作出反应的抽象动作
n TMainMenu,为一个窗体提供菜单栏以及其下拉菜单
n TOpenDialog, TSaveDialog, TFontDialog, TFindDialog, TColorDialog等等,这些类提供一些通用的对话框以显示&收集信心
n TScreen,一个用以跟踪应用程序所创建的窗体&数据模块、活动窗体、窗体中的活动组件、屏幕的尺寸及其组成、程序可用的光标及字体等数据的类。
不需要一个可视界面的组件一般都直接源自TComponent类。如果需要创建一个诸如TTimer的组件,你可以直接继承TComponent,这些组件可以出现在组件列表中,但不是通过设计时刻的可视界面而是通过代码来访问其内在功能。尺寸的huonList,