ООП. Лабораторная работа 10.
Многодокументные (MDI) приложения.
MDI приложения позволяют в рамках окна главной формы (MDI frame window) работать с неограниченным количеством дочерних окон, содержащих документы различного типа (пример - Word, Excel).
Шаг 1. Создайте новый проект (File/New Application). Дайте форме имя FrameForm (свойство Name) и измените ее заголовок на MDI Application. Установив свойство FormStyle на значение fsMDIForm сделайте форму обрамляющей формой многодокументного приложения.
Шаг 2. С помощью команды меню File/New Form добавьте к проекту дочернюю форму. Дайте ей имя ChildForm и установите ее заголовок MDI Child. Установив свойство FormStyle на значение fsMDIChild сделайте форму дочерней (подчиненной) формой многодокументного приложения.
Сохраните проект и его формы (File/Save All). Проекту дайте имя MDIAppl. dpr, модулю обрамляющей формы - MDIFrame. pas, а модулю дочерней - MDIChild. pas.
Шаг 3. По умолчанию, попытка закрытия дочернего окна приводит к его сворачиванию. Для реализации полного закрытия дочернего окна в событии OnClose замените значение параметра Action, управляющего порядком закрытия окон, с caMinimize (свернуть окно) на caFree (закрыть окно):
procedure TMDIChild. FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
Шаг 4. Для организации обращения между обрамляющей и дочерними формами обеспечим взаимную видимость их модулей. Для этого из обрамляющей формы FrameForm командой File/Use Unit подключите модуль MDIChild. pas, а из дочерней ChildForm - модуль обрамляющей формы MDIFrame. PAS.
Если обрамляющая и дочерняя имеют собственные меню, то при открытии дочерней формы набор ее меню добавляются к набору меню обрамляющей формы. Порядок образования объединенного меню определяется свойством GroupIndex (групповой номер) компонента TMenuItem:
· объединенные меню располагаются в порядке возрастания значений свойства GroupIndex;
- меню дочерней формы заменяют меню главной формы с тем-же значением GroupIndex; группы меню с одинаковым GroupIndex добавляются или заменяются целиком.
Шаг 5. Установите на обрамляющей форме компонент MainMenu и двойным щелчком вызовите у него окно Дизайнера Меню. Создайте два меню: File, состоящее из пунктов New, Open, пустой (-), Exit и меню Window, состоящее из пунктов Tile и Cascade.
Шаг 6. На дочерней форме также установите компонент MainMenu. В окне Дизайнера Меню с помощью команды Insert From Template... всплывающего меню (щелчок правой кнопки мыши) вставьте из шаблона расширенный вариант меню File и меню Edit.
Шаг 7. Для организации правильного объединения меню форм установите следующие значения их свойств GroupIndex.
В форме FrameForm File1.GroupIndex = 0 Window1.GroupIndex = 6.
В форме ChildForm File1.GroupIndex = 0 Edit1.GroupIndex = 1.
Шаг 8. Запустите приложение. Дочерняя форма открылась автоматически. Внимательно изучите содержимое набора меню. Определите, меню какой формы представлены и объясните, почему так получилось. Закройте дочернее окно и также изучите набор меню.
Шаг 9. Откажитесь от автоматического и выберите “ручной” способ открытия дочерней формы. Для этого в окне настройки параметров проекта (меню Project/Options) на странице Forms переведите пункт ChildForm из списка Auto-Create Forms в список Available Forms:
Для манипулирования дочерними формами во время работы приложения доступны следующие свойства обрамляющей формы:
Свойство | Тип | Описание |
MDIChildren [i :Integer] | TForm | Массив дочерних форм в порядке их создания. |
MDIChildCount | Integer | Количество открытых дочерних форм. |
ActiveMDIChild | TForm | Активная дочерняя форма. |
Шаг 10. Опишите процедуру открытия новой дочерней формы, вызываемую выбором команды File/New меню обрамляющей формы (обработчик события OnClick пункта New в форме FrameForm:
procedure TFrameForm. New1Click(Sender: TObject);
begin
with TChildForm. Create(Self) do
Caption := Caption + ' ' + IntToStr(Self. MDIChildCount);
end;
Здесь первой строкой вызывается метод создания дочерней формы типа TChildForm; в скобках указано имя владельца этой дочерней формы - Self (сама, т. е. обрамляющая форма). Во второй строке к заголовку дочерней формы добавляется ее номер - количество открытых дочерних форм.
Шаг 11. Т. к. после открытия дочерней формы ее меню File заменит соответствующее меню обрамляющей формы, то определим реакцию на выбор пункта меню File/New для дочерних форм:
procedure TChildForm. New1Click(Sender: TObject);
begin
FrameForm. New1.Click;
end;
Шаг 12. В обрамляющей форме в обработчиках выбора пунктов Tile и Cascade меню Window запишите по одной строке Tile; и Cascade; соответственно. Эти методы изменяют расположение дочерних окон.
Шаг 13. Для того, чтобы в меню Window был представлен список имен открытых дочерних окон установите имя объекта, отвечающего за этот пункт (Window1) в качестве значения свойства WindowMenu обрамляющего окна.
Шаг 14. Для примера работы с отдельными дочерними окнами определим реакцию на выбор пункта меню File/Close для дочерних форм:
procedure TChildForm. Close1Click(Sender: TObject);
begin
with FrameForm do
if ActiveMDIChild <> nil then ActiveMDIChild. Close;
end;
Здесь необходимость первой строки вызвана тем, что ссылка на активную дочернюю форму ActiveMDIChild является свойством обрамляющей формы.
Шаг 15. Готовый шаблон MDI-приложения можно просто загрузить из Хранилища Объектов (File/New/Project). Опробуйте данный способ. Изучите обработчики пунктов меню Window.
Задание. Разместите на дочернем окне редактор Memo и дополните созданное MDI-приложение следующими пунктами меню:
FrameForm - Window/Set Red Color – окрашивает фон редактора Memo текущего окно в красный цвет.
FrameForm - Window/Minimize all – сворачивает все подчиненные окна (если сразу не получится, посмотрите, как это сделано в шаблоне MDI - приложения).
FrameForm - Window/Restore all – восстанавливает свернутые подчиненные окна.
FrameForm - Window/Close all – закрывает все подчиненные окна.
FrameForm - Window/Table – открывает параллельное окно с информационной таблицей (TStringGrid). В таблице должны быть представлены номер, заголовок, размеры и состояние (свернутое, распахнутое, нормальное) всех подчиненных окон приложения. Любое изменение в массиве подчиненных окон должно одновременно отображаться в таблице (если открыто данное окно).


