В нашем случае программа запускается и сразу создается дочернее окно. Кстати, мы пока еще не написали нигде, что какие-то окна нужно создавать, они сами откуда-то появляются. У нас есть классы, у нас в разделе var есть необходимые переменные, но нигде не видно кода, который инициализирует эти переменные и помещает в них экземпляры классов. Дело в том, что все формы попадают в список автоматически создаваемых, а инициализацию вы можете найти в исходном коде проекта (меню Project | View Source (Проект | Посмотреть исходник).
Давайте посмотрим, как убрать его и создавать в режиме runtime (во время выполнения программы)? Очень просто, выберите меню Options | Project (Опции | Проект), и вы увидите окно, как показано на рис. 9.14. Это для Delphi 7-й и более ранних версий, а в Delphi 2005 и старше окно выглядит так, как показано на рис. 5.4.
В левой части окна перечислены те формы, которые будут создаваться автоматически (Auto-create forms (Автосоздаваемые формы)). Выделите тут childForm (наше дочернее окно) и переместите его в список Available forms (Доступные формы), нажав кнопку между списками в виде одиночной стрелки, направленной
вправо. Теперь дочерняя форма не будет создаваться автоматически. Это действие придется делать вручную.
Установите на главную форму панель и растяните ее по верхнему краю окна (свойство Align надо установить в aiTop). Теперь на панель установим кнопку и дадим ей заголовок Создать (рис. 9.15).
При нажатии на эту кнопку мы будем вручную создавать окно. Для этого напишем следующий код:
procedure TMainForm.CreateButtonclick(Sender: TObj ect); begin
ChildForm:= TChildForm.Create(Owner); end;
Здесь мы присваиваем переменной ChildForm указатель на новое созданное окно TChildForm.create. Переменная ChildForm объявлена в модуле дочернего окна в разделе var:
var
ChildForm: TChildForm;
Запустите программу и попробуйте несколько раз нажать на кнопку Создать. У вас должно создаться сразу несколько дочерних окон, как показано на рис. 9.16.
Но если вы попытаетесь закрыть любое из них, оно просто свернется. Чтобы окно закрывалось, нужно создать обработчик события Onciose для дочерней формы и в нем написать:
procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree; end;
Здесь переменной Action (действие) присваивается значение caFree. Эта переменная передается обработчику события в качестве второго параметра. Мы изменяем действие, которое выполняется по умолчанию для клиентских многодокументных окон на caFree, что заставляет форму уничтожиться. Как вы могли убедиться, по умолчанию для MDI-приложений окно сворачивается.
Сразу же посмотрим, какие еще значения может получать переменная Action:
- caNone — ничего не делать, т. е. окно не будет закрыто;
- caHide — спрятать окно, но при этом оно не будет уничтожено, а память не будет освобождена. Это значение по умолчанию для SDI-окон. По закрытию они просто прячутся, но не уничтожаются, поэтому их достаточно создать только один раз, и можно потом вызывать сколько угодно раз;
- caMinimize — не закрывать, а только минимизировать окно. Именно это значение используется по умолчанию для дочерних окон в MDI-приложениях.
Вот теперь наше приложение готово.
Как видите, для разных типов приложений используется один и тот же тип окна TForm, что очень удобно. Но вы должны помнить, что TForm может работать немного по-разному, и учитывать это при написании реальных приложений.
Напоследок рассмотрим несколько полезных свойств и методов формы, примеры которых уже реализованы в рассмотренных выше программах.
- ActiveMDichild — указывает на активное дочернее окно.
- MDichiidCount — целое число, указывающее на количество дочерних окон.
- MDichiidren — через это свойство можно получить доступ к любому дочернему окну.
Например, второе окно можно получить с помощью MDichiidren [2 ]. Допустим, вам надо изменить заголовок активной дочерней формы. Как узнать,
какая из них активная, когда их несколько? Очень просто. Создайте в главной форме кнопку и по ее нажатии напишите:
procedure TMainForm.ButtonlClick(Sender: TObject); begin
ActiveMDIChild.Caption:='Активное дочеренее окно';
В этом коде мы изменяем свойство caption активной формы. Если нет активной дочерней формы (бывает, когда дочерних форм вообще нет), то свойство
ActiveMDIChild равно nil.
Давайте попробуем изменить заголовки всех дочерних окон. Для этого запустим цикл от 0 до MDichiidcount и изменим все заголовки:
Есть еще несколько интересных методов.
- Arrangeicons — выстроить иконки всех дочерних окон.
- Cascade — выстроить каскадом все дочерние окна.
- Next — следующее дочернее окно.
- Previous — предыдущее дочернее окно.
- Tile — тоже выстроить дочерние окна, только мозаикой.
Обратите внимание, что MDI-окно мы не отображаем. Оно само показывается на экране, а мы только вызываем конструктор для создания нового экземпляра. Почему? Посмотрите на свойство visible у дочернего окна. Обратите внимание, что оно равно true. Когда это свойство равно true, то окно видимо и должно отобразиться на экране, а когда мы изменяем свойство Formstyle на fsMDichild, то свойство visible тоже автоматически становится равным true.
Учитывайте этот нюанс. Если вы случайно сделали окно дочерним, а потом поменяли обратно на fsNormal, то после запуска это окно сразу же отобразится на экране (если форма в списке автоматически создаваемых), потому что свойство visible останется равным истине.