MDI-приложения

   
На этом шаге мы рассмотрим создание MDI-приложений.

Автоматическое создание форм
Динамическое создание форм
MDI-свойства TForm
MDI-события и MDI-методы TForm
Пример MDI-приложения

   
Термин MDI (Multiple Document Interface) дословно означает
многодокументный интерфейс и описывает приложения, способные загрузить и
использовать одновременно несколько документов или объектов. Примером
такого приложения может служить диспетчер файлов (File Manager).

   
Обычно MDI-приложения состоят минимум из двух форм -
родительской и
дочерней. Свойство родительской формы FormStyle
установлено равным
fsMDIForm. Стиль дочерней формы - fsMDIChild.

   
Родительская форма служит контейнером, содержащим дочерние формы,
которые заключены в
клиентскую область и могут перемещаться, изменять размеры,
минимизироваться или максимизироваться.
В приложении могут быть дочерние формы разных типов, например одна - для
обработки изображений, а
другая - для работы с текстом.

   
В MDI-приложении, как правило, требуется выводить несколько экземпляров
классов формы.
Поскольку каждая форма представляет собой объект, она должна быть создана
перед использованием
и освобождена, когда в ней больше не нуждаются. Delphi может делать
это автоматически,
а может предоставить эту работу программисту.
Автоматическое создание форм

   
По умолчанию при запуске приложения Delphi автоматически создает по
одному экземпляру
каждого класса форм в проекте и освобождает их при завершении программы.
Автоматическое создание
обрабатывается генерируемым Delphi кодом в трех местах.

   
Первое - раздел интерфейса в файле модуля формы.

type
   TForm1 = class (TForm)
   private
      {Закрытые объявления.}
   public
      {Открытые  объявления.}
   end;

В данном фрагменте кода объявляется класс TForm1.

   
Вторым является место, в котором описывается переменная класса:

    var Form1: TForm1;     .

   
Здесь описана переменная Form1, указывающая на экземпляр класса
TForm1
и доступная из любого модуля. Обычно она используется во время работы
программы для управления формой.

   
Третье место находится в исходном тексте проекта, доступ к которому можно
получить с помощью меню
View | Project Source. Этот код выглядит как:

    Application.CreateForm(TForm1, Forml);       .

   
Процесс удаления форм обрабатывается с помощью концепции владельцев
объектов: когда объект уничтожается,
автоматически уничтожаются все объекты, которыми он владеет. Созданная
описанным образом
форма принадлежит объекту Application и уничтожается при закрытии
приложения.

   
К оглавлению
Динамическое создание форм

   
Хотя автоматическое создание форм полезно при разработке однодокументных
приложений, при создании
MDI-приложении оно, как правило, неприемлемо.

   
Для создания нового экземпляра формы используйте конструктор
Create класса формы.
Приведенный ниже код создает новый экземпляр TForm1 во время
работы программы и
устанавливает его свойство Caption равным New Form:

    Form1:= TForm1.Create(Application);
    Form1.Caption:= 'New Form';     .

   
Конструктор Create получает в качестве параметра-потомка объект типа
TComponent, который
будет владельцем формы. Обычно в качестве владельца выступает
Application. Это
делается для того, чтобы все формы были автоматически закрыты по окончанию
работы приложения.
Можно также в качестве параметра использовать значение Nil, создав,
тем самым,
форму без владельца. Однако в этом случае закрывать и уничтожать ее должен
программист.
В случае возникновения необрабатываемой ошибки такая форма останется в
памяти.

   
Примечание. При разработке MDI-приложения метод
Show не нужен, так
как Delphi автоматически показывает все вновь созданные дочерние
MDI-формы.
В случае однодокументного приложения использование метода Show
обязательно.

   
Даже при динамическом создании форм Delphi попытается "помочь" в
создании экземпляра
каждой формы. Чтобы отказаться от них, нужно в диалоговом окне Project
Options (вызывается
при выполнении пункта меню Project | Options) удалить классы форм из
списка Auto-create forms:


Рис.1. Окно Project | Options

   
Если требуется получить доступ к отдельному дочернему экземпляру класса,
используйте свойство MDIChildren, описываемое в
следующем разделе.

   
К оглавлению
MDI-свойства TForm

   
Объект TForm имеет несколько свойств, специфичных для
MDI-приложений. Перечислим
их.

   

  • property ActiveMDIChild: TForm;. Это свойство возвращает дочерний
    объект TForm,
    имеющий в текущее время фокус ввода. Оно полезно, когда родительская
    форма содержит панель
    инструментов или меню, команды которых распространяются на открытую
    дочернюю форму.
    Например, представим, что проект использует дочернюю форму, содержащую
    элемент ТМеmо, названный
    memDailyNotes. Имя класса этой дочерней формы -TfrmMDIChild.
    Родительская форма
    содержит кнопку Clear в панели инструментов, которая удаляет
    содержимое memDailyNotes в
    активной дочерней форме. Вот как это реализуется:

    procedure TfrmMDIParent.spbtnClearClick(Sender: 
    TObject); 
    begin
    if not (ActiveMDIChild = Nil) then
    if ActiveMDIChild is TfrmMDIChild then
            TfrmMDIChild(ActiveMDIChild).memDailyNotes.Clear;
    end;
    

       
    В первой строке проверяется, равен ли ActiveMDIChild значению
    Nil, так как
    в этом случае обращение к объекту вызовет исключительную ситуацию.

       
    Примечание. Свойство ActiveMDIChild равно Nil в том
    случае,
    если нет открытых дочерних форм или свойство FormStyle не равно
    fsMDIForm.

       
    Поскольку ActiveMDIChild возвращает объект TForm,
    компилятор не имеет доступа
    к memDailyNotes - объекту TfrmMDIChild. Вторая строка проверят
    соответствие типов,
    то есть действительно ли свойство ActiveMDIChild указывает на объект
    TfrmMDIChild.
    Третья строка выполняет преобразование типа и вызывает метод Clear
    компонента memDailyNotes.

       

  • property MDIChildren[I: Integer]: TForm; property MDIChildCount: Integer;.
    Свойство MDIChildren
    является массивом объектов TForm, предоставляющих доступ к
    созданным дочерним формам. MDIChildCount возвращает
    количество элементов в массиве MDIChildren.

       
    Обычно это свойство используется при выполнении какого-либо действия над
    всеми открытыми дочерними формами. Вот
    код сворачивания всех дочерних форм при щелчке на кнопке с именем
    Button1:

    procedure TForm1.Button1Click(Sender: TObject);
    var
        iCount: Integer; 
    begin
        for iCount:= MDIChildCount-1 downto  0 do
          MDIChildren[iCount].WindowState:=  wsMinimized; 
    end;
    

       
    Если сворачивать окна в порядке возрастания элементов массива, цикл будет
    работать некорректно, так как после сворачивания
    каждого окна массив MDIChildren обновляется и пересортировывается,
    и в этом случае
    можно пропустить некоторые элементы.

  • property TileMode: TTileMode; TTileMode = (tbHorizontal, tbVertical);. Это
    свойство
    перечислимого типа, определяющее, как родительская форма размещает
    дочерние при вызове метода Tile.
    Используются значения tbHorizontal (по умолчанию) и tbVertical
    для размещения форм
    по горизонтали и вертикали.
  • property WindowMenu: TMenuItem;. Профессиональные
    MDI-приложения позволяют
    активизировать необходимое дочернее окно, выбрав его из списка в меню.
    Свойство WindowMenu
    определяет объект TMenuItem, который Delphi будет
    использовать для вывода
    списка доступных дочерних форм.

       
    Для вывода списка TMenuItem должно быть меню верхнего уровня. Это
    меню имеет свойство
    Caption, равное sWindow.

  •    

       
    К оглавлению
    MDI-события и MDI-методы TForm

       
    В MDI-приложении событие OnActivate запускается только при
    переключении
    между дочерними формами. Если фокус ввода передается из не
    MDI-формы в MDI-форму,
    генерируется событие OnActivate родительской формы, хотя ее
    свойство Active никогда и
    не устанавливается равным True. Эта странность на самом деле строго
    логична: ведь,
    если бы OnActivate генерировался только для дочерних форм, не было
    бы никакой
    возможности узнать о переходе фокуса ввода от другого приложения.

       
    Специфичные для MDI-форм методы перечислены ниже:

    • procedure ArrangeIcons; - выстраивает пиктограммы
      минимизированных дочерних форм
      в нижней части родительской формы;
    • procedure Cascade - располагает дочерние формы каскадом, так
      что видны
      все их заголовки;
    • procedure Next; procedure Previous; - переходит от одной дочерней
      формы
      к другой, как-будто нажаты клавиши Ctrl+Tab или Ctrl+Shift+Tab;
    • procedure Tile; - выстраивает дочерние формы так, что они не
      перекрываются.

       
    К оглавлению
    Пример MDI-приложения

       
    Создадим приложение, позволяющее просматривать графические изображения
    на отдельной
    форме. Для этого в новом проекте у формы зададим следующие свойства:

    • Caption: Image Viewer;
    • FormStyle: fsMDIForm;
    • Name: frmMDIParent;
    • ShowHint: True.

       
    Поместим компонент TPanel в форму. Установим у него следующие
    свойства:

    • Align: alTop;
    • Caption: (пусто).

       
    Поместим компонент TSpeedButton в TPanel и зададим у него
    следующие свойства:

    • Name: spbtnLoad;
    • Hint: Load;
    • Left: 8;
    • Top: 8.

    Подберем рисунок для созданной кнопки.

       
    Добавим в форму компонент TOpenDialog и установим следующие его
    свойства:

    • Filter: Bitmaps (*.bmp)|*.bmp;
    • Name: opndlgLoad;
    • Options: [ofPathMustExist,ofFileMustExist].

       
    Теперь создадим дочернюю форму. Выполним пункт меню File | New |
    Form и появится
    пустая форма. Установим следующие ее свойства:

    • FormStyle: fsMDIChild;
    • Name: frmMDIChild;
    • Position: poDefaultPosOnly.

       
    Поместим компонент TImage во вновь созданную форму и установим
    его следующие свойства:

    • Align: alClient;
    • Name: imgMain.

       
    Удалим дочернюю форму из списка автоматически создаваемых форм
    следующим образом:

    • выполним пункт меню Project | Options, и появится диалоговое окно
      Project Options,
      показанное на рисунке 1;
    • выберем форму frmMDIChild в списке Auto-create forms;
    • щелкнем на кнопке ">". Форма frmMDIChild при этом
      будет перенесена
      в список Available forms.

         
      Создав интерфейс, перейдем к написанию исходного текста приложения.

         
      Сначала загрузим изображение. Следующий код будет размещаться в
      обработчике события OnClick
      компонента spbtnLoad:

      procedure TfrmMDIParent.spbtnLoadClick(Sender: 
      TObject);
      begin
          if opndlgLoad.Execute then
           with TfrmMDIChild.Create(Application) do
           begin
              Caption:= opndlgLoad.FileName;
              imgMain.Picture.LoadFromFile(opndlgLoad.FileName);
              ClientWidth:= imgMain.Picture.Width;
              ClientHeight:=imgMain.Picture.Height;
           end;
      end;
      

         
      После запуска диалогового окна создается новый экземпляр дочерней формы и
      загружается файл
      изображения. После загрузки размеры дочерней формы изменяются так, чтобы
      можно было
      видеть все изображение.

         
      Поскольку модуль ссылается на тип TfrmMDIChild, находящийся в
      модуле MDIChild,
      то после строки implementation следует добавить еще одну строку:

         uses MDIChild;    .
      

         
      Теперь можно приступить к компиляции и запуску приложения. Однако по
      щелчку на кнопке Close дочерняя
      форма не закрывается, а сворачивается в пиктограмму. Чтобы заставить ее
      закрыться,
      следует в код обработчика OnClose класса TfrmMDIChild внести
      изменение свойства
      Action:

      procedure TfrmMDIChild.FormClose(Sender: TObject;
                   var Action: TCloseAction);
      begin
          Action:=caFree; //Закрытие формы.
      end;
      

         
      Внешний вид работающего приложения изображен на рисунке 2.


      Рис.2. Внешний вид приложения

         
      Текст этого примера можно взять здесь.

         
      К оглавлению

         
      Со следующего шага мы начнем знакомиться с графической системой
      Delphi.



    Вы можете оставить комментарий, или Трекбэк с вашего сайта.

    Оставить комментарий