В Delphi 5 введен новый компонент, который помогает поддерживать стилистическое единство приложения. Это Frame — фрейм. Он представляет собой нечто среднее между панелью и формой. С формой его роднит то, что он:
С панелью фрейм роднит то, что он:
Таким образом, фрейм — это панель, т.е. некий фрагмент окна приложения, но способный переноситься на разные формы, в разные приложения и допускающий использование преимуществ наследования.
Начать проектирование нового фрейма можно командой File | New Frame
или командой File | New
и выбором пиктограммы Frame
на странице
New
окна Депозитария. В обоих случаях перед вами откроется окно фрейма,
подобное окну формы, а в Редакторе Кода вы увидите текст заготовки модуля
фрейма:
unit Unit2; Interface // Открытый интерфейс фрейма {Список подключаемых модулей} uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; {Объявление класса фрейма} type TFrame2 = class(TFrame) {Сюда Delphi помещает объявления компонентов, размещаемых на фрейме. Не добавляйте сюда ничего вручную} private // Закрытый раздел класса {Private declarations} {Сюда могут помещаться объявления переменных, функций и процедур, включаемых в класс фрейма, но не доступных для других модулей} public // Открытый раздел класса {Public declarations} {Сюда могут помещаться объявления переменных, функций и процедур, включаемых в класс фрейма и доступных для других модулей} end; {Сюда могут помещаться объявления типов, констант, переменных, функций и процедур, к которым будет доступ из других модулей, но которые не включаются в класс фрейма. Они будут едины для всех объектов фреймов} implementation // Реализация модуля {$R *.DFM} {Сюда могут помещаться предложения uses, объявления типов, констант, переменных, к которым не будет доступа из других модулей. Они будут едины для всех объектов фреймов. Тут же должны быть реализации всех объявленных в разделе interface функций и процедур, а также могут быть реализации любых дополнительных, не объявленных ранее функций и процедур} end.
Комментарии в приведенном тексте поясняют, куда и что можно помещать в модуле. Те переменные, объявления которых вы поместите в объявление класса, будут индивидуальны для каждого объекта фрейма. Объявления имеют обычный для класса вид. Например:
A: integer;
Переменные, объявления которых вы поместите вне объявления класса, будут едины для всех объектов фрейма. Они объявляются как обычные переменные. Например:
var A: integer;
На фрейм вы можете так же, как на форму, переносить и размещать любые компоненты, устанавливать их свойства, писать обработчики их событий и т.п.
Давайте создадим чисто тестовый фрейм, чтобы на его примере продемонстрировать проектирование фрейма, его использование, доступ к различным его элементам и наследование свойств.
Начните новое приложение и выполните команду File | New Frame
.
Перенесите на фрейм групповую панель GroupBox (см.
раздел 7.2). Перенесите
на панель метку Label и три кнопки Button. Разместите все эти
компоненты примерно так, как показано на рис. 7.9, изменив соответственно их
надписи (Caption) и назвав кнопки соответственно BSetup, BInc,
BShow.
Рис. 7.9 Пример фрейма |
Давайте введем в наш модуль в разных местах объявления целых переменных, а в обработчики событий кнопок введем операторы, манипулирующие ими и отображающие результат в метке. Модуль фрейма может приобрести следующий вид:
unit UFrame; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFrame2 = class(TFrame) GroupBox1: TGroupBox; BSetup: TButton; Label1: TLabel; BInc: TButton; BShow: TButton; procedure BSetupClick(Sender: TObject); procedure BIncClick(Sender: TObject); procedure BShowClick(Sender: TObject); private { Private declarations } {Переменная А видна только в данном модуле} A: integer; public { Public declarations } {Переменная В видна в других модулях через объект фрейма} B:integer; end; {Переменная С видна в других модулях} var C:integer; implementation {$R *.DFM} {Переменная D видна только в данном модуле} var D:integer; procedure TFrame2.BSetupClick(Sender: TObject); begin A:=1; B:=1; C:=1; D:=1; Label1.Caption := 'A=' + IntToStr(A) + ' B=' + IntToStr(B) + ' C=' + IntToStr(C) + ' D=' + IntToStr(D); end; procedure TFrame2.BIncClick(Sender: TObject); begin Inc(A); Inc(B); Inc(C); Inc(D); Label1.Caption := 'A=' + IntToStr(A) + ' B=' + IntToStr(B) + ' C=' + IntToStr(C) + ' D=' + IntToStr(D); end; procedure TFrame2.BShowCiick(Sender: TObject); begin Label1.Caption := 'A='+IntToStr(A) + ' B=' + IntToStr(B) + ' C=' + IntToStr(C) + ' D=' + IntToStr(D); end; end.
В модуле введены переменные:
Введенные в модуль обработчики щелков на кнопках обеспечивают сброс всех переменных на 1 (процедура TFrame2.BSetupClick), увеличение всех переменных на 1 (процедура TFrame2.BIncClick), отображение текущего состояния переменных (процедура TFrame2.BShowClick).
Теперь давайте разместим несколько экземпляров фрейма на форме. Перейдите в
основную форму приложения и выберите в палитре компонентов Frame (первая
кнопка на странице Standard
). Появится диалоговое окно, в котором будет
спрашиваться, какой фрейм вы хотите разместить на форме. Выберите ваш фрейм
Frame2 и он появится на форме. Можете отбуксировать его, как обычный
компонент, в нужное место. Повторите эту операцию еще раз и разместите на форме
второй фрейм (рис. 7.10). Добавьте кнопку и метку, задав ее свойство Align
равным alTop и свойство Alignment равным taCenter.
Вы получили форму, содержащую два объекта — фрейма. Можете изменить какие-то
свойства объектов. Например, изменить надписи (Caption) групповых панелей
GroupBox (см. рис. 7.10 а).
Рис. 7.10 Пример использования фреймов; форма (а) и приложение в работе (б) |
а) | |
б) |
После того, как вы изменили эти свойства, они перестают наследоваться из класса фрейма. А остальные свойства продолжают наследоваться. В этом легко убедиться. Перейдите в модуль фрейма (рис. 7.9) и измените у фрейма стиль шрифта (Font.Style) на жирный. Вы увидите, что в обоих объектах главной формы шрифт тоже станет жирным. Верните во фрейме шрифт на обычный и он синхронно изменится в объектах. А теперь установите в одном из фреймов на форме шрифт жирным. Повторив после этого эксперимент с изменением шрифта в исходном фрейме, вы увидите, что теперь шрифт меняется только в том объекте формы, в котором вы его не изменяли вручную. Таким образом объекты наследуют только те свойства, которые не были в них установлены вручную.
Теперь давайте напишем обработчик щелчка на кнопке главной формы. Прежде всего взгляните на текст модуля этой формы. Вы увидите, что в нем в описании класса формы появились две строки:
Frame21: TFrame2; Frame22: TFrame2;
Это объявления объектов фреймов. Все компоненты, размещенные на фреймах, напрямую из модуля формы не видны. Доступ к ним можно получить только через объекты Frame21 и Frame22. Имена компонентов, размещенных во фреймах, локальные. Несмотря на то, что во фреймах имеются кнопки с именами BShow, вы можете назвать тем же именем кнопку на форме.
Поместите в обработчик щелчка на этой кнопке оператор
Label1.Caption := 'В(Frame21)='+IntToStr(Frame21.B) + ' B(Frame22)='+IntToStr(Frame22.B) + ' C=' + IntToStr(C);
Он отображает в метке Label1 значения переменных В объектов фреймов и значение переменной С класса фрейма. Значения переменных А и D отобразить невозможно, поскольку эти переменные недоступны из внешних модулей. Если вы попытаетесъ отобразить их значения, компилятор выдаст сообщение об ошибке.
Сохраните ваше приложение, оттранслируйте его и выполните. Манипулируя кнопками вы легко сможете убедиться (см. рис. 7.10 б), что переменные А и В независимы для каждого фрейма, а переменные С и D одинаковы. Точнее оба фрейма оперируют с одними и теми же переменными С и D.
Рассмотренный фрейм не имел никакого практического значения. Давайте построим
более полезный пример. Во многих диалогах при установке различных опций
фигурирует фрагмент, фрейм которого показан на рис. 7.11. Фрагмент включает в
себя панель GroupBox, окно редактирования, в котором пользователь может
написать имя файла, и кнопку Обзор
, которая позволяет выбрать файл в
стандартном диалоге Windows открытия файла. Если путь к файлу длинный, то полное
имя файла с путем может не помещаться в окне редактирования. Поэтому полезно для
него предусмотреть всплывающее окно, которое отображало бы полное имя файла
вместе с путем и всплывало бы, если пользователь задержал над ним курсор мыши.
Давайте построим подобный фрейм и опробуем его в работе. Начните новое
приложение и выполните команду File | New Frame
. Перенесите на фрейм
групповую панель GroupBox. Перенесите в эту панель окно редактирования
Edit, кнопку Button, диалог OpenDialog (см.
раздел 8.2) и компонент
ApplicationEvents — перехватчик событий приложения (см.
раздел 9.4).
Расположите компоненты примерно так, как показано на рис. 7.11.
Рис. 7.11 Фрейм выбора файла |
Задайте в свойстве Filter диалога OpenDialog какой-то фильтр файлов, например, «все файлы|*.*». Свойство ShowHint (показать ярлычок подсказки) в компонентах Edit и Button установите в true. В кнопке Button кроме того можете написать текст подсказки Hint, например, «Выбор файла|Выбор файла из каталога».
В обработчик события OnShowHint компонента ApplicationEvents занесите оператор:
if HintInfo.HintControl = Edit1 then begin HintStr := Edit1.Text; ApplicationEvents1.CancelDispatch; end;
Этот оператор в момент, когда должен отображаться ярлычок, проверяет, не является ли источником этого события (HintInfo.HintControl) окно редактирования Edit1. Если да, то текст ярлычка (HintStr) подменяется текстом, содержащимся в окне редактирования и принимаются меры (метод CancelDispatch), чтобы это событие не обрабатывалось другими компонентами ApplicationEvents, которые могут присутствовать в приложении. Пояснение всех этих операций см. в разделе 9.4.
Теперь введите в модуль фрейма глобальную переменную FileName типа string, в которой будет отображаться выбранный файл. В обработчик щелчка на кнопке введите оператор
if OpenDialog1.Execute then begin Edit1.Text := OpenDialog1.FileName; FileName := OpenDialog1.FileName; end;который вызывает диалог открытия файла и помещает в окно редактирования Edit1 и в переменную FileName имя файла, выбранного пользователем, вместе с путем к нему.
В обработчик события OnExit компонента Edit1 поместите оператор
FileName := Edit1.Text;заносящий в переменную FileName имя файла, если пользователь не пользовался диалогом, а просто написал в окне имя файла.
Программирование фрейма закончено. Теперь создайте тестовую программу,
использующую этот фрейм. Предположим, что вам нужно разместить на форме два
фрагмента, описанных вами во фрейме. Перейдите в основной модуль вашего
приложения и разместите на форме так, как вы уже делали, два объекта вашего
фрейма (рис. 7.12 а).
Рис. 7.12 Приложения с двумя фреймами выбора файла: его форма (а) и приложение во время выполнения (б) |
а) | |
б) |
Теперь вы можете поменять что-то в размещенных на форме объектах фреймах, изменить надписи групповых панелей, шрифты и т.п. Сохраните ваше приложение вместе с модулем фрейма, оттранслируйте его и проверьте в работе (рис. 7.12 б).
Вы разработали достаточно полезный фрейм и хотели бы его сохранить для
использования в будущих приложениях. Это легко сделать, внеся его в Депозитарий.
Щелкните на своем фрейме правой кнопкой мыши и выберите из всплывшего меню
раздел Add To Repository
. Перед вами откроется окно, представленное на
рис. 7.13. В верхнем его окне редактирования Title
вы должны написать
название вашего фрейма — подпись под его пиктограммой при входе в Депозитарий. В
следующем окне — Description
можете написать более развернутое пояснение.
Его может увидеть пользователь, войдя в Депозитарий, щелкнув правой кнопкой мыши
и выбрав во всплывшем меню форму отображения View Details
. В выпадающем
списке Page
вы можете выбрать страницу Депозитария, на которой хотите
разместить пиктограмму своего фрейма. Впрочем, вы можете указать и новую
страницу с новым заголовком (Мои формы
на рис. 7.13). В результате она
появится в Депозитарии.
В окне Author
вы можете указать сведения о себе как об авторе.
Наконец, если стандартная пиктограмма вас не устраивает, вы можете выбрать
другую, щелкнув на кнопке Browse...
. После выполнения всех этих процедур
щелкните на кнопке OK
и ваш фрейм окажется включенным в Депозитарий.
Теперь вы можете использовать его в последующих ваших приложениях. Для этого
вам надо будет выполнить команду File | New
и в открывшемся диалоговом
окне New Items
отыскать ваш фрейм (рис. 7.14).
Рис. 7.13 Окно добавления фрейма в Депозитарий |
Рис. 7.14 Окно New Itemsс включенным новым фреймом |
В нижней части окна расположены три радиокнопки, которые определяют, как
именно вы хотите заимствовать фрейм из Депозитария: Сору
— копировать,
Inherit
— наследовать, Use
— использовать. Если включена кнопка
Сору
, то файлы фрейма просто будут скопированы в ваше приложение. При этом
никакой дальнейшей связи между исходным фреймом и копией не будет. Вы можете
спокойно изменять свойства вашей копии и это никак не отразится на фрейме,
хранящемся в Депозитарии. А если вы в дальнейшем что-то измените во фрейме,
хранящемся в Депозитарии, то эти изменения никак не затронут вашего приложения,
куда вы до этого скопировали фрейм.
При включенной кнопке Inherit
вы получите в своем проекте фрейм,
наследующий размещенному в Депозитарии. Это значит, что если вы что-то измените
во фрейме, хранящемся в Депозитарии, то это отразится при перекомпиляции во всех
проектах, которые наследуют этот фрейм. Однако, изменения в наследуемых фреймах
никак не скажутся на свойствах фрейма, хранящегося в Депозитарии.
При включенной кнопке Use
вы получите режим использования. В этом
случае в ваш проект включится сам фрейм, хранящийся в Депозитарии. Значит любое
изменение свойств фрейма, сделанное в вашем проекте, отразится и на хранящемся в
Депозитарии фрейме, и на всех проектах, наследующих или использующих этот фрейм
(при их перекомпиляции).
Таким образом, режим Inherit
целесообразно использовать для всех
модулей вашего проекта, а режим Use
— для изменения базового фрейма.
Тогда усовершенствование вами базового фрейма будет синхронно сказываться на
всех модулях проекта при их перекомпиляции.
Введенный в Delphi 5 компонент фрейм благодаря использованию наследования позволяет обеспечить единство стилистических решений не только внутри приложения, но и в рамках серии разрабатываемых вами приложений. Вам достаточно один раз разработать какие-то часто применяемые фреймы, включить их в Депозитарий, а затем вы можете использовать их многократно во всех своих проектах.