Конференция "Компоненты" » Событие вставки в панель дочернего компонента [D7, WinXP]
 
  • Olegz77 (21.11.07 19:03) [0]
    Пишу компонент-контейнер на основе TWinControl. В нем имеется другой контейнер (допустим - TPanel или TGroupBox), который занимает не всю его площадь. Как сделать так чтобы при вставке в мой компонент других контролов (с палитры Delphi в Design time), вставляемый компонент вставлялся бы не в TWinControl, а в его дочерний TPanel? Как я понимаю надо перехватывать событие вставки в Design time и вместо Parent := Self делать Parent := Self.Panel. Есть ли такое событие?
  • DimaBr © (22.11.07 08:40) [1]
    смотрим соседний топик
    http://pda.delphimaster.net/?id=1195559871&n=12
  • Olegz77 (22.11.07 14:09) [2]

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

    { TCMLGroupPanel }

    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.

  • DimaBr © (22.11.07 14:20) [3]
    Вот тут,
    CreateWnd -> Resize -> ProcessResize а сонтролы ещё не созданы


    procedure TCMLGroupPanel.ProcessResize;
    begin
    if not Assigned(gbClient) then Exit;
    gbClient.SetBounds(0, 10, Width, Height - 10);
    gbClient.SendToBack;
    end;

  • Olegz77 (22.11.07 14:51) [4]
    Создал тестовый проект. Вставил в компонент кнопку, сохранил. В dfm файле все правильно вроде, а когда снова открываешь проект не может создать форму (List index is out of bounds (2)). Еще вопрос: в GetChildren надо вызывать inherited ?
  • DimaBr © (22.11.07 15:13) [5]
    нет, поскольку мы сами указываем какий компоненты сохранять
  • Olegz77 (22.11.07 18:52) [6]
    Не пойму где все же ошибка. Не хочет загружаться из dfm. Пишет list index is out of bounds. Где то в цикле по ControlCount что-ли ошибка с индексом? Сорри за навязчивость
  • DimaBr © (23.11.07 08:42) [7]
    Тестирование компонента я вижу в таком ракурсе:
    1. Кинте компонент на форму
    2. Киньте на компонент кнопку
    3. перейдите в просмотр DFM (Alt + F12)
      (если всё в DFM впорядке то дальше)
    4. Установите брейкпоин в конструктор
    5. запустите приложение
    6. После остановки давим F8 до возникновения ошибки и локализуем её
  • DimaBr © (23.11.07 09:08) [8]
    перенесите код из 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;

  • Olegz77 (24.11.07 20:57) [9]
    Спасибо большое!!!
 
Конференция "Компоненты" » Событие вставки в панель дочернего компонента [D7, WinXP]
Есть новые Нет новых   [134430   +0][b:0][p:0.002]