Повторное использование форм в Delphi
Автор: Михаил
Голованов
Источник: RSDN Magazine #0
Опубликовано: 28.01.2002
Версия
текста: 1.2
Введение
Copy&Past
ActiveX
Forms
Frames
Repository
– репозитарий объектов
Заключение
Введение
Каждый раз, приступая к разработке нового проекта, я ловлю
себя на мысли, что когда-то я уже делал подобные формы. Поэтому я решил
поделиться несколькими мыслями о повторном использовании форм в Delphi. Я не
претендую на авторство описанных ниже методов, однако я еще не встречал
статьи, где данный вопрос был освещен достаточно полно (а может, я плохо
искал?).
Задачу повторного использования форм в Delphi можно разбить
на две части, а именно:
- Способы создания визуальных форм для многократного использования без
возможности быстрого внесения в них дальнейших изменений.
- Способы создания визуальных форм, имеющих возможность последующей гибкой
настройки.
Первая часть задачи актуальна при создании различных диалогов
и форм для решения типовых задач (например, logon-диалог). Внешний вид этих
диалогов практически стандартизован, но по каким-то причинам эти диалоги не
реализованы (или реализованы не совсем так, как хотелось бы) в составе
библиотек Delphi. Не менее актуальна эта подзадача при создании форм,
предполагающих возможность их последующего вызова из других языков и сред
программирования.
Вторая же часть задачи актуальна при проектировании форм,
состоящих из нескольких «кусков», либо форм, некоторые элементы которых должны
от проекта к проекту менять свои атрибуты (например, свойство Enabled или
Visible), причем в начале проектирования не всегда можно четко сказать, какие
из элементов управления будут менять свои свойства.
Copy&Past
Первое, что приходит в голову – простое копирование файлов
форм из проекта в проект. Это самый простой и достаточно эффективный способ,
однако не лишенный некоторых неудобств.
Простое копирование файлов форм из проекта в проект с
последующей их доработкой приводит к необходимости вручную обновлять эти файлы
во всех проектах. Данная операция носит рутинный характер и часто не бывает
выполнена из-за элементарной забывчивости.
От версии к версии Delphi формат файлов форм может меняться.
Это приводит к необходимости правки файлов при переходе на новые версии
Delphi.
Чаще всего создается некая общая папка с формами,
использующимися в различных проектах. Однако в состав Delphi входит средство,
выполняющее функции хранилища форм – репозитарий объектов.
Использование DLL как хранилища форм
При необходимости использовать формы в других средах
разработки или в различных версиях Delphi одновременно, можно "упаковать"
формы в динамически загружаемые библиотеки (DLL). Этот способ позволяет
распространять свои формы без предоставления исходного кода, что иногда может
пригодиться в коммерческих целях. При использовании данного способа в DLL
объявляется для экспорта ряд функций. Минимальный набор – функция модального
показа формы.
В качестве примера создадим простейшую DLL с формой. Для
этого в IDE выберем пункт File / New/Other, а в появившемся диалоге – пункт
меню “DLL Wizard”. Сохраним модуль под именем FormDLL. В заготовку библиотеки
добавим форму, которую затем и будем отображать в различных приложениях
(File/New/Form). На форме расположим ListBox, заполнив его тремя значениями, и
две кнопки – «OK» и «Отмена». Свойство формы BorderStyle установим в bsDialog,
а свойство кнопок ModalResult – в mrOk и mrCancel, соответственно. Внешний вид
формы приведен ниже.
Осталось написать код функции, отображающей форму и
возвращающей выбор пользователя. Ниже приведен полный исходный код модуля
FormDLL
library FormDLL;
uses
SysUtils, Windows,
Classes,
f_form in 'f_form.pas' ;
function ShowForm:Integer;stdcall;
begin
try
Form1:=TForm1.Create(nil);
Form1.ShowModal;
if Form1.ModalResult= idOk then
Result:=Form1.ListBox1.ItemIndex
else
Result:=-1;
finally
FreeAndNil(Form1);
end;
end;
exports
ShowForm;
begin
end.
|
Вот и все. Использовать такую DLL очень просто – нужно
поместить её в каталог нуждающегося в ней приложения. Можно организовать как
статическую загрузку DLL (при старте приложения), так и динамическую
(загружать и выгружать её по мере необходимости).
Для организации статической загрузки следует объявить функцию
из DLL следующим образом:
function ShowForm:Integer;external 'FormDLL.dll';
|
после чего функцию можно использовать обычным для Delphi способом.
Организация динамической загрузки немного сложнее. Сперва необходимо
соответствующим образом объявить процедурный тип:
TProc = function:integer;stdcall;
|
После этого можно загружать DLL и вызывать функцию:
var
H:Cardinal;
Proc:TProc;
Res:Integer;
Begin
H:=LoadLibrary('FormDLL.dll');
@Proc:=GetProcAddress(H,'ShowForm');
Res:=Proc;
FreeLibrary(H);
case Res of
0:Label1.Caption:='Вася';
1:Label1.Caption:='Вова';
2:Label1.Caption:='Петя';
else
Label1.Caption:='Никто';
end;
|
Данный код предельно упрощен, например, в нем нет проверки
ошибок при загрузке библиотеки.
ActiveX Forms
В ОС Windows широко используется технология
компонентно-ориентированного программирования ActiveX. В свою очередь Delphi
позволяет воспользоваться этой технологией как для проектирования самих
компонентов ActiveX, так и для их использования в приложениях. Я не буду здесь
углубляться в тонкости технологии ActiveX, просто предложу вашему вниманию
простой пример создания формы ActiveX и ее использования.
Что ж, начнем – File/New/Other. В появившемся диалоге
перейдем на закладку ActiveX и выберем элемент ActiveXForm. На экране появится
диалог установки параметров
Параметр VCL Class Name – класс-родитель для реализации всех
ActiveX-форм в Delphi
Параметр New ActiveX Name – имя класса формы.
Implementation Unit – имя модуля, содержащего описание формы
Project Name – Имя проекта
Threading Model – потоковая модель. Описывает поведение формы при
использовании ее несколькими потоками.
Оставим без изменений все параметры в диалоге и нажмем кнопку
OK. При этом мы получим заготовку проекта с пустой формой. Разместим на форме
ListBox и заполним его так же, как при использовании DLL. Далее нужно создать
метод для получения выбора пользователя. Для этого выберем пункт меню IDE
View/Type Library.
На экране появится редактор библиотеки типов, в которой
описываются интерфейсы, реализуемые в нашей форме. Выберем интерфейс
IActiveFormX и нажмем кнопку Method (всплывающая подсказка New Method). В
левую часть будет добавлен новый метод с именем Method1. Переименуем его в
Get_Result. В правой части диалога при этом будут отображаться параметры
метода. Закладка Parameters при этом позволяет определить набор входных и
выходных параметров, а также возвращаемое значение.
Добавим выходной параметр Res типа VARIANT*. Результат
представлен на рисунке. Нажав кнопку Refresh в том же диалоге, мы обновим
модуль реализации интерфейса формой ( в нашем проекте ActiveFormImpl1). Там
появится заготовка для написания кода метода. Код метода очень прост:
procedure TActiveFormX.Get_result(out Res: OleVariant);
begin
if ListBox1.ItemIndex >=0 then
Res:=ListBox1.Items[ListBox1.ItemIndex]
else
Res:='Никто';
end;
|
Осталось скомпилировать проект (Ctrl+F9) и зарегистрировать
ActiveX-форму в системе (Run/Register ActiveX Server). Можно пользоваться.
Чтобы воспользоваться полученным компонентом в Delphi,
необходимо установить его в палитру компонентов. Для этого предназначен пункт
меню Component/Import ActiveX Control. В диалоге импорта из представленного
списка выберем наш ActiveFormProj1 Library и установим его кнопкой Install. По
умолчанию он устанавливается на закладку ActiveX. Создадим проект нового
приложения File/New|Application и на его главную форму поместим компонент
ActiveFormX. Чтобы получить ввод пользователя, воспользуемся созданным методом
Get_Result интерфейса ActiveX-формы:
var
A:IActiveFormX;
Str:OleVariant;
begin
A:=ActiveFormX1.ControlInterface;
A.Get_Result(Str);
ShowMessage(Str);
end;
|
Frames
Два вышеописанных способа позволяют изготавливать формы,
которые можно использовать повторно. Однако использовать эти способы для
проектирования форм с возможностью гибкой настройки довольно трудоемко.
Начиная с 5-ой версии Delphi, появилась возможность строить формы из
заготовок-фреймов. Причем после вставки фрейма в форму есть возможность писать
обработчики событий элементов фрейма в форме. На одной форме можно разместить
несколько фреймов и организовать их взаимодействие друг с другом.
Воспользоваться фреймами очень просто. Этап первый – создать
фрейм (File/New/Frame). При этом в проект будет добавлен новый фрейм. Этап
второй – так же, как при проектировании форм, разместить на фрейме визуальные
и невизуальные компоненты. Возможно, написать обработчики событий для
компонентов для реализации нужного поведения компонентов фрейма. Этап третий –
поместить фрейм на форму. Для этого на закладке Standart палитры компонентов
следует выбрать значок Frames и кликнуть мышью на форме. Появится список
фреймов, включенных в данный проект. Выбрать нужный фрейм. Все. В сочетании с
репозитарием объектов фреймы позволяют свести к минимуму необходимость
повторной разработки элементов пользовательского интерфейса.
Repository – репозитарий объектов
Наконец, последний способ многократно использовать формы (а
так же и фреймы)– использование репозитария объектов Delphi. Репозитарий
объектов – это централизованное хранилище форм, фреймов и заготовок проектов,
предназначенных для повторного использования в среде Delphi. Форма, которую мы
видим при выборе пункта меню File/New/Other, отображает содержимое
репозитария. Добавить форму или фрейм в репозитарий не составляет никакого
труда. Просто щелкните на них правой кнопкой мыши и выберите пункт меню “Add
to repository”. На экран будет выведен диалог добавления.
Элементы этого диалога достаточно понятны:
Список Forms – список форм и фреймов, доступных для добавления.
Title – наименование под которым элемент будет виден в репозитарии
Description – описание элемента
Page – страница, на которой элемент будет отображаться.
Author – сведения об авторе данного элемента.
Поместить форму из репозитария объектов в проект несложно,
более того, вы это фактически уже неоднократно делали – File/New/Other.
Обратим внимание только на группу переключателей внизу формы: их три Copy,
Inherit, Use. Copy – копирует форму из репозитария в новый модуль. Inherit –
наследует класс объекта, описанного в репозитарии. Use – просто включает
модуль из репозитария в текущий проект.
Диалог настройки страниц репозитария и добавленных объектов
вызывается пунктом меню IDE Tools/Repository. Если вы любитель покопаться во
внутренностях Delphi, то скажу, что описание репозитария хранится в файле
delphi32.dro. Файл описания имеет формат ini файла Windows.
Заключение
Ну вот и все, надеюсь, вам понравилось. Если у вас есть
предложения и пожелания по данной статье, я буду рад получить их по адресу
mgoblin@mail.ru