Лабораторная работа № 18 Разработка компонент
Цель: Научиться создавать новый компонент
Delphi предоставляет возможность программисту создать свой собственный компонент, поместить его на одну из страниц палитры компонентов и использовать при разработке приложений точно так же, как и другие компоненты Delphi.
Процесс создания компонента может быть представлен как последовательность следующих этапов:
1. Определение назначения компонента и выбор базового класса
2. Создание модуля компонента
3. Тестирование компонента
4. Добавление компонента в пакет компонентов
Процесс создания компонента программиста рассмотрим на примере разработки компонента, назовем его NEdit, предназначенного для ввода и редактирования дробного числа.
Определение назначения компонента и выбор базового класса
Приступая к разработке нового компонента, следует четко сформулировать назначение компонента. Затем необходимо определить, какой из компонентов Delphi наиболее близок по своему назначению, виду и функциональным возможностям к компоненту, который будет разрабатываться. Именно этот компонент следует выбрать в качестве базового.
Создание модуля компонента
Чтобы создать модуль компонента, надо из меню Component выбрать команду New Component и в поля появившегося диалогового окнаNew.Component ввести информацию о создаваемом компоненте.
Поле Ancestor type должно содержать базовый тип для создаваемого компонента, задать который можно непосредственным вводом имени типа или выбором из раскрывающегося списка. Для разрабатываемого компонента базовым компонентом является компонент Edit (поле редактирования) Поэтому базовым типом для типа компонента является тип TEdit.
В поле Class Name нужно ввести имя класса разрабатываемого компонента, TNEdit.
В поле Palette Page надо ввести имя палитры компонентов (по умолчанию Samples), в которую после создания компонента будет добавлен его значок Название палитры можно выбрать из раскрывающегося списка. Если в поле Palette Page ввести имя еще не существующей палитры, то непосредственно перед добавлением компонента палитра с указанным именем будет создана.
В поле Unit file name находится автоматически сформированное имя файла модуля создаваемого компонента. Delphi присваивает модулю компонента имя, совпадающее с именем типа компонента, но без буквы Т
После щелчка на кнопке Create Unit к текущему проекту добавляется сформированный Delphi-модуль, представляющий собой заготовку модуля компонента. Текст этого модуляприведен ниже.
unit NEdit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TNEdit = class(TEdit)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TNEdit]) ;
end;
end.
В объявлении нового класса указан только тип родительского класса. В раздел реализации помещена процедура Register, которая используется во время установки созданного программистом компонента в указанную палитру Delphi для регистрации нового класса.
В сформированное Delphi объявление класса нового компонента нужно внести дополнения: объявить поле данных свойства, функцию доступа к полю данных и процедуру установки значения поля данных, свойство, конструктор, деструктор. Если на некоторые события компонент должен реагировать не так, как базовый, то в объявление класса нужно поместить описание соответствующих процедур обработки событий.
Ниже приведен текст модуля NEdit после внесения всех необходимых изменений.
// Publised должно быть Single, Double
unit NEdit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TNEdit = class(TEdit)
private
{ Private declarations }
FNumb: single; // число, находящееся в поле редактирования
// Это описание функции доступа
//и процедуры установки поля FNumb
function GetNumb: single;
procedure SetNumb(value:single) ;
protected
{ Protected declarations }
procedure Keypress(var Key: Char); overrider;
public
{ Public declarations }
published
{ Published declarations }
constructor Create(AOwner:TComponent); overrider;
property
Numb: single
read GetNumb
write SetNumb;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples',[TNEdit]) ;
end;
constructor TNEdit.Create(AOwner:TComponent) ;
begin
// don't forget to call the ancestors' constructor
inherited Create(AOwner);
end;
function TNEdit.GetNumb:single;
begin
try
Result:=StrToFloat(text) ;
except
on EConvertError do begin
Result:=0;
text:='';
end;
end;
end;
procedure TNEdit.SetNumb(Value:single) ;
begin
FNumb:=Value;
Text;=FloatToStr(value);
end;
procedure TNEdit.Keypress(var key:char);
begin
case key of
'0'.. '9', #8, #13:;
{Для России стандартный разделитель целой и дробной частей числа — запятая }
',': if Pos(',',text)<> then key:=#0;
'-': if Length(text)<>0 then key:=#0;
else key:=#0;
end;
inherited Keypress(key);
end;
end.
В описание класса TNEdit добавлено объявление свойства Numb, которое представляет собой число, находящееся в поле редактирования. Для хранения значения свойства Numbиспользуется поле FNumb. Функция GetNumb необходима для доступа к полю FNumb, а процедура setNumb — для установки значения свойства.
Конструктор класса TNEdit сначала вызывает конструктор родительского класса (TEdit), присваивает значение свойству Text, затем устанавливает значение свойства Numb.
Реакция компонента NEdit на нажатие клавиши клавиатуры определяется событийной процедурой TNEdit.Keypress, которая замещает соответствующую процедуру базового класса. В качестве параметра TNEdit.Keypress получает код нажатой клавиши. Перед вызовом процедуры обработки события onKeypress родительского класса код нажатой клавиши проверяется на допустимость. Если нажата недопустимая для компонента NEdit клавиша (не цифра, не запятая, не знак «минус» и не ), то код символа заменяется на ноль.
В тексте программы дробная часть числовой константы от целой части отделяется точкой. Во время работы программы, при вводе исходных данных, пользователь может отделить дробную часть числа от целой точкой или запятой. Какой из этих двух символов является допустимым, зависит от настройки Windows.
Так, например, если в настройке Windows указано, что разделитель целой и дробной частей числа — запятая (для России это стандартная настройка), и если во время работы приложения пользователь введет в поле редактирования, например, строку 12.34, то при выполнении инструкции
p:=StrToFloat(Editl.Text)
возникает исключительная ситуация, так как при указанной выше настройке Windows аргумент функции StrToFloat, содержимое поля ввода, не является дробным числом. (Предполагается, р— это переменная типа Real, a Edit1 — имя одного из полей ввода приложения.)
Тестирование модуля компонента
Перед добавлением нового компонента в палитру необходимо всесторонне его проверить. Для этого надо создать приложение, использующее данный компонент.
Во время создания формы приложения нельзя добавить к форме компонент, значка которого нет на палитре. Однако такой компонент может быть добавлен к форме динамически, то есть во время работы приложения.
Создается тестовое приложение обычным образом: сначала форма приложения, затем — модуль приложения.
Форма содержит две метки и командную кнопку. Первая метка — информационное сообщение, вторая метка (на рисунке она выделена) используется для вывода числа, введенного в поле редактирования. Самого поля редактирования компонента NEdit, в форме нет, он будет создан динамически во время работы программы, но для него оставлено место над полем метки.
После создания формы в образованный с помощью Delphi модуль приложения надо внести следующие изменения:
1. В список используемых модулей добавить имя модуля тестируемого компонента
2. В объявление класса формы приложения, в раздел public declaration, добавить объявление тестируемого компонента
3. Для формы приложения создать процедуру обработки события onCreate, которая вызовом конструктора тестируемого компонента создаст компонент и установит значения его свойств
Ниже приведен модуль приложения тестирования компонента NEdit.
unit test_u;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
NEdit, StdCtrls;
type
TFormI = class(TForm)
Label 1: TLabel;
Buttoni: TButton;
Label2: TLabel;
procedure FomCreate (Sender: TObject);
procedure ButtonlClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Forml: TForm1;
n:TNedit;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObj ect) ;
begin
n:=TNEdit.Create(self);
n.parent:=self;
n. left:=150;
n.top:=10;
end;
procedure TFormI.ButtonlClick(Sender: TObj ect) ;
begin
Label1.caption:=FloatToStr(n.numb) ;
end;
end.
Тестируемый компонент создается процедурой обработки события FormCreate (создание формы) посредством вызова конструктора компонента, которому в качестве параметра передается значение self, показывающее, что владельцем компонента является форма приложения. После создания компонента обязательно должен быть выполнен важный шаг: свойству parent присвоено значение. В данном случае тестируемый компонент находится в форме приложения, поэтому свойству Parent присваивается значение self.
Установка компонента
Чтобы значок компонента появился на палитре, компонент должен быть добавлен в один из пакетов (Packages) компонентов Delphi. Пакет компонентов — это файл с расширением DPK (Delphi PacKage file). Например, в пакете dclstd30.dpk находятся стандартные компоненты Delphi.
Во время добавления компонента в пакет, Delphi использует модуль компонента и файл ресурсов компонента, в котором должен находиться битовый образ значка компонента. Необходимо, чтобы имя файла ресурсов компонента совпадало с именем файла модуля компонента, расширение — DCR
(Dynamic Component Resourse). Битовый образ, находящийся внутри файла ресурсов, должен иметь имя, совпадающее с именем класса компонента.
Создание файла ресурсов компонента
Создать файл ресурсов компонента можно при помощи программы Image Editor, которая запускается выбором команды Image Editor из меню Tools.
Чтобы создать файл ресурса, надо из меню File выбрать команду New. Затем, из появившегося списка, тип создаваемого файла — ComponentResourse File.
После этого из меню Resourse надо выбрать команду New, и из появившегося списка тип ресурса —Bitmap. В результате этих действий на экране появляется диалоговое окно Bitmap Properties в котором надо установить характеристики битового образа кнопки компонента (размер 24 на 24 пикселя, количество цветов — 16) и щелкнуть на кнопке ОК.
В результате этих действий в создаваемый файл ресурсов будет добавлен новый ресурс — битовый образ с именем Bitmap 1. При двойном щелчке на имени ресурса (Bitmapl) раскрывается окно редактирования битового образа, в котором можно, используя инструменты и палитру Image Editor, нарисовать нужную картинку.
Изображение в окне графического редактора можно увеличить. Для этого надо из меню View выбрать команду Zoom In.
Цвет правого нижнего пикселя определяет «прозрачный» цвет. Элементы значка компонента, закрашенные этим цветом, после помещения значка на палитру компонентов Delphi не видны.
Перед сохранением файла ресурсов битовому образу надо присвоить имя, которое должно совпадать с именем класса компонента. Чтобы задать имя битового образа, надо щелкнуть правой кнопкой мыши на имени битового образа (Bitmapl), выбрать Rename, ввести новое имя и нажать .
Созданный файл ресурсов сохраняется на диске обычным образом, то есть выбором команды Save из меню File.
Замечание
Файл ресурсов компонента надо сохранить в том каталоге, где находится файл модуля компонента.
Следует еще раз обратить внимание на то, что имя файла ресурсов должно совпадать с именем модуля компонента, а имя битового образа — с именем класса компонента.
Установка компонента
После создания файла ресурса можно приступить к установке компонента. Для этого надо из меню Componentвыбрать команду Install Component и заполнить поля в появившемся диалоговом окне
Поле Unit file name (имя файла модуля) должно содержать имя файла модуля компонента, которое можно ввести непосредственно с клавиатуры или, после щелчка на кнопке Browse..., при помощи стандартного диалога выбора файла.
Поле Search path (путь поиска) должно содержать разделенные точкой с запятой имена каталогов, в которых Delphiво время установки компонента будет искать необходимые файлы, в частности, файл ресурса компонента. Если имя файла модуля в поле Unit file name было введено выбором файла из списка, полученного при помощи кнопки Browse..., то Delphi автоматически добавляет в поле Search path имя каталога, в котором находится модуль компонента.
Файл ресурса компонента должен находиться в одном из каталогов перечисленных в поле Search path. Если его там нет, то компоненту будет назначен значок его родительского класса.
Поле Package file name должно содержать имя пакета, в который будет.установлен компонент. Предопределенным пакетом для создаваемых программистом компонентов является пакет dclusr30.dpk.
Поле Package description содержит краткое описание пакета. Для пакета dclusr30.dpk это текст: Delphi User'sComponents (компоненты пользователя Delphi).
После заполнения перечисленных полей и щелчка на кнопке ОК начинается процесс установки. Сначала на экране появляется окно Confirm, в котором Delphi просит подтвердить обновление пакета: Package ... will be rebuilt. Continue? (Пакет... будет обновлен. Продолжить?).
После выбора Yes процесс установки продолжается. Если он завершается успешно, то на экране появляется информационное сообщение о том, что в результате обновления пакета палитра компонентов обновлена, то есть в нее добавлен значок нового компонента, и новый компонент зарегистрирован.
После установки компонента в пакет на экране появляется окно Package, окно редактора пакета, в котором перечислены компоненты, находящиеся в пакете.
На этом процесс установки компонента заканчивается, в указанной при создании модуля компонента палитре появляется значок компонента.
Ошибки при установке компонента
Во время работы над новым компонентом, наиболее частой ошибкой является попытка установить (переустановить) компонент, который уже находится в одном из пакетов (обычно такое желание возникает после внесения изменений в модуль компонента). В этом случае Delphi выводит сообщение:
The package already contains unit named... (Пакет уже содержит модуль, который называется...) и процесс установки завершается. Для того чтобы преодолеть эту ошибочную ситуацию и установить компонент в нужный пакет или установить в пакет обновленную версию компонента, надо сначала удалить компонент из пакета, затем установить его снова.
Удаление компонента
Удалить компонент из пакета можно при помощи редактора пакета.
Чтобы запустить редактор пакета, надо из меню Component выбрать команду Install Packages (установленные пакеты), в появившемся окне (рис. 166), из списка Design packages, выбрать нужный пакет и щелкнуть на командной кнопке Edit....
В появившемся окне, в ответ на запрос Close this dialog and open... (Закрыть этот диалог и открыть пакет...), надо щелкнуть на кнопке Yes. В результате этого открывается окно редактора пакета, в котором на вкладке Contains (содержимое) перечислены компоненты пакета.
Чтобы удалить компонент из пакета, надо выбрать этот компонент и щелкнуть на командной кнопке Remove.
После удаления компонента из пакета щелчком на кнопке Remove нужно обязательно выполнить перекомпиляцию пакета, для чего надо щелкнуть на командной кнопке Compile. После перекомпиляции пакета Delphi информирует о том, что удаленный компонент больше не зарегистрирован.
|