Уничтожение TFrame

Доброго всем дня !Никак не соображу в чем приколСоздаю Frame (File -> New Frame)Показываю его на основной форме
var fr: TFrame2;begin  fr:=TFrame2.Create(Form1);  with fr do begin    Parent:=Form1;    Top:=100;    Left:=100;    Visible:=true;  end;
Все замечательноНа фрейv вешаю TButton с обработчиком
procedure TFrame2.Button1Click(Sender: TObject);begin  Free;end;
Опять же все красиво, фрейм разрушается без последствийДобавляю TSpeedButton с таким же обработчиком, и вуаля - вылетает AV " EAccessVialation .... Access Violation at address 00010017.Write of address 00008100"В интернете по данной теме ничего не нашел.Может кто прольет свет на данный вопрос ?Delphi 5, Windows XP SP2Delphi 5
7 ответов

Кнопка фрейма ведь  тоже будет уничтожена, а мы в обработчике ее события.как-то так


ЗыСтранно, но ведь для TButton я никакой специальной обработки по уничтожению не пишу, и при этом все нормально


2 kamiСпасибо за ссылкуТеперь все работает замечательноОбработчик для кнопки
procedure TFrame1.SpeedButton1Click(Sender: TObject);begin  PostMessage(Handle, WM_USER, integer(Sender), 0);end;
Объявляем приемщик сообщения:
TFrame1 = class(TFrame)....  private    procedure DeleteFrame(var Message:TMessage); message WM_USER;
procedure TFrame3.DeleteFrame(var Message:TMessage);begin  // Уничтожаем кнопку  TObject(Message.Wparam).Free;  // И уже потом уничтожаем фрейм  Free;end;


Странно, но ведь для TButton я никакой специальной обработки по уничтожению не пишу, и при этом все нормально
Из факта "один раз проскочил" не надо делать вывод "всегда так делать"...Посмотрите ссылки:1. http://forum.vingrad.ru/topic-301514.html(поиск по фразе "Купите красивую рамочку" или "Запрещается уничтожать объекты")2. http://www.delphikingdom.com/asp/answer.asp?IDAnswer=76938(моё сообщение и ссылка в нём)


Странно, но ведь для TButton я никакой специальной обработки по уничтожению не пишу, и при этом все нормально
Фраза, которую можно понимать по-разному...Если интерпретировать её как "я же кнопку не удаляю сам, как же она удалится?", то ответ будет таков:При своём уничтожении компонент удаляет другие компоненты, для которых он является:  а) Владельцем (Owner'ом)  б) Родителем (Parent'ом)Владелец - это тот, кто ответственен за уничтожение тех, кем он владеет при своём уничтожении. Владелец назначается при вызове конструктора, например: TButton.Create(Self).Всем компонентам, расположенным на форме или фрейме (независимо от того, непосредственно или на других элементах, например, панелях), Owner'ом назначается именно эта форма или фрейм. Именно поэтому при уничтожении формы всё, что на ней расположено, будет уничтожено автоматически (в том числе невизуальные компоненты вроде датасетов).Родитель - это тот, на чём лежит контрол визуально, например, панель, на которой лежит кнопка. Панель при своём уничтожении будет также уничтожать кнопку, лежащую на ней.
procedure TFrame3.DeleteFrame(var Message:TMessage);begin  // Уничтожаем кнопку  TObject(Message.Wparam).Free;  // И уже потом уничтожаем фрейм  Free;end;
Здесь нет необходимости уничтожать кнопку самостоятельно. При своём уничтожении фрейм её уничтожит в любом случае.И ещё...Вы не уловили самого главного: зачем вообще нужен финт ушами с сообщением...А нужен он для того, чтобы уничтожением объекта занимался кто-то, кто не являетя обработчиком ни одного из уничтожаемых объектов и не вызывается из этих обработчиков. Это достигается тем, что в обработчике нажатия кнопки посылается сообщение тому, кто будет заниматься уничтожением, после чего происходит выход из обработчика. И вот только после этого кто-то внешний, кому было послано сообщение, начинает обработку сообщения и уничтожает тех, на кого ему показали. Таким образом, обработчик сообщения не должен быть обработчиком ни для фрейма, ни для кнопки. Сделайте его обработчиком для формы. И передавайте ссылку не на кнопку, а на фрейм.P.S. Загляните ещё раз по ссылке, приведённой kami - я там добавил комментарий, который вам может быть небезынтересен.


2 БелАморБольшое спасибо за подробное объяснениеПро "ответственных" за уничтожение объектов я знаю. При разрушениии обычной формы уничтожаются все компоненты принадлежащие ей.В том числе и кнопки, которые вызывают закрытие формы. При этом дополнительных телодвижений вроде как не требуется. Достаточно написать 
procedure TForm2.SpeedButton1Click(Sender: TObject);begin  Close;end;
Такого же мнения я был о фрейме. И често говоря был сильно удивлен, что нужны дополнительные финты.
Вы не уловили самого главного: зачем вообще нужен финт ушами с сообщением...А нужен он для того, чтобы уничтожением объекта занимался кто-то, кто не являетя обработчиком ни одного из уничтожаемых объектов и не вызывается из этих обработчиков....Сделайте его обработчиком для формы. И передавайте ссылку не на кнопку, а на фрейм.
Просто мне не хотелось загрязнять код главной формы обработкой уничтожения фреймов. Так как будто красивее получилось.Может я и не прав.
P.S. Загляните ещё раз по ссылке, приведённой kami - я там добавил комментарий, который вам может быть небезынтересен.
Ссылка очень полезная. Еще раз Огромное спасибо


При разрушениии обычной формы уничтожаются все компоненты принадлежащие ей.В том числе и кнопки, которые вызывают закрытие формы. При этом дополнительных телодвижений вроде как не требуется. Достаточно написать procedure TForm2.SpeedButton1Click(Sender: TObject);begin  Close;end;Такого же мнения я был о фрейме. И често говоря был сильно удивлен, что нужны дополнительные финты.
Close не уничтожает форму, а закрывает, т.е. делает её невидимой. Скрытую форму при желании можно опять показать (и там будут все те же данные, которые были перед закрытием). А уничтожается форма точно так-же, как и всё остальное - через вызов Free.И в отношении форм точно так-же сохраняется запрет на самоуничтожение из своего обработчика, только у форм есть метод Release, который может вызываться в обработчике и приводит к уничтожению формы не сразу, а после выхода из всех обработчиков. Косвенный способ вызова Release - в обработчике OnClose формы параметру Action, передаваемому по ссылке, присвоить значение caFree.