![]() |
|
#1
|
|||
|
|||
![]() Скажите мне, умные люди, ВСЕГДА ли при разрушении формы случается событие OnDestroy для этой формы? У меня оно как-то не случается, если форма разрушается косвенно(при разрушении формы-владельца).
Подробнее это выглядит так: На главной форме есть кнопка, при нажатии на которую создаётся другая форма, собственником которой является главная, т.е. Код:
Form2 := TForm2.Create(self) И вот какая засада - если пользователь закрывает приложение (стандартным крестиком на главной форме), не закрыв перед этим Form2(ведь таких неаккуратных - пруд пруди!), то событие TForm2.FormDestroy не наступает ![]() |
#2
|
||||
|
||||
![]() Ничё не понял.
Если я таки понял тебя, то просто при "косвенном" закрытии вызови событие Form2.Destroy или как там оно называется. И будет тебе счастье. Если неправильно я понял, то поясни ещё раз. Если не ты, то кто? (с) Терри Пратчетт Не забывайте ставить плюсы и говорить спасибо! |
#3
|
|||
|
|||
![]() ни разу не вызывала событие принудительно. Ты не покажешь, как это сделать? Нижеприведенный вариант, наверное, совсем того ?
![]() Код:
procedure TMainForm.FormDestroy(Sender: TObject); begin Form2.FormDestroy(Sender); {большие сомнения касательно того, что пихать в качестве параметра обработчика} end; |
#4
|
||||
|
||||
![]() Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation uses Unit2; {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin with TForm2.Create(Application) do begin Show; end; end; end. Код:
unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TForm2 = class(TForm) procedure FormDestroy(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } end; var Form2: TForm2; implementation {$R *.dfm} procedure TForm2.FormDestroy(Sender: TObject); begin Windows.Beep(1000, 100); end; procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction); begin Action:=caFree; end; end. Пишу программы за еду. __________________ |
#5
|
||||
|
||||
![]() В качестве параметра пихай тот объект, который должен вызвать событие. В данном случае ты ждешь ОнДестрой от Форм2. Ну вот и пихай вместо Сендер твой Форм2.
Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#6
|
|||
|
|||
![]() Спасибо, запихнула. Работает!
Попутно вопрос - у меня в последнее время уже при закрытии Delphi часто возникает "Access violation at adress... in dcc70.dll///", причём нервный такой - многократно повторяющийся - множащийся окошками. И его никак, кроме как перезагрузившись, не успокоить. Подозреваю, что это может происходить из-за неправильной организации работы с формами. Может кто сталкивался с такой штукой и даст совет - хотя бы как проверить? У меня в приложении 4 формы с обычным шоу и три - с модальным. Те, которые с модальным, организованы по стандартному(где-то здесь вычитанному) шаблону: Код:
if Form1 = nil then Form1 := TForm1.Create(nil); try Form1.onAddNewExam := OnAddNewExam;//присвоение конкретной процедуры свойству if Form1.WindowState = wsMinimized then Form1.WindowState := wsNormal; if Form1.ShowModal = mrCancel then exit; { может здесь собака зарыта? - она ж в этом случае остаётся висеть, так? хотя я по этой ветке и не ходила ещё ((, а ошибка лезет } finally Form1.Free; Form1 := nil; end; Формы, которые с обычным Show, создаются через TFormCreate(self), где self - это вышеупомянутая Form1. В каждой форме есть свойство типа TNotifyEvent, которое вызывается в CloseForm и сообщает форме-собственнику (ну, той самой Form1), что можно вызываемую рушить (а просто использовать Release в самой процедуре закрытия каждой формы вместо всех этих наворотов нельзя? ). Может непонятно объясняю, лучше код выкладывать? Но он такой... длинновастенький ![]() |
#7
|
|||
|
|||
![]() Код:
... if Form1.ShowModal = mrCancel then exit; finally Form1.Free; Form1 := nil; end; ... Последний раз редактировалось Asinkrit, 02.04.2011 в 20:22. |
#8
|
|||
|
|||
![]() Код:
... if Form1.ShowModal = mrCancel then exit; finally Form1.Free; Form1 := nil; end; ... Последний раз редактировалось Asinkrit, 02.04.2011 в 20:22. |
#9
|
|||
|
|||
![]() Да, очень доступно. Спасибо за подсказку! Попробую так поймать.
А многократное создание форм одного и того же типа при условии их корректного уничтожения - это нормально? Или лучше форму каждого типа создать один раз и потом открывать-закрывать? Ещё хочу уточнить по поводу бессмысленного кода (красного): при такой организации текста он НИКОГДА не выполнится или просто сначала будет выполнен блок Finally, а потом всё-таки exit сработает? Дело в том, что у меня-то там дальше в этой процедуре ещё кусок кода, который нужно выполнить только в случае закрытия формы с mrOK. |
#10
|
|||
|
|||
![]() 1234567890
Последний раз редактировалось Asinkrit, 02.04.2011 в 20:22. |
#11
|
|||
|
|||
![]() Выкладываю (и нервно курю в сторонке) :
Код:
{На главной форме есть бар с меню, состоящем из кнопок с названиями директорий, содержащих данные для конкретного процесса. Данные будут загружаться в зависимости от выбранной директории :} procedure TMainForm.BtnExClick(Sender: TObject); begin with Sender as TdxBarButton do FocusedDir := Caption; {если пользователь хочет создать новый процесс, то загружается спецформочка, в которой задаётся название нового процесса и пр. инфа для создания директории нового процесса :} if FocusedDir = 'Новый' then begin if FormAddExam = nil then FormAddExam := TFormAddExam.Create(nil); try FormAddExam.onAddNewExam := OnAddNewExam; {Это свойство типа TNotifyEvent, сообщающее вызывающей форме введённое в спецформочке имя новой директории(чтоб создать новую кнопку меню на баре) } if FormAddExam.WindowState = wsMinimized then FormAddExam.WindowState := wsNormal; if FormAddExam.ShowModal = mrCancel then exit; finally FormAddExam.Free; FormAddExam := nil; end; end; {если пользователь подтвердил создание нового процесса (форма закрылась с ModalResult = mrOK - там внутри возможны только 2 варианта ModalResult), то создаётся новая форма для осуществления толькочтосозданного процесса: } if FormExam <> nil then FormExam := nil; FormExam := TFormExam.Create(nil); FormExam.Top := Top + Height; FormExam.onCloseExam := OnCloseExam; {свойство типа TNotifyEvent, вызывающееся в FormExam.CloseForm(и там же после этого вызова Action := caFree) и сообщающее вызывающей форме, что эту форму можно разрушать (в теле процедуры OnCloseExam только один оператор: FormExam := nil ) : } FormExam.DefineFilesListForExam(FocusedDir);{инициация некоторых полей формы } if FormExam <> nil then begin if FormExam.WindowState = wsMinimized then FormExam.WindowState := wsNormal; FormExam.Show; end; end; //================ Ну вот, как-то так примерно ![]() Последний раз редактировалось vikk, 09.02.2011 в 16:28. |
#12
|
|||
|
|||
![]() try-finally ее не поймает.
Последний раз редактировалось Asinkrit, 02.04.2011 в 20:22. |
#13
|
|||
|
|||
![]() Спасибо за разбор моих каракулей. С MDI-формами не работаю - не могу найти достаточное количество информации, чтоб хоть попробовать, как оно это делается. Скажем, можно ли только ЧАСТЬ форм проекта сделать дочерними к какой-то ещё форме проекта или уж если такая организация, то всего проекта в целом? И особенности организации, кроме как установка FormStyle главной - в MDIForm, а других - в MDIChild что-то не встретила.
Про то, что форму не создавать всякий раз новую, а использовать одну и ту же - это я подумаю, может быть перестрою мышление ![]() Unit1: Код:
type TForm1 = class(TForm) ... private Form2: TForm2; ... end; procedure TForm1.BtnCreateForm2Click(SEnder: TObject); begin ... Form2 := TForm2.Create(self); Form2.OnClose := OnCloseForm2; ... end; procedure TForm1.OnCloseForm2(SEnder: TObject); begin Form2 := nil; end; Код:
type TForm2 = class(TForm) ... private fonClose:TNotifyEvent: TNotifyEvent read fonClose write fonClose; public property onClose: ... end; TForm2.FormClose(SEnder: TObject; Action: TCloseAction); begin ... if assigned (fonClose) then fonClose(self); Action := caFree; end; А каким образом можно не выносить обработчик события с вызываемой формы, если в теле этого обработчика производятся манипуляции над ВЫЗЫВАЮЩЕЙ формой(в данном, например, случае надо в меню вызывающей формы создать новую кнопку с именем процесса, введенным пользователем в поле вызываемой формы) ? Другими словами, каковы должны быть действия в случае необходимости передать параметры из вызываемой формы - в вызывающую (гм, я здесь уже такую темку открывала). Можно попросить у Вас общую схему - как действовать в таких случаях? Про признак я не очень поняла. Плохость такого стиля в чём заключается - в том, что в качестве условия используется Caption или в том, что напрямую в коде прописывается кирилловая строка, которая может не совпасть по кодировке на каком-то другом компе ? Ведь если у я введу булевский признак IsNew, то ему же всё равно надо будет присваивать значение в соответствии с тем, нажата ли кнопка с названием 'Новый' или другая. А можно тогда через тэг кнопки эту проблему решить(чтоб не кирильничать в коде?) : Код:
if TdxBarButton(Sender).Tag = <значение тэга кнопки "Новый"> then ... Или это тоже нехорошо? Буду оооочень благодарна за любые наставления, указания, советы и пр. Последний раз редактировалось vikk, 11.02.2011 в 10:05. |
#14
|
|||
|
|||
![]() Я не зря про MDI
Последний раз редактировалось Asinkrit, 02.04.2011 в 20:23. |
#15
|
|||
|
|||
![]() Вау! Вот это я понимаю - объяснение. Осталось только проглотить
![]() Увы, совсем непохоже на то, что писано мной ![]() |