Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.10.21;
Скачать: [xml.tar.bz2];

Вниз

Незакрываються динамически созданные 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.041 c
2-1190796642
F@T@L_Err0r
2007-09-26 12:50
2007.10.21
TColor


2-1191009199
vasIZmax
2007-09-28 23:53
2007.10.21
Вот как можно ускорить программу?


15-1190382560
мастерПакость
2007-09-21 17:49
2007.10.21
проблемы с HTML


2-1190878591
fff
2007-09-27 11:36
2007.10.21
курсор


15-1190091413
Kolan
2007-09-18 08:56
2007.10.21
Что-то я думаю, Gero пропал, а у меня есть DMClient RC1, может&amp;#133





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский