![]() |
|
|
#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.
|
|
#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 что-то не встретила.
Про то, что форму не создавать всякий раз новую, а использовать одну и ту же - это я подумаю, может быть перестрою мышление . До сих пор я всегда освобождла форму в её FormClose через Action := caFree, а обнуляла - в вызывающей, по свойству типа OnClose:TNotifyEvent, т.е. общая схема действий была такая: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
|
|||
|
|||
|
Вау! Вот это я понимаю - объяснение. Осталось только проглотить
Спасибо огромное!!!Увы, совсем непохоже на то, что писано мной . Ладно, пошла "перетрахивать" свой код. Надеюсь, больному станет легче. |