Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.21;
Скачать: CL | DM;

Вниз

Незакрываються динамически созданные Panel   Найти похожие ветки 

 
OlegM   (2007-08-07 14:37) [0]

Привет всем
Есть форма, на ней динамически создаются TPanel, и на каждой из них TButton, в которую на событие OnClick вешаеться код

(Form1.Components[i] as TPanel).Free;

Но иногда все работает, иногда выдает Abstract Error иногда выдает
Ассес вилатион. Подскажите как правильно закрывать динамически созданные компоненты.


 
{RASkov} ©   (2007-08-07 14:45) [1]

> [0] OlegM   (07.08.07 14:37)

if Form1.Components[i] is TPanel then TPanel(Form1.Components[i]).Free;


 
{RASkov} ©   (2007-08-07 14:50) [2]

> [1] {RASkov} ©   (07.08.07 14:45)

Только вот так более логичнее:
if Components[i] is TPanel then TPanel(Components[i]).Free;

Это уничтожет все панели на форме - и динамически созданные и статически, что впрочем и в [0] и [1]...
Только в [0] мы пытаемся любой компонент привести к TPanel и вызвать Free
Так же i - не должен равняться или быть больше ComponentCount....


 
Сергей М. ©   (2007-08-07 14:52) [3]


> {RASkov} ©   (07.08.07 14:45) [1]


Накой ляд здесь проверка и приведение типа ?

Free - он и в Африке Free)


> OlegM   (07.08.07 14:37)


> как правильно закрывать динамически созданные компоненты


Точно так же как и созданные "статически" - методами Free, Destroy.

Только не "закрывать", а разрушать.


 
{RASkov} ©   (2007-08-07 14:54) [4]

> then TPanel(Components[i]).Free;

Впрочем и приведение в данном случае не обязательно...
Достаточно:
for i:=0 to ComponrntCount-1 do
 if Components[i] is TPanel then Components[i].Free;


 
{RASkov} ©   (2007-08-07 14:56) [5]

> [3] Сергей М. ©   (07.08.07 14:52)

Угу...

Только я не совсем понял, что должно быть по нажатию кнопки, которая на панеле.....(


 
{RASkov} ©   (2007-08-07 15:05) [6]

> [0] OlegM   (07.08.07 14:37)

Ты более подробнее задавай вопрос, а то получается из [0]:
Мы создали несколько панелей с кнопками, а потом всего лишь одним нажатием на одну любую кнопку убили все что было на форме или только все панели в том числе и статически созданные....
В Components находяться все компоненты формы
а в Controls находятся все контролы принадлежащие тому контролу которому принадлежит этот самый список Controls
Т.е.
Controls или Form1.Controls содержит все контролы, в том числе и динамич созданные панели, если родитель этих панелей есть сама форма, а вот
Panel.Controls содержит контролы, которые находятся на панеле Panel, в том числе и те самые кнопки....


 
MetalFan ©   (2007-08-07 17:49) [7]

...OnButtonClick( Sender: TObject );
begin
if Sender is TButton then
  if TButton(Sender).Parent is TPanel then
     TButton(Sender).Parent.Free;
end;

не очень хороший конечно вариант))) предлагаю доработать мозгами


 
Юрий Зотов ©   (2007-08-07 21:08) [8]

О чем речь идет? Какие-такие FindComponent? Не о том говорим.

Обработчик щелка по кнопке уничтожает панель, на которой лежит ЭТА САМАЯ кнопка. Вместе с панелью уничтожается и сама кнопка. А обработка  события уже уничтоженной кнопки еще не завершилась.

Что будет? Access Violation будет. Это и есть корень зла, а вовсе никакие не FindComponent.

Решение: обработчик кнопки через PostMessage шлет форме сообщение, передавая в его параметрах Sender (то есть, кнопку). Получив сообщение, форма уничтожает Parent"а этой кнопки.

И никаких FindComponent.


 
Loginov Dmitry ©   (2007-08-07 21:42) [9]

> Но иногда все работает, иногда выдает Abstract Error иногда
> выдает


Попробуй после Free сделать Abort


 
OlegM   (2007-08-08 07:07) [10]

Щас опишу задачу поподробнее.
нужно на экран выдавать типа сообщения, используя для этого TPanel, различные Showmessage и child формы не подходят, уже их пробовал.
Т.е выдавать эти сообщения но,  и закрывать эти сообщения нужно кнопкой на этих панелях, но закрывать только ту панел на которой нажата кнопка и причем закрывать в такой последовательности, 1,2,3,4 т.е в какой последовательности выдались эти сообщения в такой их и закрывать и не давать закрывать например 2,1,3,4

в свойстве Tag храниться какая панелька в какой последователности была открыта.

код такой и вот на нем все и ломится

procedure TForm1.BtnClose(Sender: TObject);
var
 i,j,min:integer;
begin
 for i:=0 to Form1.ComponentCount-1 do
 begin
   if Form1.Components[i].ClassType = TPanel then
   begin
     min:=Form1.Components[i].Tag;
     for j:=0 to Form1.ComponentCount-1 do
     begin
       if Form1.Components[j].ClassType = TPanel then
       begin
         if Form1.Components[j].Tag <= min then min:=Form1.Components[j].Tag;
       end;
     end;
   end;
 end;

 for i:=0 to Form1.ComponentCount-1 do
 begin
   if Form1.Components[i].ClassType = TPanel then
   begin
     if Form1.Components[i].Tag = min then
     begin
       (Form1.Components[i] as TPanel).Free;
       Exit;
     end;
   end;
 end;
end;


хотя тотже самый код работает когда я вешаю попуп меню на панели. И работает как надо.
PS Это типа не я мозг парю это начальство дало вот такое задание в точности.


 
MBo ©   (2007-08-08 07:55) [11]

в [8] все уже написано.


 
OlegM   (2007-08-08 08:58) [12]

> Решение: обработчик кнопки через PostMessage шлет форме сообщение
А какое сообщение ?
WM_DESTROY неробит


 
MBo ©   (2007-08-08 09:07) [13]

>А какое сообщение ?
пользовательское, например
WM_MY_FREE = WM_USER + 666;


 
OlegM   (2007-08-08 09:21) [14]

Что ? )


 
{RASkov} ©   (2007-08-08 09:27) [15]

> [14] OlegM   (08.08.07 09:21)

Нечто примерно так:

const DEL_PAN = WM_USER+666; // :) Можно и +1
....
procedure DelPanel(var mes: TMessage); message DEL_PAN;

procedure TForm.DelPanel(var mes: TMessage);
begin
 TPanel(WParam).Free;
end;

procedure TForm.ButtonClick();
begin
 PostMessage(Handle, DEL_PAN, Integer((Sender as TWInControl).Parent), 0);
end;


 
OlegM   (2007-08-09 08:35) [16]

Что то я совсем спекся, ругаетцо на TPanel(WParam).Free;
[Error] Unit1.pas(49): "(" expected but ")" found


 
sergeyst ©   (2007-08-09 09:36) [17]


> Обработчик щелка по кнопке уничтожает панель, на которой
> лежит ЭТА САМАЯ кнопка. Вместе с панелью уничтожается и
> сама кнопка. А обработка  события уже уничтоженной кнопки
> еще не завершилась.

Хм.. а:
TForm1.Button1Click(Sender: TObject);
begin
 Free;
end;
никаких AV. И в чем разница?


 
Юрий Зотов ©   (2007-08-09 09:59) [18]

> OlegM   (09.08.07 08:35) [16]
TPanel(mes.WParam).Free;

Олег, Вы бы посмотрели все же в справке, что такое сообщения...

> sergeyst ©   (09.08.07 09:36) [17]

Если в цепочке обработки события не происходит обращения к полям уничтоженного объекта (и тех, которые уничтожаются вместе с ним), то AV, естественно, не будет. Если происходит - будет. Зависит это от и кода VCL, и от прикладного кода  (мы же не знаем, что там еще и на какие события навешено). В любом случае правильным будет отложенное удаление (через PostMessage), которое гарантирует, что перед удалением обработка события будет завершена. Для примера посмотрите метод Release формы (его код и описание в справке).

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


 
sergeyst ©   (2007-08-09 10:19) [19]


> Юрий Зотов ©   (09.08.07 09:59) [18]

Ага, спасибо, ясно.


 
OlegM   (2007-08-09 11:38) [20]

> Юрий Зотов
Дак конешно все это читал но очень давно. последние несколько лет только с базами.

Но что то опять я туплю короче.

это объявлено в глобальных
const
 DEL_PAN = WM_USER+1;

Так описано процедурка
procedure TForm1.DelPanel(var mes: TMessage);
begin
 TPanel(mes.WParam).Free;
end;

Такое я посылаю
PostMessage((Sender as TButton).Handle, DEL_PAN, Integer((Sender as TWInControl).Parent), 0);

Но ничего не происходит


 
MetalFan ©   (2007-08-09 11:47) [21]

в интерфейсной части класса укажи
> procedure DelPanel(var mes: TMessage); message DEL_PAN;


 
Юрий Зотов ©   (2007-08-09 11:56) [22]

PostMessage((Sender as TButton).Handle, ...

Вы сообщение КОМУ должны послать? Тому, кто его примет, поймет и обработает. Все это делает ФОРМА (потому что обработчик сообщения - это метод ФОРМЫ). А сообщение Вы почему-то посылаете КНОПКЕ.

Выкиньте подчеркнутый кусок. Хэндл ФОРМЫ, а не КНОПКИ надо указывать.


 
OlegM   (2007-08-09 12:20) [23]

> Юрий Зотов , сенк.

Только не бейте )


type
 TForm1 = class(TForm)
   ...
   procedure DelPanel(var mes: TMessage); message DEL_PAN ;
 private
   { Private declarations }
 public
   { Public declarations }
 end;

const DEL_PAN = WM_USER+1;


Куда эту константу вписать ???


 
Юрий Зотов ©   (2007-08-09 12:24) [24]

> OlegM   (09.08.07 12:20) [23]

Перед словом type. Только лучше напишите WM_USER+100.


 
OlegM   (2007-08-09 12:29) [25]

Ой люди спасибо огромное за терпение и помощь, все работает )



Страницы: 1 вся ветка

Текущий архив: 2007.10.21;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.022 c
6-1171790033
santey
2007-02-18 12:13
2007.10.21
Как установить IP адрес


1-1186500273
Лёля
2007-08-07 19:24
2007.10.21
Сложная "шапка" в DBGrid


8-1166580641
>>DEATH<<
2006-12-20 05:10
2007.10.21
палитра в bmp


3-1176821654
Kostafey
2007-04-17 18:54
2007.10.21
Обновление значений полей взятых из присоединенной таблицы


6-1171358206
SergGG
2007-02-13 12:16
2007.10.21
MailSlot поймать реального клиента