Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Как очистить компонент от компонентов.  [new]
FIL23
Member

Откуда:
Сообщений: 396
Добрых суток,

Создаю динамически компоненты.

Владелец, а так же родитель компонентов является тот компонент в котором был создан компонент.

Т.е. получается дерево что ли.

А теперь вопрос как грамматно удалить компоненты?
Делаю так. Передаю Родительскую компоненту на которой находятся все компоненты которые подлежат уничтожению. И по очереди их зануляю.



procedure ClearFormByObjects(perForm:TComponent);
var
i:integer;
perObject:TObject;
begin
for i:=perForm.ComponentCount-1 downto 0 do
  begin
  perObject:=perForm.Components[i];
  FreeAndNil(perObject);
  end ;
end;


Но вот беда при создании эти же компонент возникает исключение (а иногда нет. как звезды сойдутся).
Project alladmin.exe raised exception class EAccessViolation with message 'Access violation at address 004037D6 in module 'alladmin.exe'. Read of address F685D88B'. Process stopped. Use Step or Run to continue.
6 мар 19, 22:24    [21826805]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3189
автор
А теперь вопрос как грамматно удалить компоненты?

Самому удалять ничего не нужно. Удаление - забота владельца.
6 мар 19, 23:16    [21826828]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3898
makhaon
автор
А теперь вопрос как грамматно удалить компоненты?

Самому удалять ничего не нужно. Удаление - забота владельца.
Ну, он же хочет вручную, не удаляя владельца.
Только не удаляет, а сразу освобождает. А надо сначала удалить из списка (Delete или Remove), а потом только можно освобождать, иначе будет каша.
Если не ошибаюсь)
7 мар 19, 02:35    [21826879]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
ain-2
Member

Откуда:
Сообщений: 659
FIL23

procedure ClearFormByObjects(perForm:TComponent);
var
i:integer;
perObject:TObject;
begin
for i:=perForm.ComponentCount-1 downto 0 do
  begin
  perObject:=perForm.Components[i];
  FreeAndNil(perObject);
  end ;
end;



procedure ClearFormByObjects(perForm: TControl);
var i:integer;
begin
  for i:=perForm.ControlCount-1 downto 0 do 
    perForm.Controls[i].Free;
end;
7 мар 19, 06:38    [21826904]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6403
FIL23,

если я правильно понял вопрос, то некий объект решает, что ему пора быть уничтоженным? Верно?

Я бы сделал так: через PostMessage (а не SendMessage, это важно) отправил бы родительскому объекту сигнал, что меня дочернего объекта пора уничтожить. Таким образом через PostMessage разрывается CallStack и объект возможно будет кошерно удалить.

Техническая деталь: например, в WParam запихав integer(Self), передадим указатель
7 мар 19, 11:32    [21827097]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Gator
Member

Откуда: Москва
Сообщений: 14212
Кроик Семён,

Только не родителю, а владельцу
7 мар 19, 11:44    [21827126]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6403
const
   WM_DEL_CHILD_OBJ  = WM_USER + 1;

   
type
   TParentComponent = class(...)
   private
      procedure WMDelChildObj(var Message: TMessage); message WM_DEL_CHILD_OBJ;
   
   end;
   

procedure TParentComponent.WMDelChildObj(var Message: TMessage);
var
   Obj : TObject;
begin
   Obj := TObject(Message.WParam);

   ...
   FreeAndNil(Obj);   
end;  
//------------------------------------------------------------------------------



...
...
procedure TChildComponent.Remove();
begin
   PostMessage(FOwner.Handle, WM_DEL_CHILD_OBJ, integer(Self), 0);
end;
7 мар 19, 11:50    [21827138]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
L_argo
Member

Откуда:
Сообщений: 741
ain-2,
Free может быть недостаточно. Еще нужно занулить.
7 мар 19, 11:52    [21827141]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Arioch
Member

Откуда:
Сообщений: 10807
YuRock
Только не удаляет, а сразу освобождает. А надо сначала удалить из списка (Delete или Remove), а потом только можно освобождать, иначе будет каша.


нет, если "владелец" - в смысле стандартного механизма TComponent.Owner - то они автоматически обмениваются Notification при удалении

FIL23,


FIL23
  perObject:=perForm.Components[i];
  FreeAndNil(perObject);


Мрак. Зачем так сложно?
  perForm.Components[i].Destroy;

или
  perForm.Components[i].Free;


Но вообще, компонент-владелец сам удаляет своих детей при смерти.
Посмотри исходники TComponent в районе удаления.
7 мар 19, 12:05    [21827162]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Arioch
Member

Откуда:
Сообщений: 10807
L_argo
ain-2,
Free может быть недостаточно. Еще нужно занулить.


Занулить локальную переменную? Которая уже в следующем шаге того же самого цикла будет перезаписана?

ЗАЧЕМ ???
7 мар 19, 12:28    [21827184]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Arioch
Member

Откуда:
Сообщений: 10807
Кроик Семён
Я бы сделал так: через PostMessage (а не SendMessage, это важно) отправил бы родительскому объекту


а если у родительского объекта нет GDI Handle ? вот вообще нет, как у TLabel ? Или в принипе может быть, но пока не создан ?

Кроик Семён
что меня дочернего объекта пора уничтожить.


А если дочерний объект уже в процессе удаления, уже в деструкторе или рядышком ?
7 мар 19, 12:29    [21827187]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Arioch
Member

Откуда:
Сообщений: 10807
YuRock
Ну, он же хочет вручную, не удаляя владельца.


Внезапно, страшноужасное:

destructor TComponent.Destroy;
begin
  Destroying;
  RemoveFreeNotifications;
  DestroyComponents;
  if FOwner <> nil then FOwner.RemoveComponent(Self);
  FObservers.Free;
  inherited Destroy;
end;


...но можно и руками
7 мар 19, 12:35    [21827194]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
V.Borzov
Member

Откуда: Саратов
Сообщений: 269
FIL23,

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

И не надо путать их с контролами, это совсем другая история, ибо контрол, лежащий на TWinControl, может ему и не принадлежать. Положенный куда-нибудь Control будет удален при удалении своего потомка, а не объекта своего размещения. Можно, например, кидать на форму другую форму со всем её набранным в дизайнере функционалом и набором своих контролов. И вот если родителем этой формы будет наша парент-форма или её контрол, то можно не париться с её удалением, а если родителем формы является nil или Application, то удалить надо вручную.

+
procedure TForm6.Button1Click(Sender: TObject);
var i :integer;
begin
  for i := 1 to 1000 do  TLabel.Create(Button1);
  showmessage(inttostr(Button1.ComponentCount));
  showmessage(inttostr(Button1.ControlCount));

  //for i := Button1.ComponentCount-1 downto 0 do Button1.components[i].free;
  //while Button1.ComponentCount>0 do Button1.Components[0].free;
  With Button1 do while ComponentCount>0 do Components[ComponentCount-1].free;
  showmessage(inttostr(Button1.ComponentCount));
  showmessage(inttostr(Button1.ControlCount));
end;

:))
7 мар 19, 14:48    [21827378]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
Arioch
Member

Откуда:
Сообщений: 10807
V.Borzov,

ЕМНИП не так.

Поскольку TWinControl завязаны на GDI-объекты, то при удалении VCL-Parent'a (который в терминах GDI и окажется владельцем) они удалятся тоже.

Т.е. кто первый удаляется - Owner или Parent - тот Control и убьёт.
7 мар 19, 15:33    [21827457]     Ответить | Цитировать Сообщить модератору
 Re: Как очистить компонент от компонентов.  [new]
V.Borzov
Member

Откуда: Саратов
Сообщений: 269
Arioch,
Блин, верно. Второй абзац у меня - полный бред.
7 мар 19, 15:55    [21827491]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить