-
Пишу компонент-контейнер на основе TWinControl. В нем имеется другой контейнер (допустим - TPanel или TGroupBox), который занимает не всю его площадь. Как сделать так чтобы при вставке в мой компонент других контролов (с палитры Delphi в Design time), вставляемый компонент вставлялся бы не в TWinControl, а в его дочерний TPanel? Как я понимаю надо перехватывать событие вставки в Design time и вместо Parent := Self делать Parent := Self.Panel. Есть ли такое событие?
-
-
> DimaBr
Вот что получилось. Где ошибка? при вставке компонента на форму пишет Access Violation unit CMLGroupPanel;
interface
uses
SysUtils, Classes, Controls, StdCtrls, Graphics;
type
TCMLGroupPanel = class(TWinControl)
private
cbEnableGroup: TCheckBox;
gbClient: TGroupBox;
FOnEnableChanged: TNotifyEvent;
procedure ProcessResize;
procedure OnCheckBoxClicked(Sender: TObject);
procedure SetOnEnableChanged(const Value: TNotifyEvent);
function GetTitle: String;
procedure SetTitle(const Value: String);
protected
procedure Resize; override;
procedure CheckBoxClicked; dynamic;
procedure CreateWnd; override;
procedure DestroyWnd; override;
function IsInnerControl(aControl: TControl): Boolean;
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
procedure Loaded; override;
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
published
property Title: String read GetTitle write SetTitle;
property OnEnableChanged: TNotifyEvent read FOnEnableChanged
write SetOnEnableChanged;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Additional', [TCMLGroupPanel]);
end;
constructor TCMLGroupPanel.Create(aOwner: TComponent);
begin
inherited;
ControlStyle := ControlStyle + [csAcceptsControls];
AutoSize := False;
end;
procedure TCMLGroupPanel.Resize;
begin
inherited;
ProcessResize;
end;
procedure TCMLGroupPanel.ProcessResize;
begin
gbClient.SetBounds(0, 10, Width, Height - 10);
gbClient.SendToBack;
end;
procedure TCMLGroupPanel.OnCheckBoxClicked(Sender: TObject);
begin
CheckBoxClicked;
end;
procedure TCMLGroupPanel.CheckBoxClicked;
begin
gbClient.Enabled := cbEnableGroup.Checked;
if Assigned(FOnEnableChanged) then
FOnEnableChanged(Self);
end;
procedure TCMLGroupPanel.SetOnEnableChanged(const Value: TNotifyEvent);
begin
FOnEnableChanged := Value;
end;
function TCMLGroupPanel.GetTitle: String;
begin
Result := cbEnableGroup.Caption;
end;
procedure TCMLGroupPanel.SetTitle(const Value: String);
begin
cbEnableGroup.Caption := Value;
end;
destructor TCMLGroupPanel.Destroy;
begin
inherited;
end;
procedure TCMLGroupPanel.CreateWnd;
begin
inherited;
cbEnableGroup := TCheckBox.Create(Self);
cbEnableGroup.Parent := Self;
cbEnableGroup.Left := 10;
cbEnableGroup.Top := 5;
cbEnableGroup.OnClick := OnCheckBoxClicked;
gbClient := TGroupBox.Create(Self);
gbClient.Parent := Self;
ProcessResize;
end;
procedure TCMLGroupPanel.DestroyWnd;
begin
inherited;
end;
procedure TCMLGroupPanel.GetChildren(Proc: TGetChildProc;
Root: TComponent);
var I: Integer;
begin
inherited;
for I := 0 to gbClient.ControlCount - 1 do
Proc(gbClient.Controls[I]);
end;
function TCMLGroupPanel.IsInnerControl(aControl: TControl): Boolean;
begin
Result := (aControl = cbEnableGroup) or (aControl = gbClient);
end;
procedure TCMLGroupPanel.Loaded;
var I: Integer;
begin
inherited;
for I := 0 to ControlCount - 1 do
if not IsInnerControl(Controls[I]) then
Controls[I].Parent := gbClient;
end;
end.
-
Вот тут, CreateWnd -> Resize -> ProcessResize а сонтролы ещё не созданы
procedure TCMLGroupPanel.ProcessResize;
begin
if not Assigned(gbClient) then Exit;
gbClient.SetBounds(0, 10, Width, Height - 10);
gbClient.SendToBack;
end;
-
Создал тестовый проект. Вставил в компонент кнопку, сохранил. В dfm файле все правильно вроде, а когда снова открываешь проект не может создать форму (List index is out of bounds (2)). Еще вопрос: в GetChildren надо вызывать inherited ?
-
нет, поскольку мы сами указываем какий компоненты сохранять
-
Не пойму где все же ошибка. Не хочет загружаться из dfm. Пишет list index is out of bounds. Где то в цикле по ControlCount что-ли ошибка с индексом? Сорри за навязчивость
-
Тестирование компонента я вижу в таком ракурсе: 1. Кинте компонент на форму 2. Киньте на компонент кнопку 3. перейдите в просмотр DFM (Alt + F12) (если всё в DFM впорядке то дальше) 4. Установите брейкпоин в конструктор 5. запустите приложение 6. После остановки давим F8 до возникновения ошибки и локализуем её
-
перенесите код из Loded в CreateWnd и замените направлениепросмотра компонентов, а то после переноса кнопки количество контролов уменьшается и цикл проходит по несуществующему контролу.
procedure TCMLGroupPanel.CreateWnd;
var i: integer;
begin
inherited;
cbEnableGroup := TCheckBox.Create(Self);
cbEnableGroup.Parent := Self;
cbEnableGroup.Left := 10;
cbEnableGroup.Top := 5;
cbEnableGroup.OnClick := OnCheckBoxClicked;
gbClient := TGroupBox.Create(Self);
gbClient.Parent := Self;
for I := ControlCount - 1 downto 0 do
if not IsInnerControl(Controls[I]) then
Controls[I].Parent := gbClient;
ProcessResize;
end;
-
Спасибо большое!!!
|