Отловить событие при добавлении дочерних

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Отловить событие при добавлении дочерних

Сообщение VirtUX » 22.04.2019 00:20:53

Задача: поймать и обработать добавляемый контрол в некоторый контейнер.
Например: есть форма. На форму программно добавляют контрол.
Вопрос: где и как можно получить этот добавляемый контрол, и выполнить при этом некоторые действия над ним?
Вопрос-дополнение, по типу P.S.:
У любого TWinControl есть метод: InsertControl(AControl: TControl); и InsertControl(AControl: TControl; Index: integer); virtual;. Ясное дело, что в потомке мы можем перекрыть этот метод. Но как повесить свой обработчик на это событие?
Например: разместим на форме свой компонент (TMyComponent). В нём опишем действия над контролом, который будет добавляться на форму программно. Как это действие привязать к событию: "добавление на форму некоторого компанента"?
P.P.S.: понимаю, что объяснил не слишком доходчиво. Готов разжевать проблему до любой степени, лишь бы решить задачу...
Спасибо!
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 865
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Отловить событие при добавлении дочерних

Сообщение iskander » 22.04.2019 07:02:59

Если я правильно понял, что требуется:
Код: Выделить всё
unit main;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls;


type
  TOnCtrlInsert = procedure(aSender: TObject; aControl: TControl) of object;

  TForm = class(Forms.TForm)
  private
    FOnCtrlInsert: TOnCtrlInsert;
  public
    procedure InsertControl(aControl: TControl; aIndex: Integer); override;
    property  OnControlInsert: TOnCtrlInsert read FOnCtrlInsert write FOnCtrlInsert;
  end;

  THelpComp = class(TComponent)
  public
    procedure ControlInserted(aSender: TObject; aControl: TControl);
  end;

  TfrmMain = class(TForm)
    btAdd: TButton;
    procedure btAddClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private

  public
    HelpComp: THelpComp;
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.lfm}

{ TfrmMain }

procedure TfrmMain.btAddClick(Sender: TObject);
var
  Pane: TPanel;
begin
  Pane := TPanel.Create(Self);
  Pane.Parent := Self;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  HelpComp := THelpComp.Create(Self);
  OnControlInsert := @HelpComp.ControlInserted;
end;

{ THelpComp }

procedure THelpComp.ControlInserted(aSender: TObject; aControl: TControl);
begin
  ShowMessage('Inserted control ' + aControl.ClassName);
end;

{ TForm }

procedure TForm.InsertControl(aControl: TControl; aIndex: Integer);
begin
  inherited InsertControl(aControl, aIndex);
  if Assigned(FOnCtrlInsert) and (Controls[aIndex] = aControl) then
    FOnCtrlInsert(Self, aControl);
end;

end. 

InsertIntercept.zip
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось iskander 22.04.2019 08:22:43, всего редактировалось 2 раз(а).
iskander
постоялец
 
Сообщения: 178
Зарегистрирован: 08.01.2012 18:43:34

Re: Отловить событие при добавлении дочерних

Сообщение sign » 22.04.2019 07:22:53

На моём примере, когда мне нужно поставить свой обработчик для мыши.
Код: Выделить всё
   
...
  procedure IconMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
...

procedure TDIcon.InitMouse;
begin
  OnMouseDown  := @IconMouseDown;
  OnMouseEnter := @IconMouseEnter;
  OnMouseLeave := @IconMouseLeave;
end;


procedure IconMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
sign
энтузиаст
 
Сообщения: 1091
Зарегистрирован: 30.08.2009 09:20:53

Re: Отловить событие при добавлении дочерних

Сообщение VirtUX » 22.04.2019 08:00:44

iskander писал(а):Если я правильно понял, что требуется

Вы наследуетесь от формы. Такой подход сейчас у меня тоже используется. Но это не удобно. Ищу способ типа такого:
- используется форма по умолчанию;
- на форму кидается самописный компонент на основе TComponent (TMyAnyComponent) в режиме дизайна формы;
- если на форме есть уже контролы, то в приватном поле у TMyAnyComponent создаем массив из нужных FArrControls: array of TControls; (тут нет проблем);
- если во время дизайна в будущем разработчик добавит еще один контрол на обычную форму, то нужно как-то узнать об этом событии, и при необходимости добавить этот контрол в массив TMyAnyComponent.FArrControls (вот тут я не могу сообразить - как?);
- если во время выполнения приложения на стандартную обычную форму программно будет добавлен новый контрол (TControl), то тоже при необходимости добавить его в массив TMyAnyComponent.FArrControls.
- так же требуется отследить удаление с формы контролов.

P.S. При этом TMyAnyComponent может быть добавленным и на TPanel или TFrame, - любой контейнер. И тогда он будет отслеживать только те контролы, которые добавляются/удаляются в этом контейнере.

Добавлено спустя 3 минуты 41 секунду:
sign писал(а):На моём примере, когда мне нужно поставить свой обработчик для мыши.

Вот если бы было у TWinControl свойство OnSetControl или OnSetControlParent, которые бы обрабатывались во время инсерта контрола в контейнер или когда этому контролу назначают парентом данный контейнер, - то и вопроса бы не возникало. Но может я что-то и пропустил по незнанию...
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 865
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Отловить событие при добавлении дочерних

Сообщение iskander » 22.04.2019 08:15:20

VirtUX писал(а):Но это не удобно

Почему? Это никак не мешает дизайнеру форм.
VirtUX писал(а):требуется отследить удаление с формы контролов

Ничто не мешает добавить такой же перехватчик для RemoveControl.
Последний раз редактировалось iskander 22.04.2019 08:40:00, всего редактировалось 1 раз.
iskander
постоялец
 
Сообщения: 178
Зарегистрирован: 08.01.2012 18:43:34

Re: Отловить событие при добавлении дочерних

Сообщение Лекс Айрин » 22.04.2019 08:37:21

iskander, видимо потому что придется делать для каждого окна свое добавление. А это сразу куча дублирующегося кода.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отловить событие при добавлении дочерних

Сообщение VirtUX » 22.04.2019 09:23:03

Лекс Айрин писал(а):iskander, видимо потому что придется делать для каждого окна свое добавление. А это сразу куча дублирующегося кода.

Да, совершенно верно. Хочу избавиться от этой постоянной вставки "костылей". Можно, конечно, влезть в исходник самого TWinControl и добавить туда необходимые OnSetControl или что-то наподобие. И если другого решения не найдется, то так и придется сделать. Но не хотелось бы... Может есть способ как-то повесить обработчик события на что-то, что выполняется до или после SetControl?
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 865
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Отловить событие при добавлении дочерних

Сообщение iskander » 22.04.2019 09:38:44

Хозяин-барин...
Если не трудно, отпишитесь, как получилось решить проблему.
iskander
постоялец
 
Сообщения: 178
Зарегистрирован: 08.01.2012 18:43:34

Re: Отловить событие при добавлении дочерних

Сообщение DedFrend » 24.04.2019 08:17:53

Как я понял речь идет о том, чтобы иметь централизованное место, где собирается информация о создании/удалении определенных компонентов. Мне кажется можно сделать чтобы при создании/удалении создавалось сообщение типа WM_USER+... а в центрохранилище организовать их обработку
DedFrend
новенький
 
Сообщения: 34
Зарегистрирован: 25.11.2018 12:21:50

Re: Отловить событие при добавлении дочерних

Сообщение VirtUX » 26.04.2019 15:50:03

Задача повесить обработчик на контейнер (TPanel, TForm, TGroupBox, etc), который обрабатывал бы добавление/удаление контрола в этом контейнере. При этом вешать на стандартные контейнеры, а не на переопределенные в наследниках. Сейчас мне приходится переопределять стандартные (TAnyPanel = class(TPanel), TAnyGroupBox = class(TGroupBox), etc) и в них реализовать необходимые свойства (property OnInsertControl, property OnRemoveControl), на которые я вешаю свои обработчики (pAnyPanel.OnInsertControl:= @OtherComponent.CheckInsertedControl;). Но было бы гораздо проще, если бы можно было отлавливать добавление/удаление в контейнере, без его переопределения в новый класс...
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 865
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Отловить событие при добавлении дочерних

Сообщение Лекс Айрин » 26.04.2019 18:17:35

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

Добавлено спустя 9 минут 45 секунд:
Попробуй посмотреть тут http://fegorsk.ru/index.php/studentam/d ... enty-formy
Это правда для Дельфи, но принцип должен быть одинаковым. А для проверки лежит он на контейнере или нет можно проверять свойство parent.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отловить событие при добавлении дочерних

Сообщение iskander » 26.04.2019 22:00:29

VirtUX писал(а):(TAnyPanel = class(TPanel), TAnyGroupBox = class(TGroupBox), etc)

??? И создаете их все в runtime ?
Похоже вы не смотрели внимательно мой пример, этот фокус
Код: Выделить всё
  TForm = class(Forms.TForm)

позволяет вполне себе формошлепствовать и редактировать свойства компонентов в инспекторе объектов без перекомпиляции LCL.
В аттаче пример, который делает примерно то, что вы описали.
Без особого изящества, при необходимости допилите напильником.
Прежде чем открывать проект, нужно установить в IDE компонент из папочки wcobserver.
observe_containers.zip
У вас нет необходимых прав для просмотра вложений в этом сообщении.
iskander
постоялец
 
Сообщения: 178
Зарегистрирован: 08.01.2012 18:43:34

Re: Отловить событие при добавлении дочерних

Сообщение VirtUX » 27.04.2019 13:23:49

Лекс Айрин писал(а):есть же какое-то сообщение, которое вызывается при смене количества дочерних элементов

Вот знать бы - какое? Я перерыл довольно много, но так и не нашел. Возможно, не там искал, или не то искал. Поэтому и задал вопрос тут.
Лекс Айрин писал(а):Попробуй посмотреть тут

Это про простой перебор компонентов. И про управление списком оных.
iskander писал(а):создаете их все в runtime ?

Нет. Всё описанное выше относится ко времени дизайна (верстки) в среде Lazarus (ну ко времени Run тоже, как само разумеещееся). Мне нужно отловить событие, когда разработчик добавляет любой компонент (в действительности интересуют только контролы) на стандартный (имеющийся в списке компонент в Lazarus сразу после его установки) контейнер (типа TPanel, TForm, TFrame, etc). Вот и всё.
Сейчас приходится перед началом разработки приложения устанавливать дополнительный пакет с переопределенными мной контейнерами. Так сказать - врапперы на стандартные TPanel, TGroupBox и т.п. Ищу способ, чтобы не делать этого, и получить возможность отлавливать изменения с дочерними у обычных, стандартных контейнеров, которые идут по умолчанию в среде разработки Lazarus.

Добавлено спустя 2 минуты 47 секунд:
Я понимаю, что можно подправить исходники классов и пересобрать Lazarus. Но это слишком радикальный и не совсем удобный способ
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 865
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Отловить событие при добавлении дочерних

Сообщение Снег Север » 27.04.2019 13:27:12

VirtUX писал(а): получить возможность отлавливать изменения с дочерними у обычных, стандартных контейнеров,

Такого нет. Попробуйте хелперы, что ли.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2060
Зарегистрирован: 27.11.2007 16:14:47

Re: Отловить событие при добавлении дочерних

Сообщение iskander » 27.04.2019 13:36:07

Снег Север писал(а):Попробуйте хелперы, что ли.

Полагаю, хелперы здесь не помогут.
VirtUX писал(а):устанавливать дополнительный пакет с переопределенными мной контейнерами

VirtUX, а вы в пример заглядывали?
iskander
постоялец
 
Сообщения: 178
Зарегистрирован: 08.01.2012 18:43:34

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot], ZuluSpirit и гости: 4

Рейтинг@Mail.ru