Суббота, 18.05.2024
Королевство Delphi
Главное меню
Статьи
Наш опрос
Как часто ви на этот сайт заходите?
Всего ответов: 159
Статистика
Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа
Главная » Статьи » Система » Компоненты

Создание собственных компонентов

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

Компоненты - это самая удобная вещь. С самого появления языков программирования, все программеры стремятся добится многократности использования кода. Для этого мы перешли к процедурному программирования, затем к объектному и сейчас нам предлагают перейти к компонентному программированию. То, что предлагает нам MS - использовать компоненты ActiveX я назову настоящей лажей. Эти компоненты требую гемороя для регистрации их на машине клиента, слежка за версиями и многое другое. Borland предложила свои компоненты. По умолчанию они встраиваются прямо в запускной файл и не требуют никакой регистрации и великолепно работают.

Я думаю, что я достаточно расхвалил компоненты Delphi, пора бы и написать один для примерчика.

Для создания нового компонента выбери меню Component-> New Component.

Давай расмотрим каждое окошечко в отдельности:

  • Ancestor type - Тип предка. Это имя объекта, от которого мы порадим наш объект. Это даст нашему объекту все возможности его предка, плюс мы добавим свои. Для часиков нам понадобится TGraphicControl.
  • Class Name - Имя нашего будущего компонента. Я его назвал TGraphicClock.
  • Palette Page - Имя палитры компонентов, куда будет помещён наш компонент после инсталляции. Я оставил значение по умолчанию "Samples". Но ты можешь поместить его даже на закладку "Standart".
  • Unit file name - имя и путь к модулю, где будет располагатся исходный код компонента. Хотябы посмотри под каким именем сохранят твой компонент и где.
  • Search path - Сюда можно даже не заглядывать.

Жмём "ОК" (именно "ОК", а не Install) и получаем созданный Дульфой код:

unit GraphicClock;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
 TGraphicClock = class(TGraphicControl)
 private
 { Private declarations }
 protected
 { Protected declarations }
 public
 { Public declarations }
 published
 { Published declarations }
 end;

procedure Register;

implementation

procedure Register;
begin
 RegisterComponents('Samples', [TGraphicClock]);
end;

end.

В принципе простейший компонент готов и его можно инсталировать в Дельфу. Но этот компонент ничего не умеет и он пока является полным аналогом своего предка TGraphicControl. Чтобы он стал отличатся, сейчас мы добавим ему разные свойства.

Начнём написание нашего компонента с конструктора и деструктора. конструктор - это простая процедура, которая автоматически вызывается при создании компонента. Деструктор - тоже процедура, только она автоматически вызывается при уничтожении компонента. В конструкторе мы проинициализируем все наши переменные, а в деструкторе уничтожим.

Итак, напиши в разделе public:

 constructor Create(AOwner: TComponent); override;

Теперь нажми сочетание клавишь CTRL+SHIFT+C. Дельфи сам создаст заготовку для конструктора:

 constructor TGraphicClock.Create(AOwner: TComponent);
 begin
 inherited;
 end;

Поправим её до вот такого вида:

constructor TCDClock.Create(AOwner: TComponent);
begin
//Вызываем конструктор предка
 inherited Create(AOwner);

//Устанавливаем значения ширины и высоты по умолчанию
 Width := 50;
 Height := 50;

//Устанавливаем переменную ShowSecondArrow в true.
//Она будет у нас отвечать за показ секундной стрелки
 ShowSecondArrow := true;

//Инициализируем остальные переменные
 PrevTime := 0;
 CHourDiff := 0;
 CMinDiff := 0;

//Инициализируем растры TBitmap, в которых будут хранится
//фон и сам рисунок часов.
 FBGBitmap:= TBitmap.Create;
 FFont:=TFont.Create;;

 FBitmap:= TBitmap.Create;
 FBitmap.Width := Width;
 FBitmap.Height := Height;

 //Выставляем формат времени
 DateFormat:='tt';

 //Запускаем таймер
 Ticker := TTimer.Create( Self);
 //Интервал работы таймера - одна секунда
 Ticker.Interval := 1000;
 //По событию OnTimer будет вызыватсья процедура TickerCall
 Ticker.OnTimer := TickerCall;
 //Включаем таймер
 Ticker.Enabled := true;

//Устанавливаем цвета поумолчанию
 FFaceColor := clBtnFace;
 FHourArrowColor := clActiveCaption;
 FMinArrowColor := clActiveCaption;
 FSecArrowColor := clActiveCaption;
end;

Ключевое слово inherited вызывает конструктор предка (в нашем случае TGraphicClock). В остальном, я надеюсь, что с конструктором всё ясно.

Теперь создадим деструктор. Для этого также опишем его в разделе public:

 public
 { Public declarations }
 constructor Create(AOwner: TComponent); override;
 destructor Destroy; override;

Кстати, ключевое слово override; после имени этих процедур говорит о том, что мы хотим переписать уже существующую у предка функцию с таким именем. Теперь жмём Ctrl+Shift+C и получаем заготовку для деструктора и поправляем её до вида :

destructor TGraphicClock.Destroy;
begin
 Ticker.Free;
 FBitmap.Free;
 FBGBitmap.Free;
 inherited Destroy;
end;

Заметь, что в конструкторе я вызывал предка в самом начале inherited, а в деструкторе в самом конце. В конструкторе сначала нужно, чтобы проинициализировался предок (он проинициализирует необходимые ссылки), а потом можно инициализировать свои вещи. Если в деструкторе мы сначала вызовем предка, то последующая работа с компонентом уже будет невозможна, потому что предок уничтожит все ссылки, поэтому я ставлю этот вызов в конце.

Теперь опишем все необходимые нам переменные в разделе private:

 private
 //Для часов обязательно понадобится таймер
 Ticker: TTimer;

 //Картинки часов и фона 
 FBitmap, FBGBitmap: TBitmap;

 /События
 FOnSecond, FOnMinute, FOnHour: TNotifyEvent;

 //Центральная точка
 CenterPoint: TPoint;
 //Радиус
 Radius: integer;

 //Остальные параметры, которые мы рассмотрим в процессе.
 LapStepW: integer;
 PrevTime: TDateTime;
 ShowSecondArrow: boolean;
 FHourArrowColor,FMinArrowColor, FSecArrowColor: TColor;
 FFaceColor: TColor;
 CHourDiff, CMinDiff: integer;
 FClockStyle:TClockStyle;
 FDateFormat: String;
 FFont: TFont;

Теперь в разделе private опицем процедуру TickerCall. Мы её уже использовали в конструкторе. Она у нас вызывается по событию от таймера:

 protected
 { Protected declarations }
 procedure TickerCall(Sender: TObject);

Жмём CTRL+SHIAT+C и модифицируем созданную функцию:

procedure TCDClock.TickerCall(Sender: TObject);
var
 H,M,S,Hp,Mp,Sp: word;
begin
 //Если компонент создан в дезайнере, то выход
 if csDesigning in ComponentState then exit;
 //Иначе это уже запущеная программа

 //Получить время
 DecodeCTime( Time, H, M, S);
 //Получить предыдущее время.
 DecodeCTime( PrevTime, Hp, Mp, Sp);

 //Сгенерировать событие OnSecond
 if Assigned( FOnSecond) then FOnSecond(Self);
 //Сгенерировать событие OnMinute
 if Assigned( FOnMinute) AND (Mp < M) then FOnMinute(Self);
 //Сгенерировать событие OnHour
 if Assigned( FOnHour) AND (Hp < H) then FOnHour(Self);

 //Сохранить текущее время в PrevTime
 PrevTime := Time;

 if ( NOT ShowSecondArrow) AND (Sp <= S) then exit;

 //Прорисовать часы.
 DrawArrows;
end;

DrawArrows напичкана математикой и она сейчас не имеет для нас особого значения. Немного ниже я приведу её в полном исходнике, а сейчас я просто расказываю тебе о том, как создавать компонента, поэтому мы рассмотрим сабытия генерируемые в функции TickerCall.

У нас уже объявлено три события:

FOnSecond, FOnMinute, FOnHour: TNotifyEvent;

Все они появятся на закладке Events в окне Object Inspector, когда ты поставишь компонент на форму. Чтобы приложения могло поймать эти события, мы объявили переменные типа TNotifyEvent и генерируем эти события (с помощью конструкции типа FOnSecond(Self) для события OnSecond), когда изменилась секунда, изменилась минута или изменился час.

Помимо этого, в разделе published мыдолжны описать свойство OnSecond:

 property OnSecond: TNotifyEvent read FOnSecond write FOnSecond;
 property OnMinute: TNotifyEvent read FOnMinute write FOnMinute;
 property OnHour: TNotifyEvent read FOnHour write FOnHour;

Теперь наш компонент сможет генерировать события.

С событиями вроде всё ясно (если нет, то посмотри на исходник в конце статьи). Теперь переходим к свойствам. В разделе published мы можем создавать свойства, которые будут отображатся в Object Inspector при выделении наших часиков. Все свойства, которые есть у предка нужно просто описать

 published
 property Align;
 property Enabled;
 property ParentShowHint;
 property ShowHint;
 property Visible;

Слово property говорит о том, что мы описываем свойство. Для них не нужны процедуры или функции, потому что эти свойства уже есть у предка. Нам надо только описать их и всё. Я описал только маленькую часть из доступных у TGraphicControl функций. Ты можешь добавить любые из доступных. Чтобы узнать, какие функции можно добавлять, открой помощь (меню Help->Delphi Help) и найди там объект TGraphicControl. Щёлкни по нему дважды и в появившейся справке выбери пункт Properties (вверху окна) (рис 2). Появится окно с перечнем всех свойств. Ты можешь добавить любое из них. Например, чтобы добавить свойство Action нужно написать в разделе published:

 published
 property Action;

Чтобы добавить своё свойство, нужно немного попатеть. Например. Добавим возможность, чтобы пользователь мог менять картинку фона. Для этого описываем в разделе published свойство BGBitmap:

//свойство Имя :Тип читать из FBGBitmap записывать с помощью SetBGBitmap
 property BGBitmap:TBitmap read FBGBitmap write SetBGBitmap;

Коментарий поможет тебе разобраться в написанном здесь. Итак, мы объявили свойство BGBitmap типа ТBitmap. Для чтения используется простая переменная FBGBitmap (можно использовать и функцию, но нет смысла, потому что можно прямо читать из переменной), для записи используется процедура SetBGBitmap. Процедура выглядит так:

 procedure TCDClock.SetBGBitmap(Value: TBitmap);
 begin
 FBGBitmap.Assign(Value);
 invalidate;
 end;

Теперь ты можешь изменять фон простой операцией GraphicClock1.BGBitmap:=bitmap.

Если ты хочешь создать свойство с выпадающим списком (как например у свойства Align), по щелчку которого выпадает список возможных параметров, то тут уже немного сложнее. В моих часах есть такой параметр, который делает выбор, какого типа будут часы - аналоговые или цыфровые. Объявление делается так:

//свойство Имя :Тип Это нам известно Значение по умолчанию
 property ClockStyle:TClockStyle read FClockStyle write SetStyleStyle default scAnalog;

Мы объявляем свойство ClockStyle типа TClockStyle. Тип TClockStyle мы должны описать в самом начале, до описания нашего объекта TGraphicClock:

type
 TClockStyle = (scAnalog, scDigital);

 TGraphicClock = class(TGraphicControl)
 private
 Ticker: TTimer;

Строка TClockStyle = (scAnalog, scDigital) - объявляет список переменных, которые и будут выпадать по выбору свойства.

Всё остально происходит так же, за исключением нового слова default Которое устанавливает значение по умолчанию - scAnalog.

Вот и всё, что я хотел тебе рассказать.

Чтобы установить компонент в системе нужно щёлкнуть меню Component->Install Component. Перед тобой появится окно.

В строке Unit file name нужно указать полный путь к файлу. Для облегчения выбора используй кнопку Browse

 справа. Перед тобой появится запрос на компиляцию пакета. Соглашайся.

В этом окне ты можешь откомпелировать пакет с помощью кнопки Compile и установить в Delphi с помощью Install .

Вот и всё. Наслаждайся новым компонентом в твоей палитре.

На сегодня хватит. Статья и так получилась достаточно большая. Увидимся в следующий раз.

Напоследок у меня есть небольшая просьба. Пиши мне, о чём бы ты хотел прочитать на моих страницах. Некоторые разделы я неуспеваю писать, а некоторые я просто уже не знаю, о чём тебе рассказать. Ты просто пиши мне, а там разберёмся.

Получить ссылку на материал

Категория: Компоненты | Добавил: Барон (16.12.2011)
Просмотров: 1346 | Теги: компонент | Рейтинг: 5.0/1
[ Пожертвования для сайта ] [ Пожаловаться на материал ]

Если вам помог материал сайта кликните по оплаченной рекламе размещенной в центре

Поиск
Категории раздела
ActiveX [10]
CORBA и COM [16]
Kol и MCK [23]
WinAPI [28]
Компоненты [27]
Работа с Bluetooth [4]
Железо [8]
Текст [18]
Разное [98]
Королевство Delphi © 2010-2024
Яндекс цитирования