
- •Глава 6 - Использование и создание визуальных компонент
- •6.1 Назначение и устройство vcl
- •6.1.1 Vcl для прикладных программистов
- •6.1.2 Vcl для системных программистов
- •6.1.3 Компоненты vcl
- •6.2 Типы компонент
- •6.2.1 Стандартные компоненты
- •6.2.2 Оригинальные компоненты
- •6.3.1 Зачем нужны свойства?
- •6.3.2 Объявление свойств
- •6.3.2.1 Доступ к внутренним данным свойств
- •6.3.3 Переопределение свойств
- •6.3.4 Типы свойств
- •6.3.4.1 Свойства типа множество
- •6.3.4.2 Свойства типа массив
- •6.4.2 Определение событий
- •6.4.2.3 Стандартные события
- •6.4.3 Обработка событий
- •6.6 Иерархия классов vcl
- •6.7.2 Наследование компоненты
- •6.7.2.1 Модификация существующих компонент
- •6.7.2.2 Создание оригинальных оконных компонент
- •6.7.2.3 Создание графических компонент
- •6.8 Разработка простой компоненты
- •6.8.3 Члены данных, свойства и методы
- •6.8.5 Инсталляция компоненты
6.7.2 Наследование компоненты
Любая компонента является производной от общего прародителя TComponent, от его более специализированных наследников (таких как TControl или TGraphicControl) или от существующего компонентного класса. Компонеитой может стать практически любой элемент вашей программы, поведением которого вы хотите управлять на стадии проектирования. Цель Базовый класс
Модификация существующей компоненты Любая существующая компонента, например, TListBox, или абстрактный компонентный класс TCustomListBox.
Создание оригинальной компоненты TCustomControl
Создание графической компоненты TGraphicControl
Создание невидимой компоненты TComponent
6.7.2.1 Модификация существующих компонент
Простейший способ построить новую компоненту - это начать с существующей и изменить ее свойства. Вашей целью может являться добавление, исключение или замена значений по умолчанию некоторых свойств компоненты-образца. Вы можете использовать для этой цели любой подходящий абстрактный класс VCL, в название которого входит слово "Custom".
Например, вы можете произвести новую компоненту списка со специальными свойствами, которых нет в стандартном классе TListBox. Поскольку нельзя прямо модифицировать TListBox, вы должны начать с ее ближайшего предшественника в иерархии классов. Для этой цели лучше всего подходит TCustomListBox, которая реализует все мыслимые свойства производных компонент списка, однако не выставляет всех их в секции _published.
Наследуя вашу компоненту от одного из абстрактных типов (таких как TCustomListBox), вы всего лишь объявляете в секции _published те свойства, которые хотите включить в вашу компоненту, оставляя остальные в секции protected.
6.7.2.2 Создание оригинальных оконных компонент
С оконным интерфейсным элементом, видимым во время работы программы, пользователь обычно может взаимодействовать. Все оконные компоненты являются производными от базового класса TWinControl. Стандартный элемент оконного управления характеризует так называемый "оконный дескриптор" (window handle), который заключен в свойстве Handle. Благодаря оконному дескриптору, Windows "узнает" данную компоненту, в частности, что она может принять фокус ввода и передавать оконный дескриптор функциям Windows API для идентификации рабочего окна.
Хотя вы можете создать оригинальный интерфейсный элемент (который не имеет существующих аналогов и никак не связан с ними), используя TWinControl как отправную точку, C++Builder предоставляет компоненту TCustomControl как раз для этой цели. TCustomControl - это специализированный оконный элемент управления, который упрощает рисование сложных визуальных изображений. Если вашей компоненте не нужно принимать фокус ввода, вы можете наследовать ее от графического элемента управления, который дает экономию системных ресурсов. Все компоненты стандартного оконного управления: кнопки, списки, поля редактирования (за исключением TLabel, которая никогда не принимает фокус ввода) - являются косвенными производными TWinControl.
6.7.2.3 Создание графических компонент
Оригинальные оконные и графические компоненты очень сходны. Однако в отличие от производных TCustomControl, графические компоненты лишены оконного дескриптора и не могут принять фокус ввода. Windows "не узнает" графические компоненты, поэтому их применение не приводит к дополнительным накладным расходам на передачу дескриптора. Графические компоненты обеспечивают отображение объектов без использования системных ресурсов.
Вы должны производить новые графические компоненты от базового абстрактного класса TGraphicControl (который, в свою очередь, является потомком TControl). TGraphicControl предоставляет выбор канвы для рисования и обрабатывает сообщения WM_PAINT. Все, что вам следует сделать, это переопределить метод рисования Paint в соответствии заданными требованиями.
6.7.2.4 Создание невидимых компонент
Мы знаем, что все без исключения компоненты имеют общего прародителя абстрактный класс TComponent. Однако, только невидимые компоненты можно наследовать непосредственно от TComponent.
Любая производная от TComponent наследует все встроенные в нее свойства и методы. Невидимые компоненты встречаются довольно редко и используются, главным образом, в качестве интерфейсных элементов с другими компонентами (доступа к базам данных или как держатели диалоговых окон.
6.7.3 Добавление свойств, событий и методов.
Свойства представляют главную отличительную черту компонент, главным образом потому, что пользователи могут видеть и манипулировать ее свойствами во время проектирования, немедленно наблюдая реакцию времени выполнения программы. Мы уже знаем, что свойства, в отличие от члена данных, сами не хранят данные, однако методы чтения и записи организуют к ним доступ. Помните об этом, когда решите создать или изменить компонентные свойства.
События играют чрезвычайно ответственную роль в поведении компонент, Событие - это связь между некоторым происшествием в системе (таким как воздействие пользователя на компоненту или изменение фокуса) и кодом-обработчиком события, который реагирует на это происшествие. Обработчик события почти всегда пишется прикладным программистом, ибо только он знает, какой должна быть реакция на данное событие. Используя события, прикладной программист может приспособить поведение компонент к своим требованиям, без необходимости изменения самих объектов. Предоставить прикладному программисту такую возможность в отношении новой компоненты и является задачей разработчика компоненты. События, возникающие в результате наиболее типичных действий пользователя (например, движений мышью) встроены во все стандартные компоненты VCL, однако вы также можете определить новые события. Мы уже знаем, что C++Builder реализует события как свойства. Помните об этом, когда решите создать или изменить компонентные события.
Мы уже знаем, что компонентные методы ничем не отличаются от других объектных функций-членов. Хотя C++Builder не вводит никаких специальных ограничений на оформление компонентных методов, имеется ряд правил, которых стоит придерживаться. Помните об этом, когда решите создать или изменить компонентные методы.
6.7.4 Регистрация компоненты
Перед тем как ваша компонента сможет работать на стадии проектирования приложения, C++Builder должен зарегистрировать ее. При регистрации становится известным положение новой компоненты в Палитре компонент C++Builder.
Регистрация компоненты - это простой процесс, который информирует C++Builder о том, какая компонента добавляется к VCL и на какой вкладке Палитры она должна появиться.
Чтобы зарегистрировать компоненту:
1. Добавьте функцию Register к файлу МуСотр.срр, заключив ее имя в пространство имен (заметьте, что название пространства имен начинается с заглавной буквы, а все остальные буквы - прописные).
2. В теле функции Register объявите массив типа TComponentClass, в который введите регистрируемую компоненту.
3. В теле функции Register вызовите функцию RegisterComponents стремя параметрами: название вкладки Палитры компонент, массив компонентных классов и размер компонентных классов.
namespace Mycomp {
void _fastcall Register()
{
TComponentClass classes[1] = {_claesid(TMyComponent)};
RegisterComponents("Samples", classes, 0) ;
) }
Листинг 6.13. Регистрация компоненты.
Листинг 6.13 представляет включение в файл МуСотр.срр кода для регистрации компоненты TMyComponent на вкладке Samples Палитры компонент.
Когда компонента зарегистрирована, вы можете испытать и инсталлировать ее на Палитру, завершая тем самым процесс разработки новой компоненты.
6.7.5 Отладка неинсталлированной компоненты
Вам следует испытать поведение созданной компоненты при выполнении программы до ее инсталляция на Палитру. По существу, вам придется смоделировать те действия, которые производит C++Builder, когда пользователь перемещает компоненту из Палитры на форму. Этот процесс требует выполнения следующих шагов:
1. Включите файл модуля MyComp.h вашей компоненты в заголовочный файл некоторой формы.
2. Добавьте объектный член данных, представляющий испытываемую компоненту, в конец секции public объявлений класса формы, вне области объявлений, которые делает C++Builder.
3. Подсоедините обработчик к событию OnCreate формы.
4. Вызовите конструктор компонентного объекта (компонента отвечает за самоуничтожение, когда наступит время) из обработчика этого события, передав ему параметр, указывающий на владельца компоненты. Обычно параметром служит указатель this на объект, который содержит этот метод. В нашем примере параметр this ссылается на форму.
5. Сразу же за вызовом конструктора установите свойство Parent - родителя компоненты, обычно представляющего собой форму, группирующую рамку или панель инструментов. Обычно значением этого свойства является указатель this. Внимание: Если ваша компонента не является элементом управления, т.е. вы
не наследовали ее от TControl, пропустите этот шаг.
6. Инициируйте значения других свойств компоненты.
Предположим, вы собираетесь испытать компоненту TMyComponent в модуле с именем МуСотр. Создайте новый проект, а затем следуйте перечисленным шагам процесса подготовки модуля формы. Листинг 6.14 содержит законченный образец текста модуля формы отлаживаемой компоненты.
#ifndef TestFormH
#define TestFormH
//---_-_______-_-__-________-_-_._-_____________-_-___-_-_
ttinclude <Classes.hpp>
#include <Controls.hpp> ftinclude <StdCtrls.hpp>
#include <Forms.hpp>
#include "MyComp.h" // 1. //----—---——----—-----—-----—---—_--____-_----------
class TFormI : public Tform {
publ i shed:
private:
public:
TMyComponent* MyComponentI; // 2,
virtual _fastcall TFormI (TComponent* Owner); •// 3,
};
//----—--—---—------—-—-———---—--——-—------——--
extern TFormI *Forml;
//_--__--______----—-----—---------------------—--------
#endif
// Это файл MyComp.cpp модуля формы:
#include <vcl.h>
#pragma hdrstop
#include "TestForm.h" //——-----——-——--—------—-—--——---—--—----—--—--
ftpragma resource "*.dfm"
TFormI *Forml;
//---------—--—-------------------—---—--------------—
_fastcall TFormI::TFormI(TComponent* Owner) : TForm(Owner)
{
MyComponentI = new TMyComponent(this); // 4. MyComponent->Parent = this; // 5. MyComponentl->Left = 12; // 6.
}
Листинг 6.14. Текст модуля формы новой компоненты.
6.7.6 Инсталляция компоненты на Палитру
Компонентные модули, написанные на C++, имеют расширение .срр, а компоненты, написанные на Объектном Паскале, имеют расширение .pas.
При инсталляции новой компоненты или при выполнении команды Component | Rebuild Library, Библиотека Визуальных Компонент перестраивается, и C++Builder создает временный файл CMPLIB32.CPP исходных текстов VCL. Чтобы сохранить этот файл, с помощью команды Options | Environment | Library откройте диалог опций и установите флаг Save Library Source Code.
Чтобы добавить к VCL компоненту, выполните следующие шаги:
1. С помощью команды Component | Install откройте диалоговое окно инсталляции компонент.
2. Нажмите кнопку Add, которая открывает диалог добавления модуля. Введите имя модуля непосредственно в поле Module Name или найдите его местоположение, нажав на кнопку поиска Browse. Имя добавленного вами компонентного модуля появится внизу списка названий группы Installed Components. В списке Component classes вы увидите имена компонентных классов, уже находящихся в выбранной группе Библиотеки. У вновь введенного модуля имя компонентного класса отсутствует.
3. Нажмите кнопку ОК, закрывая диалог инсталляции компонент. Библиотека будет перестроена и новая компонента установлена на ту вкладку Палитры, которую вы определили как параметр функции регистрации (см. Листинг 6.13).
Чтобы удалить компоненту из VCL, выполните следующие шаги:
1. Выполните команду Component | Install, которая открывает диалоговое окно установки компонент.
2. Найдите ненужный вам более компонентный класс в списке Component classes выбранной группы Библиотеки и нажмите кнопку Remove.
3. Нажмите кнопку ОК. Библиотека будет перестроена и новая компонента удалена из Палитры.
Чтобы перестроить Палитру, выполните следующие шаги:
1. Откройте диалог установки опций Палитры с помощью команд Component | Configure Palette или Options | Environment | Palette.
2. Нажмите кнопку Add и выберите имя для новой вкладки. Имя добавленной вами вкладки появится внизу списка Pages названий вкладок.
3. Перетащите мышью выбранную компоненту в списке Components на нужную вкладку списка Pages.
4. Нажмите кнопку ОК. Библиотека и Палитра будут перестроены.
6.7.7 Сохранение файлов новой компоненты
Когда вы закончите процесс разработки, созданная компонента будет представлена следующими файлами:
• объектный файл результата компиляции MyComp.obj;
• заголовочный файл объявлений, сгенерированный компилятором (MyComp.h для исходного текста на C++ или MyComp.hpp для исходного текста на Объектном Паскале);
• файл битового образа Палитры (MyComp.res или MyComp.dcr);
• файл формы MyComp.dfm, если компонента использует форму.
Перед тем, как использовать вновь созданную компоненту, перепишите в каталог \.. .\CBuilder\LIB\OBJ следующие файлы компоненты МуСотр: все двоичные файлы (с расширениями .dfm, .res и .dcr), все исходные файлы (с расширениями .срр или .pas), все объектные файлы (с расширениями .obj и .Но) и все заголовочные файлы (с расширениями .h или .hpp). Желательно создать и сохранить контекстно-справочный файл (с расширением .hip).