我创建了一个继承自Tcustom控件的简单测试控件,该控件包含2个面板。第一个是标题与顶部对齐,客户端面板与alclient对齐。
我希望客户端面板接受设计者的控件,尽管我可以将控件放置在面板上,但它们在运行时不可见,并且在项目关闭时无法正确保存。
该控件的示例代码如下
unit Testcontrol;
interface
uses Windows,System.SysUtils, System.Classes,System.Types, Vcl.Controls,
Vcl.Forms,Vcl.ExtCtrls,graphics,Messages;
type
TtestControl = class(TCustomControl)
private
FHeader:Tpanel;
FClient:Tpanel;
protected
public
constructor Create(Aowner:Tcomponent);override;
destructor Destroy;override;
published
property Align;
end;
implementation
{ TtestControl }
constructor TtestControl.Create(Aowner: Tcomponent);
begin
inherited;
Fheader:=Tpanel.create(self);
Fheader.Caption:='Header';
Fheader.Height:=20;
Fheader.Parent:=self;
Fheader.Align:=altop;
Fclient:=Tpanel.Create(Self);
with Fclient do
begin
setsubcomponent(true);
ControlStyle := ControlStyle + [csAcceptsControls];
Align:=alclient;
Parent:=self;
color:=clwhite;
BorderStyle:=bssingle;
Ctl3D:=false;
ParentCtl3D:=false;
Bevelouter:=bvnone;
end;
end;
destructor TtestControl.Destroy;
begin
FHeader.Free;
FClient.Free;
inherited;
end;
end.
如果我在测试组件上放一个按钮,结构将其显示为表单的一部分,而不是测试组件的子组件。...然后它仍然无法正常工作。
有没有办法做到这一点?
答案 0 :(得分:2)
经过大量的搜索,我发现了一些信息,使我可以拼凑出一个似乎可行的解决方案。
似乎必须重写基类中的两个过程才能更新控件。
第一个是称为“ Loaded”的方法,流结束时将调用该方法。
似乎流式传输将设计人员放置的所有子面板组件放置在基本组件上,而不是放置在它们最初作为其父面板上。因此,该例程在加载过程完成后手动重新分配Parent属性。
第二种方法称为GetChildren,除了chm帮助中相当晦涩的文本外,我找不到更多有关此方法实际作用的信息。但是,我改写了我在网上找到的另一个具有类似要求的示例中的覆盖代码,并且该示例可以正常工作。因此,如果任何人都可以提供有关为什么这样做的必要见识,那么这将是有用的信息。
我在下面粘贴了示例自定义组件的完整源代码,以便将来有类似要求的任何人都可以将其用作自己组件的起始模板。
unit Testcontrol;
interface
uses Windows, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.ExtCtrls,graphics;
type
TtestControl = class(TCustomControl)
private
FHeader:Tpanel;
FClient:Tpanel;
protected
procedure Loaded;override;
procedure GetChildren(Proc:TGetChildProc; Root:TComponent);override;
public
constructor Create(Aowner:Tcomponent);override;
destructor Destroy;override;
published
property Align;
end;
implementation
{ TtestControl }
constructor TtestControl.Create(Aowner:Tcomponent);
begin
inherited;
Fheader:=Tpanel.create(self);
Fheader.setsubcomponent(true);
Fheader.Caption:='Header';
Fheader.Height:=20;
Fheader.Parent:=self;
Fheader.Align:=altop;
Fclient:=Tpanel.Create(Self);
with Fclient do
begin
setsubcomponent(true);
ControlStyle := ControlStyle + [csAcceptsControls];
Align:=alclient;
Parent:=self;
color:=clwhite;
BorderStyle:=bssingle;
Ctl3D:=false;
ParentCtl3D:=false;
Bevelouter:=bvnone;
end;
end;
destructor TtestControl.Destroy;
begin
FHeader.Free;
FClient.Free;
inherited;
end;
procedure TtestControl.Loaded;
var i:integer;
begin
inherited;
for i := ControlCount - 1 downto 0 do
if (Controls[i] <> Fheader) and (Controls[i] <> Fclient) then
Controls[i].Parent := Fclient;
end;
procedure TtestControl.GetChildren(Proc:TGetChildProc; Root:TComponent);
var i:integer;
begin
inherited;
for i := 0 to Fclient.ControlCount-1 do
Proc(Fclient.Controls[i]);
end;
end.