Перед початком роботи по створенню нового компонента потрібно створити окремий каталог для модуля і інших файлів компонента. Після цього можна приступити до створення модуля компонента.
Для того щоб створити модуль компонента, необхідно з меню Component вибрати команду New Component і в поля діалогового вікна New Component (рис. 16.1) ввести інформацію про створюваний компоненті.
Рис. 16.1. Діалогове вікно New Component
Поле Ancestor type має містити базовий тип для створюваного компонента. Базовий тип компонента можна задати безпосереднім введенням імені типу або вибором зі спадного списку. Для компоненту, базовим компонентом є стандартний компонент Edit (поле введення-редагування). Тому базовим типом для типу розробляється компонента є тип TEdit.
У поле Class Name необхідно ввести ім’я класу компоненту, наприклад TNkEdit. Згадайте, що в Delphi імена типів повинні починатися буквою т.
У поле Palette Page потрібно ввести ім’я вкладки палітри компонентів, на яку після створення компонента буде додано його значок. Назва вкладки палітри компонентів можна вибрати зі списку. Якщо в поле Palette Page ввести ім’я ще не існуючої вкладки палітри компонентів, то безпосередньо перед додаванням компонента вкладка з вказаним ім’ям буде створена.
У поле Unit, file name знаходиться автоматично сформоване ім’я файлу модуля створюваного компонента. Delphi привласнює модулю компонента ім’я, яке збігається з ім’ям типу компонента, але без літери T. Натиснувши на кнопці з трьома крапками, можна вибрати каталог, в якому повинен бути збережений модуль компоненту.
Після натискання кнопки ОК до поточного проекту додається сформований Delphi-модуль, який представляє собою заготовку (шаблон) модуля компонента. Текст цього модуля наведений у лістингу 16.1.
Лістинг 16.1. Шаблон модуля компонента
unit NkEdit; interface uses Windows, Messages, SysUtils, Classes, Controls, StdCtrls; type TEdit1 = class (TEdit) private { Private declarations} protected { Protected declarations} public { Public declarations} published { Published declarations} end; procedure Register; implementation procedure Register; begin RegisterComponents ( 'Samples', [TNkEdit]); end; end.
В оголошенні нового класу вказано тільки тип батьківського класу. В розділ реалізації поміщена процедура Register, яка використовується під час установки створеного програмістом компонента на зазначену вкладку палітри компонентів Delphi для реєстрації нового класу.
У сформований Delphi оголошення класу нового компонента потрібно внести доповнення: оголосити властивість, поле даних цього властивості, функцію доступу до поля даних, процедуру установки значення поля даних, конструктор і деструктор. Якщо на деякі події компонент повинен реагувати не так, як базовий, то в оголошення класу потрібно помістити опис відповідних процедур обробки подій.
У лістингу 16.2 наведено текст модуля компонента NkEdit після внесення всіх необхідних змін.
Лістинг 16.2. Модуль компонента NkEdit
unit NkEdit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TNkEdit = Class (TEdit) private FNumb: single; // число, що знаходиться в полі редагування // Це опис функції доступу // і процедури установки поля FNumb function GetNumb: single; procedure SetNumb (value: single); protected procedure KeyPress (var Key: Char); override; public published constructor Create (AOwner: TComponent); override; property Numb: single // властивість компонента read GetNumb write SetNumb; end; procedure Register; implementation // процедура реєстрації компонента procedure Register; begin RegisterComponents ( 'Samples', [TNkEdit]); end; // конструктор компонента constructor TNkEdit.Create (AOwner: TComponent); begin // do not forget to call the ancestors 'constructor inherited Create (AOwner); end; // функція доступу до поля FNumb function TNkEdit.GetNumb: single; begin try // поле Text може бути порожнім Result: = StrToFloat (text); except on EConvertError do begin Result: = 0; text: = ''; end; end; end; // процедура запису в поле FNumb procedure TNkEdit.SetNumb (Value: single); begin FNumb: = Value; Text: = FloatToStr (value); end; // процедура обробки події KeyPress procedure TNkEdit.KeyPress (var key: char) ; begin case key of '0' .. '9', # 8, # 13:; '-': if Length (text) <> 0 then key: = # 0; else if not ((key = DecimalSeparator) and (Pos (DecimalSeparator, text) = 0)) then key: = # 0; end; inherited KeyPress (key); // виклик процедури обробки події // OnKeyPress батьківського класу end; end.
В опис класу TNkEdit додано оголошення властивості Numb, яке представляє собою число, яке перебуває в поле редагування. Для зберігання Значення властивості Numb використовується поле FNumb. Функція GetNumb необхідна для доступу до поля FNumb, а процедура setNumb – для установки значення властивості.
Конструктор класу TNkEdit спочатку викликає конструктор батьківського класу (TEdit), присвоює значення властивості Text, потім встановлює значення властивості Numb.
Реакція компонента NkEdit на натискання клавіші клавіатури визначається процедурою обробки події TNkEdit.KeyPress, яка заміщає відповідну процедуру базового класу. Як параметр процедура TNkEdit.KeyPress отримує код натиснутої клавіші. Перед викликом процедури обробки події OnKeyPress батьківського класу код натиснутоюклавіші перевіряється на допустимість. Якщо натиснута неприпустима для компонента NkEdit клавіша, то код символу замінюється на нуль. Допустимими для компонента NkEdit є цифрові клавіші, роздільник цілої і дробової частин числа (в Залежно від настройки Windows: крапка чи кома), “мінус”, “Backspase “ (Дозволяє видалити помилково введений символ) і “Enter”.
Тут слід згадати, що в тексті програми дробова частина числової константи відокремлюється від цілої крапкою. Під час роботи програми при вводі вихідних даних користувач повинен використовувати той символ, який заданий в налаштуванні Windows. В якості роздільник зазвичай застосовують кому (це для Росії стандартна настройка) або точку. Наведена процедура обробки події OnKeyPress враховує, що настройка Windows може змінюватися, і тому самі ввели символ порівнюється ні з константою, а зі значенням глобальної змінної DecimalSeparator, яка містить символ-роздільник, використовуваний в Windows в даний момент.
Після введення тексту модуля компонента модуль потрібно відкомпілювати і зберегти.