Пособие по написанию компонентов
Содержание:
- Почему я сел писать это пособие
- Начало. Для чего нужны компоненты
- Шаг 1. Придумывание идеи
- Шаг 2. Создание пустого модуля компонента
- Шаг 3. Начинаем разбираться во всех директивах
- Шаг 4. Пишем процедуры и функции.
- Шаг 5. Устанавливаем компонент
Теперь изучим более сложные вещи:
- Создание свойств своего типа
- Имплантируем таймер в компонент
- Переустановка компонента
- Дополнительная информация
Почему я сел писать это пособие
Во-первых, потому что когда я очень хотел написать свой первый компонент, я прочитал две книги, и у меня ничего интересного собственно не вышло. Потом я прочитал еще одну книгу (в ней хотя бы пример рабочий был), вроде разобрался. Но там был разобран такой простой компонент, что все более сложное мне приходилось делать самому, иногда методом тыка, иногда сидел разбирался и так далее. Результат - разобрался, чего и вам желаю и надеюсь помочь этим пособием.
Для чего нужны компоненты
Дельфи имеет открытую архитектуру - это значит, что каждый программист волен усовершенствовать эту среду разработки, как он захочет. К стандартным наборам компонентов, которые поставляются вместе с Дельфи можно создать еще массу своих интересных компонентов, которые заметно упростят вам жизнь (это я вам гарантирую). А еще можно зайти на какой-нибудь крутой сайт о Дельфи и там скачать кучу крутых компонентов, и на их основе сделать какую-нибудь крутую прогу. Так же компоненты освобождают вас от написания "тысячи тонн словесной руды". Пример: вы создали компонент - кнопку, при щелчке на которую данные из Memo сохранятся во временный файл. Теперь как только вам понадобится эта функция вы просто ставите этот компонент на форму и наслаждаетесь результатом. И не надо будет каждый раз прописывать это, для ваших новых программ - просто воспользуйтесь компонентом.
Шаг 1. Придумывание идеи
Первым шагом нужно ответить себе на вопрос: "Для чего мне этот компонент и что он будет делать?". Затем необходимо в общих чертах продумать его свойства, события, на которые он будет реагировать и те функции и процедуры, которыми компонент должен обладать. Затем очень важно выбрать "предка" компонента, то есть наследником какого класса он будет являться. Тут есть два пути. Либо в качестве наследника взять уже готовый компонент (то есть модифицировать уже существующий класс), либо создать новый класс.
Для создания нового класса можно выделить 4 случая:
- Создание Windows-элемента управления (TWinControl)
- Создание графического элемента управления (TGraphicControl)
- Создание нового класса или элемента управления (TCustomControl)
- Создание невизуального компонента (не видимого) (TComponent)
Теперь попробую объяснить что же такое визуальные и невизуальные компоненты. Визуальные компоненты видны во время работы приложения, с ними напрямую может взаимодействовать пользователь, например кнопка Button - является визуальным компонентом.
Невизуальные компоненты видны только во время разработки приложения (Design-Time), а во время работы приложения (Run-Time) их не видно, но они могут выполнять какую-нибудь работу. Наиболее часто используемый невизуальный компонент - это Timer.
Итак, что бы приступить от слов к делу, попробуем сделать какой-нибудь супер простой компонент (только в целях ознакомления с техникой создания компонентов), а потом будем его усложнять.
Шаг 2. Создание пустого модуля компонента
Рассматривать этот шаг я буду исходя из устройства Дельфи 3, в других версиях этот процесс не сильно отличается. Давайте попробуем создать кнопку, у которой будет доступна информация о количестве кликов по ней.
Чтобы приступить к непосредственному написанию компонента, вам необходимо сделать следующее:
Закройте проекты, которые вы разрабатывали (формы и модули)
В основном меню выберите Component -> New Component...
Перед вами откроется диалоговое окно с названием "New Component"
В поле Ancestor Type (тип предка) выберите класс компонента, который вы хотите модифицировать. В нашем случае вам надо выбрать класс TButton
В поле Class Name введите имя класса, который вы хотите получить. Имя обязательно должно начинаться с буквы "T". Мы напишем туда, например, TCountBtn
В поле Palette Page укажите имя закладки на которой этот компонент появиться после установки. Введем туда MyComponents (теперь у вас в Делфьи будет своя закладка с компонентами!).
Поле Unit File Name заполняется автоматически, в зависимости от выбранного имени компонента. Это путь куда будет сохранен ваш модуль.
В поле Search Path ничего изменять не нужно.
Теперь нажмите на кнопку Create Unit и получите следующее:
unit CountBtn;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
type
TCountBtn = class(TButton)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;
procedure register;
implementation
procedure register;
begin
RegisterComponents('MyComponents', [TCountBtn]);
end;
end.
|
Шаг 3. Начинаем разбираться во всех директивах
Что же здесь написано? да собственно пока ничего интересного. Здесь объявлен новый класс TCountBtn и процедура регистрации вашего компонента в палитре компонентов.
Директива Private. Здесь вы будете писать все скрытые поля которые вам понадобятся для создания компонента. Так же в этой директиве описываются процедуры и функции, необходимые для работы своего компонента, эти процедуры и функции пользователю не доступны. Для нашего компонент мы напишем туда следующее (запись должна состоять из буквы "F" имени поля: тип этого поля):
Буква "F" должна присутсвовать обязательно. Здесь мы создали скрытое поле Count, в котором и будет храниться число кликов по кнопке.
Директива Protected. Обычно я здесь пишу различные обработчики событий мыши и клавиатуры. Мы напишем здесь следующую строку:
procedure Click; override;
|
Это указывает на то, что мы будем обрабатывать щелчок мыши по компоненту. Слово "override" указывает на то, что мы перекроем стандартное событие OnClick для компонента предка.
В директиве Public описываются те процедуры и функции компонента, которые будут доступны пользователю. (Например, в процессе написания кода вы пишите имя компонента, ставите точку и перед вами список доступных функций, объявленных в диретиве Public). Для нашего компонента, чтобы показать принцип использования этой директивы создадим функцию - ShowCount, которая покажет сообщение, уведомляя пользователя сколько раз он уже нажал на кнопку. Для этого в директиве Public напишем такой код:
Осталась последняя директива Published. В ней также используется объявления доступных пользователю, свойств и методов компонента. Для того, чтобы наш компонент появился на форме необходимо описать метод создания компонента (конструктор), можно прописать и деструктор, но это не обязательно. Следует обратить внимание на то, что если вы хотите, чтобы какие-то свойства вашего компонента появились в Инспекторе Объектов (Object Inspector) вам необходимо описать эти свойства в директиве Published. Это делается так: property Имя_свойства (но помните здесь букву "F" уже не нужно писать), затем ставиться двоеточие ":" тип свойства, read процедура для чтения значения, write функция для записи значения;. Но похоже это все сильно запутано. Посмотрите, что нужно написать для нашего компонента и все поймете:
constructor Create(aowner: Tcomponent); override; //Конструктор
property Count: integer read FCount write FCount; //Свойство Count
|
Итак все объявления сделаны и мы можем приступить к написанию непосредственно всех объявленных процедур.
Шаг 4. Пишем процедуры и функции.
Начнем с написания конструктора. Это делается примерно так:
constructor TCountBtn.Create(aowner:Tcomponent);
begin
inherited create(Aowner);
end;
|
Здесь в принципе понимать ничего не надо. Во всех своих компонентах я писал именно это (только класс компонента менял и все). Также сюда можно записывать любые действия, которые вы хотите сделать в самом начале работы компонента, то есть в момент установки компонента на форму. Например можно установить начальное значение нашего свойства Count. Но мы этого делать не будем.
Теперь мы напишем процедуру обработки щелчка мышкой по кнопке:
procedure Tcountbtn.Click;
begin
inherited click;
FCount := FCount + 1;
end;
|
"Inherited click" означает, что мы повторяем стандартные методы обработки щелчка мышью (зачем напрягаться и делать лишнюю работу:)).
У нас осталась последняя процедура ShowCount. Она может выглядеть примерно так:
procedure TCountBtn.ShowCount;
begin
Showmessage('По кнопке '+ caption+' вы сделали: '+inttostr(FCount)+' клик(а/ов)');
end;
|
Здесь выводится сообщение в котором показывается количество кликов по кнопке (к тому же выводится имя этой кнопки, ну это я добавил только с эстетической целью).
И если вы все поняли и сделали правильно, то у вас должно получится следующее:
unit CountBtn;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls;
type
TCountBtn = class(TButton)
private
{ Private declarations }
FCount: integer;
protected
{ Protected declarations }
procedure Click; override;
public
{ Public declarations }
procedure ShowCount;
published
{ Published declarations }
property Count: integer read FCount write FCount;
constructor Create(aowner: Tcomponent); override;
end;
procedure register;
implementation
procedure register;
begin
RegisterComponents('DelphiWorld Components', [TCountBtn]);
end;
constructor TCountBtn.Create(aowner:Tcomponent);
begin
inherited create(Aowner);
end;
procedure Tcountbtn.Click;
begin
inherited click;
FCount := FCount + 1;
end;
procedure TCountBtn.ShowCount;
begin
Showmessage('По кнопке '+ caption+' вы сделали: '+
inttostr(FCount)+' клик(а/ов)');
end;
end.
|
Скорее сохраняйтесь, дабы не потерять случайным образом байты набранного кода:)).
Шаг 5. Устанавливаем компонент
Если вы сумели написать и понять, все то что здесь предложено, то установка компонента не должна вызвать у вас никаких проблем. Все здесь делается очень просто. В главном меню выберите пункт Component -> Install Component. перед вами открылось диалоговое окно Install Component. В нем вы увидите две закладки: Into exsisting Package и Into new Package. Вам предоставляется выбор установить ваш компонент в уже существующий пакет или в новый пакет соответственно. Мы выберем в уже существующий пакет.
В поле Unit File Name напишите имя вашего сохранненого модуля (естественно необходимо еще и указать путь к нему), а лучше воспользуйтесь кнопкой Browse и выберите ваш файл в открывшемся окне.
В Search Path ничего изменять не нужно, Делфьи сама за вас все туда добавит.
В поле Package File Name выберите имя пакета, в который будет установлен ваш компонент. Мы согласимся с предложенным по умолчанию пакетом.
Теперь нажимаем кнопочку Ok. И тут появиться предупреждение Package dclusr30.dpk will be rebuilt. Continue? Дельфи спрашивает: "Пакет такой-то будет изменен. Продолжить?". Конечно же надо ответить "Да". И если вы все сделали правильно, то появиться сообщение, что ваш компонент установлен. Что ж можно кричать Ура! Это ваш первый компонент.
Создание свойств своего типа
Теперь мы попробуем создать свойство нестандартного типа. Рассмотрим это на примере метки - TLabel. У этого компонента есть такое свойство: Alignment. Оно может принимать следующие значения: taLeftJustify, taCenter, taRightJustify. Приступаем к созданию свойства. Ничего интересного мне придумать не удалось, но тем не менее я вам покажу это на примере того свойства, которое я придумал. Оно очень простое и поможет вам разобраться. Свойство будет называться ShowType (тип TShowTp), в нашем компоненте оно будет отвечать за отображение свойства Count. Если пользователь установит свойство ShowType в Normal, то кнопка будет работать, как и работала. А если пользователь присвоит этому свойтсву значение CountToCaption, то количество кликов, будет отображаться на самой кнопке.
Для начале нам необходимо объявить новый тип. Описание типа нужно добавить после слова Type. Вот так это выглядело вначале:
type
TCountBtn = class(TButton)
|
Вот так это должно выглядеть:
type
TShowTp = (Normal, CountToCaption);
TCountBtn = class(TButton)
|
Здесь мы объявили новый тип TShowTp, который может принимать только два значения. Все значения, которые вы хотите добавить перечисляются через запятую.
Теперь нам понадобиться создать поле этого типа. Это мы уже умеем и делать и поэтому не должно вызвать никаких сложностей. В директиву Private напишите:
Мы создали поле ShowType, типа TShowTp.
Конечно же необходимо добавить это свойство в инспектор объектов:
property ShowType: TshowTp read FshowType write FShowType;
|
Ну и наконец, чтобы наш компонент реагировал на изменение этого свойства пользователем надо слегка изменить обработчик события OnClick. После небольшой модификации он может иметь примерно такой вид:
procedure Tcountbtn.Click;
begin
inherited click;
FCount := Fcount + 1;
if ShowType = Normal then
Caption := Caption;
if ShowType = CountToCaption then
Caption := 'Count = ' + inttostr(count);
end;
|
Объясню что произошло. Вначале мы увеличиваем счетчик на единицу. Затем проверяем какое значение имеет свойство ShowType. Если Normal, то ничего не делаем, а если CountToCaption, то в надпись на кнопке выводим количество кликов. Не так уж и сложно как это могло показаться с первого раза.
Имплантируем таймер в компонент
Очень часто бывает, что вам необходимо вставить в компонент, какой-нибудь другой компонент, например, таймер. Как обычно будем рассматривать этот процесс на конкретном примере. Сделаем так, что через каждые 10 секунд значение счетчика кликов будет удваиваться. Для этого мы встроим таймер в нашу кнопку. Нам понадобиться сделать несколько несложных шагов.
После раздела uses, где описаны добавленные в программу модули, объявите переменную типа TTimer. Назовем ее Timer. Приведу небольшой участок кода:
unit CountBtn;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
var
Timer: TTimer;
type
|
Дальше в директиву Protected необходимо добавить обработчик события OnTimer для нашего таймера. Это делается так:
procedure OnTimer(Sender: TObject);
|
Поскольку наш таймер это не переменная, а компонент, его тоже надо создать, для этого в конструктор нашей кнопки напишем:
constructor TCountBtn.Create(aowner: Tcomponent);
begin
inherited create(Aowner);
Timer := TTimer.Create(self);
Timer.Enabled := true;
Timer.OnTimer := OnTimer;
Timer.Interval := 10000;
end;
|
Здесь создается экземпляр нашего таймера и его свойству Iterval (измеряется в миллисекундах) присваивается значение 10000 (то есть 10 секунд если по простому).
Собственно осталось написать саму процедуру OnTimer. Я сделал это так:
procedure TCountBtn.OnTimer(Sender: TObject);
begin
FCount := FCount * 2;
end;
|
Вот примерно то, что у вас должно получиться в конце:
unit CountBtn;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls;
var
Timer: TTimer;
type
TShowTp = (Normal, CountToCaption);
TCountBtn = class(TButton)
private
{ Private declarations }
FCount: integer;
FShowType: TShowTp;
protected
{ Protected declarations }
procedure OnTimer(Sender: TObject);
procedure Click; override;
public
{ Public declarations }
procedure ShowCount;
published
{ Published declarations }
property Count: integer read FCount write FCount;
constructor Create(aowner: Tcomponent); override;
property ShowType: TshowTp read FshowType write FShowType;
end;
procedure register;
implementation
procedure register;
begin
RegisterComponents('Mihan Components', [TCountBtn]);
end;
constructor TCountBtn.Create(aowner:Tcomponent);
begin
inherited create(Aowner);
Timer:=TTimer.Create(self);
Timer.Enabled:=false;
Timer.OnTimer:=OnTimer;
Timer.Interval:=1000;
end;
procedure Tcountbtn.Click;
begin
inherited click;
FCount:=Fcount+1;
Timer.Enabled:=true;
if ShowType = Normal then
Caption:=Caption;
if ShowType = CountToCaption then
Caption:='Count= '+inttostr(count);
end;
procedure TCountBtn.ShowCount;
begin
Showmessage('По кнопке '+ caption+' вы сделали: '+
inttostr(FCount)+' клик(а/ов)');
end;
procedure TCountBtn.OnTimer(Sender: TObject);
begin
FCount:=FCount*2;
end;
end.
|
Если у вас что-то не сработало, то в начале проверьте все ли у вас написано правильно. Затем проверьте может у вас не хватает какого-нибудь модуля в разделе Uses.
Переустановка компонента
Очень часто бывает необходимо переустановить ваш компонент. Если вы попробуете сделать это путем выбора Component->Install Component, то Дельфи вас честно предупредит о том, что пакет уже содержит модуль с таким именем. Перед вами открывается окно с содержимым пакета. В нем вы должны найти имя вашего компонента и удалить его (либо нажать кнопочку Remove). Теперь в пакете уже нет вашего компонента. Затем проделайте стандартную процедуру по установке компонента.
|