![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Метод
VetMIg © (2002-05-08 14:45:00)Почему, когда я уничтожаю форму методом "Free". После 3-го закрытия этой формы программа выдает ошибку?
Пример:
...
Form1.Visible:= False;
Form1.Free;
...
VetMIg (2002-05-21 14:34:00) [1]Спасибо друзья... Я вдоволь начитался. Обязательно попробую ваши советы. И еще раз спасибо :-))))))
Tonie (2002-05-16 12:55:00) [2]To KSergey © (15.05.02 16:11)
>PostMessage(Handle, CM_RELEASE, 0, 0);
Ну так в этом и смысл, сообщение CM_RELEASE будет помещено после уже имеющихся в очереди, поэтому и TCustomForm.CMRelease произойдет после того как все оставшиеся сообщения будут обработаны
Кстати Close вызывает Release, поэтому использование Close вместе c ... Action := caFree вполне корректно
Release;
procedure TCustomForm.Close;
var
CloseAction: TCloseAction;
begin
if fsModal in FFormState then
ModalResult := mrCancel
else
if CloseQuery then
begin
if FormStyle = fsMDIChild then
if biMinimize in BorderIcons then
CloseAction := caMinimize else
CloseAction := caNone
else
CloseAction := caHide;
DoClose(CloseAction);
if CloseAction <> caNone then
if Application.MainForm = Self then Application.Terminate
else if CloseAction = caHide then Hide
else if CloseAction = caMinimize then WindowState := wsMinimized
else
end;
end;
Fantos (2002-05-16 11:52:00) [3]Позволю заметить, что ПРИНЦИПИАЛЬНОЕ различие в использовании FREE или RELEASE я прочувствовал на собственных "граблях". И заключались они (грабли) в следующем:
- программа подключала DLL-ку (динамически, в отдельном потоке) с вызовом формы из нее (не модально!). В этом модуле шла работа с устройствами через COM-порты... Так вот, если в интерфейсной процедуре из DLL-ки (вы понимаете о чем я?) ставилось удаление формы через FREE, то основная программа ПРИ или ПОСЛЕ выполнения FREELIBRERY - частенько И НЕ ЗАКОНОМЕРНО вываливала ошибку AV ! Причина -- банальное ОТСУТСТВИЕ обработчика очереди сообщений...форма то уже УДАЛЕНА!
А вот когда FREE была заменена на RELEASE, вот тогда все стало нормально работать и закрываться...
Вот Вам и разница, как говорится - "на пальцах"...
Поэтому, для "выписки рецепта" необходимо, сначала, "обдумать" всю связку удаляемых форм и основного модуля(или формы, если хотите)...
KSergey (2002-05-15 16:11:00) [4]2 Producer
А если много - зачем его увеличиваете?
и опять же тема окаазлась интересной, нек. тонкости выискались, так что погорячились вы, Producer.
К тому же никто не ответил пока: правомочно ли использовать Free в такой конструкции
with TAbout_Form.Create (Self) do
try
ShowModal;
finally
Free;
end;
или это приведет таки к возможным ошибкам?
Хоят вот мне как кажется: ну уничтожил я форму, за ней уничтожилось окно, хендл его пропал для системы (неактуален), но сообщения остались. Ну и что? Они проигнорируются - вот и все. Если послать сообщение с отфонарным хендлом - неужели винды AV выкинут? Как-то я сильно сомневаюсь в том... (а вот проверить лень, признаю)
К слову, не поленился сейчас глянул как реализовано Release: как то не совсем понятно на мой вкус...
// 1. Шлет сама себе CM_RELEASE, причем Post"ом - отсюда и выход из этой процедуры сразу, до собственно разрушения
procedure TCustomForm.Release;
begin
PostMessage(Handle, CM_RELEASE, 0, 0);
end;
// 2.А как там у нас реакция на CM_RELEASE устроена?
procedure TCustomForm.CMRelease;
begin
Free;
end;
О, нифига себе! просто уничтожается объект, причем Free и не взирая на оставшиеся, возможно, сообщения! Так что про сообщения, якобы обрабатываемые Relaese до конца - это выдумка, однако.
Да и само назначение/применение Release становится мне не совсем понятным: типа "разрушься на досуге".
К стати, реакция на caFree - просто вызывается Release - вот и все.
Видимо, применение Relеase (равно как и его назначение) - в возможности формы уничтожать полностью саму себя. Что, впрочем, похоже можно сделать и вызвав в любом месте Free, важно чтобы это был последний оператор в методе. Ну и, возможно, не во всех обработчиках так можно сделать - могут, наверное, и проблемы возникнуть, если в OnCreate прям сразу Free вызвать ;)
Прощу прощения, если кого утомил. Буду рад конструктивной критике, коли чего недопонимаю.
Producer (2002-05-15 13:47:00) [5]Не много-ли шума вокруг простого вопросика? Я думаю, что VetMlg отнюдь не с "бронепоезда" и уже давно "в проблеме".
KilkennyCat (2002-05-15 11:16:00) [6]Тысяча извинений, с хайд и шоу я переборщил :)
Разумеется, визибле нот визибле.
KilkennyCat (2002-05-15 11:00:00) [7]А вот так делаю я:
При вызове какой либо формы из главной:
begin
About := TAbout.Create(self);
try
About.ShowModal;
Main.hide;
finally
About.Free;
Main.Show;
end;
end;
Разумеется, эта форма не должна создаваться в проекте (кинуть ее в секцию Available forms)
Закрытие формы About
modalresult := mrCancel;
Хотя и не обязательно, если в дальнейшем не обрабатывать это.
KSergey (2002-05-15 10:42:00) [8]2 Zemal
Чем философски умничать - лучше бы выспался. Полезнее бы оно как-то было для всех - меньше подбирать
KSergey (2002-05-15 10:42:00) [9]2 Zemal
Чем филосовски умничать - лучше бы выспался. Полезнее бы оно как-то было для всех - меньше подбирать
Zemal (2002-05-15 10:20:00) [10]VetMlg, ну ты дал! Когда код пишешь мысли практично, представляй как будет работать программа, представляй образно объекты и всё будет хорошо. А в твоём случае, после уничтожения формы как будут работать её события если их нет??? Если кнопка в событии которой выполняются инструкции уже разрушена?
И кстати, метод Free во многих случаях работает без помех, если вы сами не посылаете сообщение окну формы какой-нить "нитью", которая страшно подтормаживает из-за низкого приоритета и не проверяя существование формы шлёт ей месаги. Это называется безолаберность. Пишите процедуры и функции так, что бы потом не думать какой метод вызвать Free или Release. :))) Просто соблюдайте правила хорошего тона в программировании - проверяйте (не ленитесь) все VCL компоненты перед обращением к ним, если есть вероятность, что их нет. :)))
И ещё, VetMlg, как ты думаешь? Объект себя "вешает", потом "встаёт из могилы" и "прощается с роднёй"? Если уж форма себя унечтожает, то позаботься о том, чтобы: во-первых, были унечтожены все объекты в классе этой формы (если ты что-то создаёшь сам), дело всё в том, что если ты создаёшь объект в классе формы, то ты его и должен уничтожить, само приложение не будет разрушать такие объекты и они остаются висеть в памяти, а ты уже не можешь ничего с ними поделать, т.к. теряешь указатель на эти объекты, во-вторых, старайся думать так, как "думает" приложение, пока не научишься представлять как оно работает - ничего из тебя не получется (в смысле: программист ты будешь "примерочный" - который ищет примеры где только можно и составляет приложение из этих кусков, немного их подправив, а потом удивляется откуда ошибки и беспомощно разводит руками).
Мой совет: начинайте с основ, т.е. с объектной модели. Не усвоив это не переходите к изучению методов и т.д., потому что это бесполезно. Без понятия философии классов (наследование и т.д.), нечего дальше даже нос совать. Жаль, что мало в каких книгах хорошо это описывают... сразу начинают учить за "21 день"... и начинаются вопросы в форумах, которые показывают совершенное незнание основ (времени жизни объектов, области видимости и т.д.). Печально смотреть на программеров подготовленных за "21 день", которые потом засыпают форумы вопросами типа "знаю как пользоваться ноздрями, а дышать не могу! почему?"... ДА ПОТОМУ! Лезь в учебники!!!
Блин... бардак... извините друзья! Я просто не выспался сегодня! :) Бошка трещит, а триггера не ждут... :)
Извиняюсь, если лабуду написал, что было в голове то и написал :)... даже перечитывать не охото, тем более исправлять :)... типа: версия "как-есть". гы-гы.
:)))
Alex M.A. (2002-05-15 09:54:00) [11]Возможно, я неправильно понял замысел автора, но использование следующих конструкций не приводит к возникновению ошибок,
и по-моему позволяет достичь нужного результата.
procedure TForm1.AboutMenuClick(Sender: TObject);
begin
AboutBox:=TAboutBox.Create(Application);
AboutBox.ShowModal;
end;
procedure TAboutBox.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;
caFree - The form is closed and all allocated memory for the form is freed.
leshy (2002-05-15 09:49:00) [12]А почему в
TAbout_Form.OnCloseнельзя просто поставитьAction := caFree, и не задумываться больше над этим. Туда же можно вставитьAbout_Form := nil, чтобы не делать этого где то ещё. Туда же, кстати, можно иMain_Form.Show, вместоVisibleиSetFocus.
Хотя, если быть до конца корректным, обнуление переменной формы лучше делать в BeforeDestruction.
Соответственно, закрытие формы производить простымClose.
KSergey (2002-05-15 09:44:00) [13]2 koks
А если модальная - то что? Какая разница?
KSergey (2002-05-15 09:42:00) [14]Скобочка одна выпала:
procedure TAbout_Form.FormClose(Sender: TObject; var Action: TCloseAction);
koks (2002-05-15 09:41:00) [15]procedure TAbout_Form.Image3Click(Sender: TObject);
begin
PlaySound("sound\menu_back.wav", 0, Snd_FileName);
Close;
Main_Form.Visible:= True;
Main_Form.SetFocus;
end;
procedure TAbout_Form.About_FormOnClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
Это если у тебя About_Form - не модальная...
Да, кстати, интересно было бы найти, при установки Action := caFree форма РЕАЛЬНО удаляется методом Free или Realease...
KSergey (2002-05-15 09:40:00) [16]Все что вам отвечено - абсолютно верно (как будто кто-то в том сомневался ;)
Я бы посоветовал сделать так:
procedure TAbout_Form.Image3Click(Sender: TObject);
begin
PlaySound("sound\menu_back.wav", 0, Snd_FileName);
Close;
// а вот цель след. вдух строк не ясна:
// а что, MainForm была скрыта в момент показа About?
// А зачем?! Ну впрочем есть надо - можно и оставить эти строки
// Main_Form.Visible:= True;
// Main_Form.SetFocus;
end;
// и обязательно далее: облаботчик OnClose формы About:
procedure TAbout_Form.FormCloseSender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
В моем понятии все это очень корректно сработает. Или есть возражения?
Хотя вообще-то я бы вообще все это сделал не так. Где-то же, как я понимаю, форма About создается? Вот в этом месте я бы сделал так (предположим, что это нажатие на кнопку в главной форме):
// внимание: здесь не присваивается значение переменной About_Form
// А оно вообще-то надо?! Обычно и без этого можно обойтись
with TAbout_Form.Create (Self) do
try
ShowModal;
finally
Free;
end;
Тогда и обработчик клика на картинке преобразуется в
procedure TAbout_Form.Image3Click(Sender: TObject);
begin
PlaySound("sound\menu_back.wav", 0, Snd_FileName);
Close;
// ну если очень надо - можно раскомментировать две след. строчки
// Main_Form.Visible:= True;
// Main_Form.SetFocus;
end;
Вот и все!
К стати, в приведенной конструции, которую я везде использую, так же никогда не пользовал Release. Пока везло.. Возможно, этому есть объяснение, но я его не знаю. Может кто-либо просветит? (т.к. вроде как аргументы в пользу Release выглядят вполне разумными, но может именно в такой конструкции это принципиально уже не важно, т.к. все сообщения уже проехали в момент ShowModal?)
Мальфет (2002-05-15 08:54:00) [17]VetMIg, извини, но над стилем тебе надо поработать...
По сабжу: Абсолютно неправомощно использовать процедуры освобождения объекта из самого объекта.
Alx2 (2002-05-15 08:07:00) [18]Free из самого себя - не выход. Release?
Slym (2002-05-15 06:51:00) [19]Гасишь форму, а в его методе продолжаешь -
Main_Form.Visible:= True;
Main_Form.SetFocus;
попробуй фри вставить в конец :)
Fay (2002-05-15 02:20:00) [20]Круто !!!