Сообщений 0    Оценка 96        Оценить  
Система Orphus

Повторное использование форм в Delphi

Автор: Михаил Голованов
Источник: RSDN Magazine #0
Опубликовано: 28.01.2002
Исправлено: 13.03.2005
Версия текста: 1.2.1
Введение
Copy&Paste
ActiveX Forms
Frames
Repository – репозитарий объектов
Заключение

Введение

Каждый раз, приступая к разработке нового проекта, я ловлю себя на мысли, что когда-то я уже делал подобные формы. Поэтому я решил поделиться несколькими мыслями о повторном использовании форм в Delphi. Я не претендую на авторство описанных ниже методов, однако я еще не встречал статьи, где данный вопрос был освещен достаточно полно (а может, я плохо искал?).

Задачу повторного использования форм в Delphi можно разбить на две части, а именно:

Первая часть задачи актуальна при создании различных диалогов и форм для решения типовых задач (например, logon-диалог). Внешний вид этих диалогов практически стандартизован, но по каким-то причинам эти диалоги не реализованы (или реализованы не совсем так, как хотелось бы) в составе библиотек Delphi. Не менее актуальна эта подзадача при создании форм, предполагающих возможность их последующего вызова из других языков и сред программирования.

Вторая же часть задачи актуальна при проектировании форм, состоящих из нескольких «кусков», либо форм, некоторые элементы которых должны от проекта к проекту менять свои атрибуты (например, свойство Enabled или Visible), причем в начале проектирования не всегда можно четко сказать, какие из элементов управления будут менять свои свойства.

Copy&Paste

Первое, что приходит в голову – простое копирование файлов форм из проекта в проект. Это самый простой и достаточно эффективный способ, однако не лишенный некоторых неудобств.

Простое копирование файлов форм из проекта в проект с последующей их доработкой приводит к необходимости вручную обновлять эти файлы во всех проектах. Данная операция носит рутинный характер и часто не бывает выполнена из-за элементарной забывчивости.

От версии к версии 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' {Form1};

{$R *.res}

{Функция отображения формы}
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;

{Функции, экспортируемые из DLL}
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


Эта статья опубликована в журнале RSDN Magazine #0. Информацию о журнале можно найти здесь
    Сообщений 0    Оценка 96        Оценить