Delphi继承重叠:创建子看父亲

时间:2017-04-09 01:30:35

标签: inheritance components delphi-xe8

情况就是这样:

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.

dpr:

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()方法)显示:

  

" Hello Owner Name是myAncestor,Owner类是TMyChild,ComponentCount是1,myIdex是0,我的名字是,我的类是TMyComponent"

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

如何查看正确的ComponentCount?

1 个答案:

答案 0 :(得分:0)

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

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

例如:

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.