3. Завдання властивостей компонента
Поля даних завжди мають бути захищені від несанкціонованого доступу. Тому їх доцільно визначати в private - закритому розділі класу. У окремих випадках їх можна поміщати в protected - захищений розділ класу, щоб можливі нащадки цього класу мали до них доступ. Традиційно ідентифікатори полів співпадають з іменами відповідних властивостей, але з додаванням як префіксу символу F. Таким чином, в нашому прикладі ви можете занести в розділ private оголошення трьох необхідних нам полів даних :
class PACKAGE TEditLetNum : public TEdit
{
private:
//Закриті елементи-дані класу
bool FEnableNum;
bool FEnableLet;
bool FModified;
};
Після чого потрібно оголосити властивості - методи читання і запису цих полів. Властивість оголошується оператором виду :
рroperty <тип> <ім'я> = {read = < ім’я поля або методу читання>
write = <ім’я поля або методу запису>
<директиви запам'ятовування і значення за
замовчуванням>};
Якщо в розділах read або write записано ім'я поля, значить, передбачається пряме читання або запис даних.
Якщо в розділі read записано ім'я методу читання, то читання буде здійснюватися тільки функцією з цим ім'ям. Функція читання - це функція без параметру, що повертає значення того типу, який оголошений для властивості. Ім'я функції читання прийнято починати з префікса Get, після якого слідує ім'я властивості.
Якщо в розділі write записано ім'я методу запису, то запис буде здійснюватися тільки процедурою з цим ім'ям. Процедура запису - це процедура з одним параметром того типу, який оголошений для властивості. Ім'я процедури запису прийнято починати з префікса Set, після якого слідує ім'я властивості.
Якщо розділ write відсутній в оголошенні властивості, означає ця властивість тільки для читання і користувач не може задавати його значення.
Директиви запам'ятовування визначають, як потрібно зберігати значення властивостей при збереженні користувачем файлу форми .dfm. Найчастіше використовується директива
default = <значення за замовчуванням>
Вона не задає початкові умови. Це справа конструктора. Директива просто каже, що якщо користувач в процесі проектування не змінив значення властивості за умовчанням, то зберігати значення властивості не потрібно.
Отже, для нашого прикладу оголошення властивостей можуть мати вигляд:
public:
__fastcall TEditLetNum(TComponent* Owner);
// Властивість тільки часу виконання
__property bool Modified = (read=FModified, default=false};
__published:
//Властивості компонента, що включаються в Інспектор Об'єктів
__property bool EnableLet = {read=FenableLet, write=SetEnableLet, default=true);
__property bool EnableNum = {read=FenableNum, write=SetEnableNum, default=true};
Оголошення властивості Modified поміщається в розділ public, оскільки ця властивість має бути доступна тільки під час виконання. Властивості EnableNum і EnableLet поміщаються в розділ __published, оскільки вони повинні відображуватися в Інспекторові Об'єктів під час проектування.
Властивості EnableNum і EnableLet мають прямий доступ до полів для читання. Але для запису вони мають методи SetEnableNum і SetEnableLet відповідно. Це пов'язано з тим, що при записі властивостей потрібно перевіряти, чи не виявляться значення обох цих властивостей рівними false. Подібне завдання значень потрібно запобігати, оскільки в цьому випадку у вікно редагування взагалі нічого не можна буде ввести.
Властивість Modified взагалі не має методу запису, оскільки вона призначена тільки для читання.
Вказані в оголошеннях методи запису можуть бути реалізовані звичайними функціями, оголошення яких поміщаються в private - закритий розділ класу, а їх реалізація включається в тіло модуля. Для того, щоб задати властивостям початкові значення, потрібно ще включити відповідні оператори в тіло конструктора. У результаті в даний момент модуль компонента може мати наступний вигляд.
Файл EditLetNum.h:
class PACKAGE TEditLetNum : public TEdit
{
private:
//Закриті елементи - дані класу.
bool FEnableLet; bool FEnableNum; bool FModified;
protected:
//Захищені методи запису
void __fastcall SetEnableLet (bool AEnableLet);
void fastcall SetEnableNum(bool AEnableNum);
public:
//Оголошення конструктора
__fastcall TEditLetNum(TComponent* Owner);
//Властивість тільки.часу виконання
__property bool Modified = {read=FModified, default=false};
__published:
//Властивості компонента, що включаються в Інспектор Об'єктів
__property bool EnableLet = (read=FenableLet,
write=SetEnableLet, default=true};
__property bool EnableNum = {read=FenableNum,
write=SetEnableNum, default=true};
};…
Файл EditLetNum.cpp:
…
static inline void ValidCtrCheck(TEditLetNum *)
{
new TEditLetNum(NULL);
}
//
__fastcall TEditLetNum::TEditLetNum(Tcomponent *Owner)
:TEdit(Owner)
{
FEnableLet = true;
FEnableNum = true;
FModified = false;
}
//
namespace Editletnum
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[l] = {
__classid(TEditLetNum));
RegisterComponents{"MyComponents", classes, 0);
}
}
//
void fastcall TEditLetNum::SetEnableNum(bool AEnableNum)
{
//Надання значення полю FEnableNum FEnableNum = AEnableNum;
//Якщо значення FEnableNum і FEnableLet = false,
//то полю FEnableLet привласнюється true
if (! AEnableNum)
if (! FEnableLet) FEnableLet = true;
}
//
void __fastcall TEditLetNum::SetEnableLet(bool AEnableLet)
{
//Надання значення полю FEnableLet
FEnableLet = AEnableLet;
//Якщо значення FEnableNum і FEnableLet = false,
//то полю FEnableNum привласнюється true
if (!AEnableLet) if (!FEnableNum) FEnableNum = true;
}…
Процедури, що реалізовують методи запису, привласнюють полю передане в них значення параметра і у разі, якщо передано значення false, перевіряють значення іншого поля. Якщо і інше поле має значення false, то воно виправляється на true.
Оголошення процедур запису включені в розділ protected. Це означає, що вони закриті для зовнішнього користувача, але доступні для можливих нащадків вашого класу.
Конструктор оголошений у відкритому розділі класу public і має ім'я TEditLetNum, співпадаюче з ім'ям класу. У реалізації конструктора задаються початкрві значення новим властивостям, які ви додали в компонент.
Збережіть підготовлені файли і відкомпілюйте їх (кнопка Compile в Диспетчера Пакетів).
Побудуємо тестове застосування для відладки встановленого компонента. Хоча він ще не до кінця створений, дещо вже можна побачити.
Відкрийте новий проект і внесіть в нього з відповідної сторінки бібліотеки ваш новий компонент. Відкрийте (командою File | Open) файл вашого компоненту, щоб можна було вносити в нього якісь зміни. Збережете проект під яким-небудь ім'ям (наприклад, "Test"). Відкомпілюйте ваше застосування (команда Project | Make All Projects). Якщо усе пройшло без помилок, виділите на формі ваш компонент і погляньте на його властивості в Інспекторові об'єктів. Ви знайдете там додані вами властивості EnableNum і EnableLet. Обидві властивості мають за умовчанням задані в конструкторі значення true. Спробуйте змінити обидва значення на false. Це вам не вдасться зробити, оскільки спрацюють написані вами методи запису.
Властивість Modified в Інспекторові об'єктів ви не побачите, оскільки ця властивість може використовуватися тільки під час виконання.