2017-04-09 201 views
-1

就是这种情况:Delphi的继承重叠:在创建子见父亲

3 involucrated:一个myComponent的部件,一个祖先形式和子形式:(编辑)

MyComponent的:

unit Component1; 

interface 

uses 
    System.SysUtils, System.Classes, Vcl.Dialogs; 

type 
    TMyComponent = class(TComponent) 
    private 
    { Private declarations } 
    procedure Something(i: Integer); 
    protected 
    { Protected declarations } 
    public 
    { Public declarations } 
    constructor Create(AOwner: TComponent); override; 
    published 
    { Published declarations } 
    end; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterComponents('Samples', [TMyComponent]); 
end; 

{ TMyComponent } 

constructor TMyComponent.Create(AOwner: TComponent); 
var 
    i: integer; 
begin 
    inherited Create(AOwner); 
    if AOwner.ComponentCount > 0 then 
    for i := 0 to AOwner.ComponentCount -1 do 
     Something(i); 
end; 

procedure TMyComponent.Something(i: Integer); 
var 
    txt: string; 
begin 
    txt := Format('Owner Name is %s, Owner Class is %s, ComponentCount is %d,'+ 
    'myIndex is %d, My name is %s, my class is %s', 
    [Owner.Name, Owner.ClassName, Owner.ComponentCount, i, Owner.Components[i].Name, 
    Owner.Components[i].ClassName]); 
    ShowMessage('Hello '+txt); 
end; 

end. 

祖先形态:

unit Ancestor; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Component1; 

type 
    TmyAncestor = class(TForm) 
    MyComponent1: TMyComponent; 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    myAncestor: TmyAncestor; 

implementation 

{$R *.dfm} 

end. 

子窗体:

unit TheChild; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Ancestor, Vcl.StdCtrls, Component1; 

type 
    TmyChild = class(TmyAncestor) 
    edt1: TEdit; 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    myChild: TmyChild; 

implementation 

{$R *.dfm} 

end. 

朝鲜民主主义人民共和国:

program InheritanceTest; 

uses 
    Vcl.Forms, 
    Ancestor in 'Ancestor.pas' {myAncestor}, 
    TheChild in 'TheChild.pas' {myChild}; 

{$R *.res} 

begin 
    Application.Initialize; 
    Application.MainFormOnTaskbar := True; 
    Application.CreateForm(TmyChild, myChild); 
    Application.Run; 
end. 

子窗体从祖先窗体继承myComponent的。

创建时,子窗体会触发构造函数TMyComponent.Create(),但AOwner.ComponentCount请参阅祖先ComponentCount而不是子项的ComponentCount

消息(从myComponent.Something()法)表明这一点:

“你好所有者姓名myAncestor,所有者类是TMyChild,ComponentCount是1,myIdex是0,我的名字是,我的课是TMyComponent”

组件在子窗体中看不到edt1组件!

如何查看正确的ComponentCount?

+0

A [MCVE]将有助于 –

+0

我可以附加文件? – NizamUlMulk

+0

请勿附加文件。制作一个[mcve]并将它编辑成问题 –

回答

0

您的TMyComponent对象没有看到TEdit对象,因为该对象尚未创建。您的TMyComponent对象首先被创建,因为它首先出现在子Form的DFM中。

如果您希望组件在您的组件创建后创建TEdit时,您可以让组件覆盖虚拟Notification()方法。当组件被添加到(或从中移除)所有者时,所有者向其拥有的所有组件广播opInsert(或opRemove)通知。由于您的TMyComponentTEdit对象拥有相同的所有者,因此在表单的拥有组件列表中添加TEdit时,您的组件将收到opInsert通知。

例如:

unit Component1; 

interface 

uses 
    System.SysUtils, System.Classes, Vcl.Dialogs; 

type 
    TMyComponent = class(TComponent) 
    private 
    { Private declarations } 
    procedure Something(const FromWhere: string; Index: Integer); 
    protected 
    { Protected declarations } 
    procedure Notification(AComponent: TComponent; Operation: TOperation); override; 
    public 
    { Public declarations } 
    constructor Create(AOwner: TComponent); override; 
    published 
    { Published declarations } 
    end; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterComponents('Samples', [TMyComponent]); 
end; 

{ TMyComponent } 

constructor TMyComponent.Create(AOwner: TComponent); 
var 
    i: integer; 
begin 
    inherited Create(AOwner); 
    if AOwner <> nil then 
    begin 
    for i := 0 to AOwner.ComponentCount-1 do 
     Something(`Create`, i); 
    end; 
end; 

procedure TMyComponent.Notification(AComponent: TComponent; Operation: TOperation); 
var 
    i: integer; 
begin 
    inherited; 
    if (Operation = opInsert) and (AComponent <> Self) and (AComponent.Owner = Owner) then 
    Something('Notification', AComponent.ComponentIndex); 
end; 

procedure TMyComponent.Something(const FromWhere: string; Index: Integer); 
var 
    txt: string; 
begin 
    txt := Format('Owner Name is %s, Owner Class is %s, ComponentCount is %d, myIndex is %d, My name is %s, my class is %s', 
    [Owner.Name, Owner.ClassName, Owner.ComponentCount, Index, Owner.Components[Index].Name, Owner.Components[Index].ClassName]); 
    ShowMessage(FromWhere + ',' + txt); 
end; 

end. 
+0

亲切!谢谢Remy! – NizamUlMulk

+0

现在,另一个问题....该方法解决插入组件的识别...但是...总是有一个但是...该组件将是不完整的,例如。创建一个dbgrid,但列还没有。我怎么知道什么时候一切完成?是否有可能? – NizamUlMulk

+0

@NizamUlMulk当它自己完成加载时,会通知一个组件(通过'Loaded()'),但是在这种情况下,组件之间不会有广播通知。这将需要两个组件之间的直接沟通。否则,你可以让你的组件发送一个异步消息给自己,然后等待该消息被消息队列处理。 DFM加载是一种同步操作,所以所有组件在收到消息时都会被加载。 –