Форум: "Основная";
Текущий архив: 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