Where to initialize Subcomponent.Parent?

泄露秘密 提交于 2020-01-30 11:22:27

问题


I want to create my own custom control. Let's say I want to initialize its graphic properties. Obviously I cannot do that in Create because a canvas/handle is not YET allocated. The same if my custom control contains a subcomponent (and I also set its visual properties).

There are quite several places on SO that discuss the creation of a custom control. They don't really agree on it.

So, I did this test that shows the creation order. The conclusion is:

   Dropping control on a form:
      Create
      AfterConstruction
      SetParent
      CreateWnd
      CreateWindowHandle
      CreateWnd (post inherited)
      SetParent (post inherited)

   Executing the program
      Create
      AfterConstruction
      SetParent
      SetParent (post inherited)
      SetParent
      SetParent (post inherited)
      Loaded
      CreateWnd
      CreateWindowHandle
      CreateWnd (post inherited)
      SetParent
      SetParent (post inherited)

   Dynamic creation
      Create
      AfterConstruction

   Reconstructing the form
      Not tested yet

I used to create the subcomponent in Create and set MySubcomponents.Parent = self in CreateWnd. But that is not a good place because CreateWnd is not always called. AfterConstruction is also out of question because the handle is not ready yet.

UNIT cvTester;

{This file tests the initialization order of a custom control.}

INTERFACE
{$WARN GARBAGE OFF}  

USES
  System.SysUtils, System.Classes, vcl.Controls, vcl.Forms, Vcl.ExtCtrls;


TYPE
  TCustomCtrlTest = class(TPanel)
    private
    protected
    public
      constructor Create(AOwner: TComponent); override;
      procedure Loaded; override;
      procedure AfterConstruction; override;
      procedure CreateWnd; override;
      procedure CreateWindowHandle(const Params: TCreateParams); override;
      procedure WriteToString(s: string);
    published
  end;



procedure Register;

IMPLEMENTATION
USES System.IOUtils;

procedure Register;
begin
  RegisterComponents('mine', [TCustomCtrlTest]);
end;

constructor TCustomCtrlTest.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  WriteToString('Create'+ #13#10);
  // Create other subcomponents here:
  // Subcomponent.Owner:= Self;
end;

procedure TCustomCtrlTest.Loaded;
begin
  inherited;
  WriteToString('Loaded'+ #13#10);
end;

procedure TCustomCtrlTest.AfterConstruction;
begin
  inherited;
  WriteToString('AfterConstruction'+ #13#10);
end;

procedure TCustomCtrlTest.CreateWnd;
begin
  inherited;
  WriteToString('CreateWnd'+ #13#10);
  // Subcomponent.Parent = Self;
end;

procedure TCustomCtrlTest.CreateWindowHandle(const Params: TCreateParams);
begin
  inherited CreateWindowHandle(Params);
  WriteToString('CreateWindowHandle'+ #13#10);
end;

procedure TCustomCtrlTest.SetParent(AParent: TWinControl);
begin
  WriteToString('SetParent'+ #13#10);
  inherited SetParent(AParent);
  WriteToString('SetParent (post inherited)'+ #13#10);
end;

function GetAppDir: string;
begin
 Result:= ExtractFilePath(Application.ExeName);
end;

procedure TCustomCtrlTest.WriteToString(s: string);
begin
 System.IOUtils.TFile.AppendAllText(GetAppDir+ 'test.txt', s);
end;
end.

来源:https://stackoverflow.com/questions/56859524/where-to-initialize-subcomponent-parent

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!