Как сделать Free родителю

Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду

Аватара пользователя
Игорь Акопян
Сообщения: 1440
Зарегистрирован: 13 окт 2004, 17:11
Откуда: СПБ
Контактная информация:

Код: Выделить всё

When you call Free for a component, it calls Free for all components that it owns, that is, all components in its component list.
Т.о. если компонент был создан к примеру так:

Код: Выделить всё

procedure TMyButton.Click(Sender: TObject);
begin
  with TBevel.Create(MyPanel) do
  begin
    ...
  end;
end;
то экземпляр класса TBevel добавляется в коллекцию Components объекта MyPanel, и при вызове MyPanel.Free будет корректно убит.

Если же код такой:

Код: Выделить всё

procedure TMyButton.Click(Sender: TObject);
begin
  with TBevel.Create(nil) do
  begin
    ...
  end;
end;
Тады освобождать придётся вручную
Blood_Magic
Сообщения: 273
Зарегистрирован: 30 июн 2005, 14:53

создаю:

Код: Выделить всё

      
Result:=TPanel.Create(pnButton);
      With Result do
        begin
          Name:='BrowserButton'+IntToStr(pnButton.ComponentCount);
          Parent:=pnButton;
          Caption:=ButtonCaptions[I];
          BevelOuter:=bvNone;
          Color:=$DEDEDE;
          Top:=0;
          Height:=ButtonHeight;
          Width:=MinButtonWidth;
          ShowHint:=True;
          PopupMenu:=ButtonPopupMenu;
          OnMouseDown:=BrowserButtonMouseDown;
          Tag:=pnButton.ComponentCount;
        end;
      sp:=TShape.Create(Result);
      With sp do
        begin
          Name:='ShapeBrowserButton'+IntToStr(pnButton.ComponentCount);
          Parent:=Result;
          Brush.Style:=bsClear;
          Align:=alClient;
        end;

      If pnButton.ComponentCount>1 then
        begin
          im:=TImage.Create(Result);
          With im do
            begin
              Name:='imCloseButtonBrowserButton'+IntToStr(pnButton.ComponentCount);
              Parent:=Result;
              Transparent:=True;
              imCloseButtons.GetBitmap(0,im.Picture.Bitmap);
              AutoSize:=True;
              Left:=sp.Width-Width-Delta-1;
              Top:=(sp.Height-Height) shr 1;
              Anchors:=[akTop,akRight];
              OnMouseClick:=imCloseButtonClick;
             end;
        end;
Убиваю:

Код: Выделить всё

//Обрабботка нажатия на Image
procedure Tfm.imCloseButtonClick(Sender: TObject);
begin
  TImage(Sender).Parent.Free;
end;<<------ Ошибка после выполнения этой строки
В результате ошибка при выходе из процедуры, сама строка TImage(Sender).Parent.Free; выполняется нормально, причем все убивается хорошо.
Аватара пользователя
Игорь Акопян
Сообщения: 1440
Зарегистрирован: 13 окт 2004, 17:11
Откуда: СПБ
Контактная информация:

блин... вот она лень-матушка... до конца то я не дочитал... сорри
Warning: Never explicitly free a component within one of its own event handlers or free a component from the event handler of a component it owns or contains. For example, don’t free a button in its OnClick event handler or free the form that owns the button from the button's OnClick event.
Изображение
Blood_Magic
Сообщения: 273
Зарегистрирован: 30 июн 2005, 14:53

кто знает что делать?
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Попробуй так:

Код: Выделить всё

  PostMessage((Sender as TImage).Parent.Handle, WM_CLOSE, 0, 0);
Blood_Magic
Сообщения: 273
Зарегистрирован: 30 июн 2005, 14:53

Eugie писал(а):Попробуй так:

Код: Выделить всё

  PostMessage&#40][/quote]

Мне надо именно уничтожить. То что Вы написали это (Sender as TImage).Parent.Visible:=Flase;
Eugie
Сообщения: 708
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

Тогда такой вариант:

Код: Выделить всё

const WM_MYDESTROYPANEL = WM_USER + $100;

procedure TForm1.Image1Click(Sender: TObject);
begin
  PostMessage(Self.Handle, WM_MYDESTROYPANEL, 0, 0);
end;

procedure TForm1.WndProc(var Message: TMessage); // ! override !
begin
  if WM_MYDESTROYPANEL = Message.Msg then
    Image1.Parent.Free
  else
    inherited;
end;
Суть в том, чтобы развести по времени запрос на удаление и само уничтожение родительского контрола, т.е. вынести из обработчика Image1Click() - там некорректно.
Blood_Magic
Сообщения: 273
Зарегистрирован: 30 июн 2005, 14:53

уряяяяяяяяяяяя! спасибо что натолкнул на мысль! это проще делается но смысл тот же:

Код: Выделить всё

const
  WM_DestroyPanelButton = WM_USER + $200;
....................
  private
    procedure DestroyPanelButton(var Msg: TMessage); message WM_DestroyPanelButton;
.....................

procedure Tfm.DestroyPanelButton(var Msg: TMessage);
begin
  Image1.Parent.Free;
end;

 
в этом случаи никакого override не надо и inherited не надо
Ответить