2017-04-09 33 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加載是一種同步操作,所以所有組件在收到消息時都會被加載。 –