Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как очистить компонент от компонентов. / 15 сообщений из 15, страница 1 из 1
06.03.2019, 22:24
    #39783266
FIL23
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
Добрых суток,

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

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

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

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



Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
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;



Но вот беда при создании эти же компонент возникает исключение (а иногда нет. как звезды сойдутся).
Код: pascal
1.
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.
...
Рейтинг: 0 / 0
06.03.2019, 23:16
    #39783282
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
авторА теперь вопрос как грамматно удалить компоненты?
Самому удалять ничего не нужно. Удаление - забота владельца.
...
Рейтинг: 0 / 0
07.03.2019, 02:35
    #39783298
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
makhaonавторА теперь вопрос как грамматно удалить компоненты?
Самому удалять ничего не нужно. Удаление - забота владельца.Ну, он же хочет вручную, не удаляя владельца.
Только не удаляет, а сразу освобождает. А надо сначала удалить из списка (Delete или Remove), а потом только можно освобождать, иначе будет каша.
Если не ошибаюсь)
...
Рейтинг: 0 / 0
07.03.2019, 06:38
    #39783309
ain-2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
FIL23
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
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;




Код: pascal
1.
2.
3.
4.
5.
6.
procedure ClearFormByObjects(perForm: TControl);
var i:integer;
begin
  for i:=perForm.ControlCount-1 downto 0 do 
    perForm.Controls[i].Free;
end;
...
Рейтинг: 0 / 0
07.03.2019, 11:32
    #39783437
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
FIL23,

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

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

Техническая деталь: например, в WParam запихав integer(Self), передадим указатель
...
Рейтинг: 0 / 0
07.03.2019, 11:44
    #39783454
Gator
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
Кроик Семён,

Только не родителю, а владельцу
...
Рейтинг: 0 / 0
07.03.2019, 11:50
    #39783462
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
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;
...
Рейтинг: 0 / 0
07.03.2019, 11:52
    #39783465
L_argo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
ain-2,
Free может быть недостаточно. Еще нужно занулить.
...
Рейтинг: 0 / 0
07.03.2019, 12:05
    #39783474
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
YuRockТолько не удаляет, а сразу освобождает. А надо сначала удалить из списка (Delete или Remove), а потом только можно освобождать, иначе будет каша.

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

FIL23,


FIL23
Код: pascal
1.
2.
  perObject:=perForm.Components[i];
  FreeAndNil(perObject);



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


или
Код: pascal
1.
  perForm.Components[i].Free;



Но вообще, компонент-владелец сам удаляет своих детей при смерти.
Посмотри исходники TComponent в районе удаления.
...
Рейтинг: 0 / 0
07.03.2019, 12:28
    #39783486
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
L_argoain-2,
Free может быть недостаточно. Еще нужно занулить.

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

ЗАЧЕМ ???
...
Рейтинг: 0 / 0
07.03.2019, 12:29
    #39783488
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
Кроик СемёнЯ бы сделал так: через PostMessage (а не SendMessage, это важно) отправил бы родительскому объекту

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

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

А если дочерний объект уже в процессе удаления, уже в деструкторе или рядышком ?
...
Рейтинг: 0 / 0
07.03.2019, 12:35
    #39783492
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
YuRockНу, он же хочет вручную, не удаляя владельца.

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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
destructor TComponent.Destroy;
begin
  Destroying;
  RemoveFreeNotifications;
  DestroyComponents;
  if FOwner <> nil then FOwner.RemoveComponent(Self);
  FObservers.Free;
  inherited Destroy;
end;



...но можно и руками
...
Рейтинг: 0 / 0
07.03.2019, 14:48
    #39783581
V.Borzov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
FIL23,

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

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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
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;


:))
...
Рейтинг: 0 / 0
07.03.2019, 15:33
    #39783611
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
V.Borzov,

ЕМНИП не так.

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

Т.е. кто первый удаляется - Owner или Parent - тот Control и убьёт.
...
Рейтинг: 0 / 0
07.03.2019, 15:55
    #39783631
V.Borzov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как очистить компонент от компонентов.
Arioch,
Блин, верно. Второй абзац у меня - полный бред.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как очистить компонент от компонентов. / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]