Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Borland Delphi 4.0 для начинающих - Создание приложения 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, Form1); 

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

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

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

Конструктор Create получает от вас в качестве параметра потомка TComponent, который и будет владельцем вашей формы. Обычно в качестве владельца выступает Application, чтобы все формы были автоматически закрыты по окончании работы приложения. Вы можете также передать параметр Nil, создав форму без владельца (или владеющую собой — как вам больше нравится), но тогда закрывать и уничтожать ее придется вам. В случае возникновения необрабатываемой ошибки такая форма останется в памяти, что не говорит о высоком профессионализме программиста...
В приведенном ниже коде Form1 указывает только на последнюю созданную форму. Если вам это не нравится, воспользуйтесь приведенным ниже кодом — возможно, он более точно отвечает вашим запросам:

	with TFormI.Create(Application) do 
    	    Caption:= 'New Form'; 

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



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

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

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

ActiveMDIChild
Это свойство возвращает дочерний объект TForm, имеющий в текущее время фокус ввода. Оно полезно, когда родительская форма содержит панель инструментов или меню, команды которых распространяются на открытую дочернюю форму.
Например, представим, что проект использует дочернюю форму, содержащую элемент TMemo, названный 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.

MDIChildren и MDIChildCount
Свойство MDIChildren является массивом объектов TForm, предоставляющих доступ к созданным дочерним формам. MDIChildCount возвращает количество элементов в массиве MDIChildren.
Обычно это свойство используется при выполнении какого-либо действия над всеми открытыми дочерними формами. Вот код сворачивания всех дочерних форм командой Minimize All.

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

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

TileMode
Это — свойство перечислимого типа, определяющее, как родительская форма размещает дочерние при вызове метода Tile. Используются значения tbHorizontal (по умолчанию) и tbVertical для размещения форм по горизонтали и вертикали.

WindowMenu
Профессиональные MDI-приложения позволяют активизировать необходимое дочернее окно, выбрав его из списка в меню. Свойство WindowMenu определяет объект TMenuItem, который Delphi будет использовать для вывода списка доступных дочерних форм.
Для вывода списка TMenuItem должно быть меню верхнего уровня. Это меню имеет свойство Caption, равное swindow.

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

MDI-методы TForm
Специфичные для MDI-форм методы перечислены ниже.
Arrangelcons выстраивает пиктограммы минимизированных дочерних форм в нижней части родительской формы.
Cascade располагает дочерние формы каскадом, так что видны все их заголовки.
Next и Previous переходит от одной дочерней формы к другой, как будто вы нажали <Ctrl+Tab> или <Ctrl+Shift+Tab>.
Tile выстраивает дочерние формы так, что они не перекрываются.

Пример MDI-приложения
В этом разделе мы расширим возможности созданной ранее программы просмотра изображений.

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

1. Выберите команду File/New Application, и появится пустое приложение.
2. Установите следующие свойства.

	Свойство               Значение
	-------------------------------
	Caption                Image Viewer
	FormStyle              fsMDIForm
	Name                   frmMDIParent           
	ShowHint               True

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

	Свойство               Значение
	-------------------------------
	Align                  alTop
	Caption                -

4. Поместите три компонента TSpeedButton в TPanel и назовите их spbtnLoad, spbtnStretch и spbtnCenter. Установите следующие их свойства.
	Свойство                   Значение
	------------------------------------
	spbtnLoad.Hint             Load
	spbtnLoad.Left             8
	spbtnLoad.Top              8
	spbtnStretch.AllowAlIUp    True
	spbtnStretch.Grouplndex    1
	spbtnStretch.Hint          Stretch
	spbtnStretch.Left          48
	spbtnStretch.Top           8
	spbtnCenter.AllowAlIUp     True
	spbtnCenter.Grouplndex     2
	spbtnCenter.Hint           Center
	spbtnCenter.Left           80
	spbtnCenter.Top            8

Свойства Glyph установите те же, что и для SDI-приложения.

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

	Свойство                   Значение
	------------------------------------
	Filter                     Bitmaps (*.bmp)]*.bmp
	Name                       opndlgLoad
	Options                    [ofPathMustExist,ofFileMustExist]

Теперь создадим дочернюю форму.

1. Выберите из меню File/New Form, и появится пустая форма.
2. Установите следующие ее свойства.

	Свойство                   Значение
	------------------------------------
	FormStyle                  fsMDIChild
	Name                       frmMDIChild
	Position                   poDefaultPosOnly
3. Поместите компонент TImage во вновь созданную форму и установите его следующие свойства.
	Свойство                   Значение
	------------------------------------
	Align                      alClient
	Name                       imgMain

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

1. Выберите команду Project/ Options, и появится диалоговое окно Project Options, показанное на рис. 1.14.
2. Выберите frmMDIChild в списке Auto-create forms.
3. Щелкните на кнопке. Форма frmMDIChild при этом будет перенесена в список Available forms.
4. Щелкните на кнопке ОК.

Теперь самое время сохранить проект, выбрав команду File/Save Project As. Сохраните Unit1 как MDIParent, а проект — как EgMDIApp.

Написание кода


Создав интерфейс, перейдем к написанию исходного текста приложения, который будет очень похож на код для SDI-приложения.
Сначала загрузим изображение. Введите следующий код в обработчик события 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:

    Action:= caFree; 

Компоненты TSpeedButton Stretch и Center выполняют те же функции, что и в SDI-приложении, однако их обработчики события OnClick следует изменить следующим образом

if not (ActiveMDIChild = Nil) then 
     if ActiveMDIChild 15 TfrmMDIChild then 
        TfrmMDIChild(ActiveMDIChild).imgMain.Stretch:= spbthStretch.Down;

и

if not (ActiveMDIChild = Nil) then 
    if ActiveMDIChild is TfrmMDIChild then 
        TfrmMDIChild(ActiveMDIChild).imgMain.Center:= spbthCenter.Down; 

Остается последняя проблема — состояния кнопок Stretch и Center одинаковы для всех дочерних форм Для решения этой задачи добавьте в обработчик события OnActivate класса TfrmMDIChild строки.

    frmMDIParent.spbtnStretch.Down:= imgMain.Stretch; 
    frmMDIParent.spbtnCenter.Down:= imgMain.Center; 

И, наконец, самый последний из последних штрихов— в модуле MDIChild добавьте после строки implementation строку.

    uses MDIParent; 

Компилируйте, запускайте и смотрите. MDI-приложение создано!


ПРЕДОСТЕРЕЖЕНИЕ: В этом примере присвоение нового значения свойству Down класса TSpeedButton вызывало событие Оn-click. Будьте осторожны при написании кода обработчика события, который генерирует новое событие путем присвоения значения свойству, ведь при этом можно создать бесконечную рекурсию.

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

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог