Возможно ли для дополнительной панели в пользовательском элементе управления принимать элементы управления от дизайнера? - PullRequest
0 голосов
/ 04 февраля 2019

Я создал простой тестовый элемент управления, унаследованный от элемента управления 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.

Если я надену кнопку на тестовом компоненте, структура показываетэто как часть формы, а не подкомпонент тестового компонента .... и тогда он все равно не работает.

Есть ли способ сделать это?

1 Ответ

0 голосов
/ 05 февраля 2019

После долгих поисков, я нашел некоторую информацию, которая позволила мне собрать решение, которое, кажется, работает.

Кажется, что для обновления элемента управления необходимо переопределить две процедуры в базовом классе.

Первый - это метод, называемый "Loaded", который вызывается после завершения потоковой передачи.

Кажется, что при потоковой передаче все компоненты субпанели, размещенные конструктором, размещаются в базовом компоненте., а не на панели, к которой они изначально принадлежали.Поэтому эта процедура вручную переназначает свойства Parent после завершения процесса загрузки.

Второй метод называется GetChildren, я не смог найти много информации о том, что этот метод на самом деле делает, кроме довольно загадочного текста вхм помогите.Однако я адаптировал переопределенный код из другого примера, который я нашел в Интернете, который имел аналогичное требование, и он работал.Так что, если кто-то может дать некоторое представление о том, почему это необходимо, то это будет полезной информацией.

Я вставил полный исходный код для примера пользовательского компонента ниже, чтобы любой, кто имеет подобные требования в будущем, можете использовать его в качестве исходного шаблона для своих компонентов.

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.
...