powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Закрытие MDIChild-формы
25 сообщений из 43, страница 1 из 2
Закрытие MDIChild-формы
    #39780290
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пишем MDI приложение.
В нем есть базовая форма для всех MDIChild-фор, пусть TMdiBaseForm, от которой наследуются все остальные дочерние формы;

При закрытии дочерних формы не сворачиваем их, а именно закрываем:

Код: pascal
1.
2.
3.
4.
procedure TMdiBaseForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;



Все формы создаются типовым способом:

Код: pascal
1.
2.
3.
  if Assigned(frmMdiChildren1) 
    then frmMdiChildren1.BringToFront
    else frmMdiChildren1 := TfrmMdiChildren1.CreateMDI(Application);



Все работает как надо, до момента закрытия формы.
После этого переменная frmMdiChildren1 остается ненулевая и форма повторно не создается.
Так вот вопрос: как занулить переменную формы после ее закрытия?
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780305
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
client6aac,

Код: pascal
1.
frmMdiChildren1:= nil;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780306
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function TMainForm.CheckMDIChild(Sender: TForm): Boolean;
var
  i: Integer;
begin
  Result := False;
  for i := 0 to (MDIChildCount - 1) do
    if MDIChildren[i] = Sender then
    begin
      Result := True;
      exit;
    end
    else
      Result := False;
end;



Использование
Код: sql
1.
2.
3.
4.
  if CheckMDIChild(frmMdiChildren1) then
    frmMdiChildren1.Show
  else
    frmMdiChildren1 := TfrmMdiChildren.Create(Self);  
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780310
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacПосле этого переменная frmMdiChildren1 остается ненулевая и форма повторно не создается.

А где место в котором вы обнуляете переменную ? Зачем вообще существует переменная frmMdiChildren1 ?
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780322
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DimaBrА где место в котором вы обнуляете переменную?
Вот вопрос то и был об этом... может не совсем корректно выразил мысль... Если закрытие окна происходит в базовой форме, которая не знает ничего о переменных, то где и как правильно занулять переменную формы?

DimaBrЗачем вообще существует переменная frmMdiChildren1 ?
Для того, что бы понять создавалась форма ранее или нет. Если будет создано стопитцот разных окошек и искомое потеряется где-то в самом низу, то клацнув в главном меню на пунктик вызова этого окна мы или выведем его наверх (если оно было ранее создано), либо создадим.

В общем-то, нужное решение было дано в третьем посте, за что goldmi45 отдельное спасибо. Наверное тему можно закрывать
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780326
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
client6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;



Открываем

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
procedure TForm1.btnClick(Sender: TObject);
begin
  if Assigned(Form2) then
    Form2.Show
  else
  begin
    Application.CreateForm(TForm2, Form2);
    Form2.Show;
  end;
end;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780327
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Но это - корявый метод...

Лучше закрывать\открывать "Главной формой"
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780328
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacТак вот вопрос: как занулить переменную формы после ее закрытия?

Удалить эту переменную вообще.
Она не нужна.

Реестр существующих окон держать в другом виде, например

Код: pascal
1.
2.
 Type MyMDIClass = class of TMdiBaseForm;
Var   MyMDIForms: TDictionary<MyMDIClass, TMdiBaseForm>



Ну и не забывать оттуда удалять закрываемые формы.

P.S. именно такой реестр на самом деле редко практичен: он не позволяет открывать НЕСКОЛЬКО окон одного класса. Впрочем, как и переменная "frmMdiChildren1" не может содержать несколько указателей на несколько окон сразу.

А в реальности часто по другому. Например в браузере открыто несколько разных веб-страничек, в Excel открыто несколько разных файлов: класс один и тот же, а окон много: уникальный идентификатор окна состоит не только из класса, но и ещё каких-то данных.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780335
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
zinpubclient6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;


[/src]

Не годится... Action := caFree; делаем в базовой форме, которая ничего не знает про Form2

Arioch
В текущей логике приложения как раз и нужно открытие окошек в единственном экземпляре.
Но за наставление на путь истинный - спасибо!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780338
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch,

Зачем создавать то, что уже есть?

MDIChildren и MDIChildCount
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780341
Фотография krapotkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
список MDI окон у нас по факту есть
но держать ссылки на формы в своем ObjectList(OwnObjects=FALSE!!!) никто не мешает
при закрытии нужно пробегать по нему и удалять из него ссылку на удаляемую форму

вопрос именно - для чего нам этот список
более практичным выглядит вариант когда это список моих объектов, которые содержат всякие данные и В ТОМ ЧИСЛЕ ссылку на форму...
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780342
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arioch
Вот только что созрела мысль, что в Вашем варианте с Дикшионари я тоже не очень понимаю как удалять Айтем из словаря при закрытии формы при условии, что все это должно быть реализовано в базовой форме
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780343
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А две одинаковые формы (одного типа) не могут быть созданы ?
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780347
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DimaBrА две одинаковые формы (одного типа) не могут быть созданы ?
нет, при попытке создания второго экземпляра формы, нужно вывести наверх уже имеющийся
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780348
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
goldmi45client6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function TMainForm.CheckMDIChild(Sender: TForm): Boolean;
var
  i: Integer;
begin
  Result := False;
  for i := 0 to (MDIChildCount - 1) do
    if MDIChildren[i] = Sender then
    begin
      Result := True;
      exit;
    end
    else
      Result := False;
end;



Или проще

Код: pascal
1.
2.
3.
4.
function TMainForm.CheckMDIChild(Sender: TForm): Boolean;
begin
  Result := MyFormsRegistry.Contains(Sender as TMdiBaseForm);
end;



http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Generics_Collections_TList_Contains.html

Но вообще привязывать реестр (реестры) открытых окон к TMainForm - стрёмная идея.
Потом если понадобиться распутать - то хрен распутаешь, спагетти зависимостей нарастёт.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
Type TMdiBaseForm = class
...
private
    FRegistry: TList<TMdiBaseForm>; 
   // может быть один синглтон на всю программу, или несколько (разные открытые проекты-странички-файлы)
....
public
  procedure BeforeDestruction; Override;
  property MDIRegistry: TList<TMdiBaseForm> write RegisterInNewRegistry;
....

procedure TMdiBaseForm.BeforeDestruction; 
begin
   MDIRegistry := nil;
   inherited;
end;

procedure TMdiBaseForm.RegisterInNewRegistry(const NewReg: TList<TMdiBaseForm>); 
begin
   if NewReg = FRegistry then exit;
   if nil <> FRegistry then FRegistry.Remove(Self);
   if nil <> NewReg then NewReg.Add(Self);   
   FRegistry := NewReg;
end;

.....

  LMyNewForm := TMyMDIxxxxForm.Create( ...... );
  LMyNewForm.XXX := yyy;
  LMyNewForm.AAA := bbb;
  LMyNewForm.MDIRegistry := MyProjectWindows;
  LMyNewForm.Show;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780349
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arioch,
я не пойму как это все делать из БАЗОВОЙ формы:)
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780350
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
goldmi45Arioch,

Зачем создавать то, что уже есть?

MDIChildren и MDIChildCount

1) лаконичнее. Одна строка - вызов стандартной функции TList<t>.Contains гораздо меньше, чем расписанный вами if с циклами. Следовательно, меньше шансов тупой ошибки.

2) гибче. Например, в дальнейшем нужно будет иметь несколько MDI-Parent окон. Или с MDI будет переход на что-то другое (табы, докающиеся плавающие окна, ...)
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780356
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
client6aaczinpubclient6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;


[/src]

Не годится... Action := caFree; делаем в базовой форме, которая ничего не знает про Form2


Ну
Код: pascal
1.
Sender:= nil;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780357
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacя не пойму как это все делать из БАЗОВОЙ формы:)

1) пробросить в базовую формы ссылку на содержащий её реестр
2) иметь один единственный реестр в приложении - глобальную переменную
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780358
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacНе годится... Action := caFree; делаем в базовой форме, которая ничего не знает про Form2

так From2 тут явно один из потомков базовой формы, то же самое, что frmMdiChildren1
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780359
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Но Arioch прав, гораздо лучше реестр окон, в который можно добавить собственные свойства\методы... итд
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780361
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;[/src[

Ну [SRC pascal]Sender:= nil;



Зачем? переменная Sender перестаёт существовать через мгновение, когда ты выходишь из процедуры!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780363
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
procedure TMdiBaseForm.RegisterInNewRegistry(const NewReg: TList<TMdiBaseForm>); 
begin
   if NewReg = FRegistry then exit;
//   if nil <> FRegistry then FRegistry.Remove(Self);
   if nil <> FRegistry then begin
     FRegistry.Remove(Self);
     FRegistry := nil;
   end;
   if nil <> NewReg then NewReg.Add(Self);   
   FRegistry := NewReg;
end;



Вот так лучше.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780364
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ariochzinpub
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;[/src[

Ну [SRC pascal]Sender:= nil;



Зачем? переменная Sender перестаёт существовать через мгновение, когда ты выходишь из процедуры!

Тьфу... Да! затупил...
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780366
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krapotkinболее практичным выглядит вариант когда это список моих объектов, которые содержат всякие данные и В ТОМ ЧИСЛЕ ссылку на форму.

после чего этот список начинает расти, а либо поиск, либо удаление объектов в массиве - операции дорогие

свалить ВСЕ объекты в одну кучу - спорное решение.
...
Рейтинг: 0 / 0
25 сообщений из 43, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Закрытие MDIChild-формы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]