![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Незакрываються динамически созданные Panel [Win2k, WinXP]
OlegM © (2007-08-07 14:37:00)Привет всем
Есть форма, на ней динамически создаются TPanel, и на каждой из них TButton, в которую на событие OnClick вешаеться код
(Form1.Components[i] as TPanel).Free;
Но иногда все работает, иногда выдает Abstract Error иногда выдает
Ассес вилатион. Подскажите как правильно закрывать динамически созданные компоненты.
OlegM (2007-08-09 12:29:00) [1]Ой люди спасибо огромное за терпение и помощь, все работает )
Юрий Зотов (2007-08-09 12:24:00) [2]> OlegM (09.08.07 12:20) [23]
Перед словом type. Только лучше напишите WM_USER+ 100.
OlegM (2007-08-09 12:20:00) [3]> Юрий Зотов , сенк.
Только не бейте )
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 11:56:00) [4]PostMessage( (Sender as TButton).Handle, ...
Вы сообщение КОМУ должны послать? Тому, кто его примет, поймет и обработает. Все это делает ФОРМА (потому что обработчик сообщения - это метод ФОРМЫ). А сообщение Вы почему-то посылаете КНОПКЕ.
Выкиньте подчеркнутый кусок. Хэндл ФОРМЫ, а не КНОПКИ надо указывать.
MetalFan (2007-08-09 11:47:00) [5]в интерфейсной части класса укажи
> procedure DelPanel(var mes: TMessage); message DEL_PAN;
OlegM (2007-08-09 11:38:00) [6]> Юрий Зотов
Дак конешно все это читал но очень давно. последние несколько лет только с базами.
Но что то опять я туплю короче.
это объявлено в глобальных
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);
Но ничего не происходит
sergeyst (2007-08-09 10:19:00) [7]
> Юрий Зотов © (09.08.07 09:59) [18]
Ага, спасибо, ясно.
Юрий Зотов (2007-08-09 09:59:00) [8]> 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 09:36:00) [9]
> Обработчик щелка по кнопке уничтожает панель, на которой
> лежит ЭТА САМАЯ кнопка. Вместе с панелью уничтожается и
> сама кнопка. А обработка события уже уничтоженной кнопки
> еще не завершилась.
Хм.. а:
TForm1.Button1Click(Sender: TObject);
begin
Free;
end;
никаких AV. И в чем разница?
OlegM (2007-08-09 08:35:00) [10]Что то я совсем спекся, ругаетцо на TPanel(WParam).Free;
[Error] Unit1.pas(49): '(' expected but ')' found
{RASkov} (2007-08-08 09:27:00) [11]> [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-08 09:21:00) [12]Что ? )
MBo (2007-08-08 09:07:00) [13]>А какое сообщение ?
пользовательское, например
WM_MY_FREE = WM_USER + 666;
OlegM (2007-08-08 08:58:00) [14]> Решение: обработчик кнопки через PostMessage шлет форме сообщение
А какое сообщение ?
WM_DESTROY неробит
MBo (2007-08-08 07:55:00) [15]в [8] все уже написано.
OlegM (2007-08-08 07:07:00) [16]Щас опишу задачу поподробнее.
нужно на экран выдавать типа сообщения, используя для этого 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 Это типа не я мозг парю это начальство дало вот такое задание в точности.
Loginov Dmitry (2007-08-07 21:42:00) [17]> Но иногда все работает, иногда выдает Abstract Error иногда
> выдает
Попробуй после Free сделать Abort
Юрий Зотов (2007-08-07 21:08:00) [18]О чем речь идет? Какие-такие FindComponent? Не о том говорим.
Обработчик щелка по кнопке уничтожает панель, на которой лежит ЭТА САМАЯ кнопка. Вместе с панелью уничтожается и сама кнопка. А обработка события уже уничтоженной кнопки еще не завершилась.
Что будет? Access Violation будет. Это и есть корень зла, а вовсе никакие не FindComponent.
Решение: обработчик кнопки через PostMessage шлет форме сообщение, передавая в его параметрах Sender (то есть, кнопку). Получив сообщение, форма уничтожает Parent'а этой кнопки.
И никаких FindComponent.
MetalFan (2007-08-07 17:49:00) [19]
...OnButtonClick( Sender: TObject );
begin
if Sender is TButton then
if TButton(Sender).Parent is TPanel then
TButton(Sender).Parent.Free;
end;
не очень хороший конечно вариант))) предлагаю доработать мозгами
{RASkov} (2007-08-07 15:05:00) [20]> [0] OlegM (07.08.07 14:37)
Ты более подробнее задавай вопрос, а то получается из [0]:
Мы создали несколько панелей с кнопками, а потом всего лишь одним нажатием на одну любую кнопку убили все что было на форме или только все панели в том числе и статически созданные....
В Components находяться все компоненты формы
а в Controls находятся все контролы принадлежащие тому контролу которому принадлежит этот самый список Controls
Т.е.
Controls или Form1.Controls содержит все контролы, в том числе и динамич созданные панели, если родитель этих панелей есть сама форма, а вот
Panel.Controls содержит контролы, которые находятся на панеле Panel, в том числе и те самые кнопки....