Создание визуальных компонентов в ИСР C++ Builder.


ЛАБОРАТОРНАЯ РАБОТА №5.

Тема: Создание визуальных компонентов в ИСР C++ Builder.

Введение

Процесс разработки собственного компонента (назовем его TMyComponent) проходит через выполнение следующих обязательных этапов:
1. Создание модуля нового компонента.
2. Наследование производного класса TMyComponent от существующего базового компонентного класса.
3. Добавление нужных свойств, событий и методов.
4. Регистрация компонента в C++ Builder.
5. Испытание компонента.
6. Инсталляция компонента на Палитру.
7. Сохранение файлов компонента.
Далее будет показано, как некоторые из перечисленных действий, программируемых вручную, мастер компонентов способен выполнить автоматически (создание файлов модуля, наследование компонентного класса, объявление нового конструктора и , регистрация компонента).

1. Создание модуля

Программный модуль состоит из двух файлов МуСотр.срр и МуСотр.h, которые компилируются в объектный файл с расширением МуСотр.оbj. С++ Builder использует модули в различных целях — каждая форма (или логическая группа компонентов) имеют свой собственный модуль. При разработке компонента вы либо создаете новый модуль, или добавляете его к существующему модулю.
Чтобы создать новый модуль компонента, выполните команду File | New и выберите значок Unit. Если модуль уже существует, выполните команду File | Ореn и отыщите ваш файл МуСотр.срр. Имея модуль в окне Редактора кода, можно приступить к разработке. Для начала перечислите в МуСотр.h необходимые файлы предкомпиляции и объявите производный класс вашего компонента с объектным конструктором (Листинг 1).

# ifndef MyCompH
#define MyCompH
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>

class PACKAGE TMyComponent:public<базовый класс>
{
public:
_fastcall TMyComponent (TCompon* Owner);
};
#endif
Листинг 1. Заготовка интерфейсной части модуля MyComp.h

Начиная с версии С++ Builder 3 объявление нового компонентного класса должно включать макрос РАСКАGЕ. Функционально сходные компоненты группируются в пакеты — динамические библиотечные файлы с расширением BPL. Как и обычные DLL, пакеты содержат код, разделяемый многими приложениями. Пакетная организация ускоряет компиляцию и сборку приложений, позволяет получать более эффективные исполняемые коды за счет того, что к готовой программе VCL уже не подгружается целиком.
Естественно, что новый компонент пока представлен пустым кодовым файлом МуСотр.срр (Листинг 2).
#include <vcl.h>
#pragma hdrstop
#include “MyComp.h”

#pragma package(smart_init)
_fastcall TMyComponent::TMyComponent (TComponent* Owner):<базовый класс>(Owner)
{
}

Листинг 2. Заготовка кодовой части модуля MyComp.cpp

Пока мы создали компонент, который ничем не отличается от своего родителя. В следующем разделе описываются варианты наследования в зависимости от выбранного типа базового компонентного класса.

2. Наследование

Любой компонент можно произвести от общего прародителя ТComponent, от более специализированных наследников ТWinControl или ТGraphicControl, а также от иного существующего компонентного класса. Компонентом способен стать практически любой элемент вашей программы, поведением которого вы хотите управлять на стадии проектирования.

Цель Базовый класс
Модификация существующего компонента Любой существующий компонент (например, TListBox) или абстрактный класс (TCustomListBox)
Создание адаптированного компонента TCustomControl
Создание графического компонента TGraphicControl
Создание невидимого компонента TComponent

2.1. Модификация существующих компонентов

Простейший способ построить новый компонент — это начать с существующего и изменить его свойства. Вашей целью может являться добавление, исключение или замена значений по умолчанию некоторых свойств компонента-образца. Вы можете использовать для этой цели любой подходящий абстрактный класс, в название которого входит слово Custom.
Например, вы можете произвести новый компонент списка со специальными свойствами, которых нет в стандартном классе ТListВох. Поскольку нельзя прямо модифицировать ТListВох, вы должны начать с его ближайшего предшественника в иерархии классов. Для этой цели лучше всего подходит ТCustomListBox, который реализует все мыслимые свойства производных компонентов списка, однако не выставляет всех их в секции _published.
Наследуя ваш компонент от одного из абстрактных типов, вы всего лишь объявляете в секции _published модуля МуСоmр.h свойства родителя, которые хотите включить в ваш компонент, оставляя остальные в секции protected.

2.2. Адаптация оконных компонентов

С оконным интерфейсным элементом, видимым во время работы программы, пользователь обычно может взаимодействовать. Все оконные компоненты являются производными от базового класса ТWinControl. Стандартный оконный элемент управления характеризует так называемый оконный дескриптор (window handle), который заключен в свойстве Handle. Благодаря оконному дескриптору Windows «узнает» данный компонент, в частности, что он может принять фокус ввода и передавать оконный дескриптор функциям Windows API для идентификации рабочего окна.
Конечно, вы можете создать оригинальный интерфейсный элемент (который не имеет существующих аналогов и никак не связан с ними), используя TWinControl как отправную точку. Однако компонент TCustomControl более подходит для этой цели. TCustomControl — это специализированный оконный элемент управления, который упрощает рисование сложной графики. Если вашему компоненту не нужно принимать фокус ввода, вы можете наследовать его от графического элемента управления, что дает экономию системных ресурсов. Все компоненты стандартного оконного управления: кнопки, списки, поля редактирования (за исключением TLabel, который никогда не принимает фокус ввода) являются косвенными производными TWinControl.

2.3. Создание графических компонентов

Оконные и графические компоненты очень сходны. Однако в отличие от производных TCustomControl графические компоненты лишены оконного дескриптора и не могут принять фокус ввода. Windows «не узнает» графические компоненты, поэтому их применение не приводит к дополнительным накладным расходам на передачу дескриптора. Графические компоненты обеспечивают отображение объектов без использования системных ресурсов.
Вы должны производить новые графические компоненты от базового абстрактного класса TGraphicControl, который предоставляет канву для рисования и обрабатывает сообщения WM_PAINT. Все, что вам следует сделать, — это переопределить метод рисования Paint: в соответствии с заданными требованиями.

2.4. Создание невидимых компонентов

Мы знаем, что все без исключения компоненты имеют общего прародителя — абстрактный класс ТComponent. Однако только невидимые компоненты можно наследовать непосредственно от ТСomponent.
Невидимые компоненты встречаются довольно редко и используются, главным образом, в качестве интерфейсных элементов с другими компонентами (доступа к базам данных или как держатели диалоговых окон).

3. Добавление свойств, событий и методов

Свойства представляют главную отличительную черту компонентов, главным образом потому, что пользователи могут видеть и манипулировать свойствами во время проектирования, немедленно наблюдая реакцию программы. Мы уже знаем, что свойства в отличие от членов данных сами не хранят информацию, однако методы чтения и записи организуют к ним доступ. Помните об этом, когда решите создать или изменить компонентные свойства.
События играют чрезвычайно ответственную роль в поведении компонентов. Событие — это связь между некоторым происшествием в системе (таким, как воздействие пользователя на компонент или изменение фокуса) и кодом-обработчиком события, который реагирует на это происшествие. Обработчик события почти всегда пишется прикладным программистом, ибо только он знает, какой должна быть реакция на данное событие. Используя события, программист может приспособить поведение компонентов к своим требованиям без изменения самих объектов. Предоставить прикладному программисту такую возможность в отношении нового компонента и является задачей разработчика. События, возникающие в результате наиболее типичных действий пользователя (например, движений мышью) встроены во все стандартные компоненты VCL, однако не возбраняется определить новые события. Мы уже знаем, что С++ Builder реализует события как свойства. Помните об этом, когда решите создать или изменить компонентные события.
Известно, что компонентные методы ничем не отличаются от других объектных функций-членов. Хотя С++ Builder не вводит никаких специальных ограничений на оформление компонентных методов, имеется ряд правил, которых стоит придерживаться. Вспомните эти правила, когда решите создать или изменить компонентные методы.

4. Регистрация

Перед тем как ваш компонент сможет работать на стадии проектирования приложения, С++ Builder должен зарегистрировать его. При регистрации становится известным положение нового компонента в Палитре.
Регистрация компонента — это простой процесс, который информирует C++ Builder о том, какой компонент добавляется к VCL и на какой странице Палитры он должен появиться:
1. Добавьте функцию Register к файлу МуСотр.срр, заключив ее имя в пространство имен. Заметьте, что название пространства имен совпадает с именем модуля. Название начинается с заглавной буквы, а все стальные буквы — прописные. Не забудьте еще раз записать ключевое слово РАСКАСЕ перед именем функции.
2. В теле функции Register объявите массив типа TComponentClass, в который введите регистрируемый компонент.
3. Из функции Register вызовите функцию RegistarComponents с тремя параметрами: название страницы Палитр компонентов, массив компонентных классов и индекс последнего класса в этом массиве.
Листинг 3 показывает включение в файл МуСотр.срр кода регистрации компонента ТMyComponent на странице МуSamples.
Когда новый компонент зарегистрирован, вы можете испытать и инсталлировать его на Палитру, завершая тем самым процесс разработки.

_fastcall TMyComponent::TMyComponent(TComponent* Owner): <базовый класс>(Owner)
{
}
namespace MyComp
{
void_fastcall PACKAGE Register()
{
TComponentClass classes[1]={_classid (TMyComponent)};
RegisterComponents(“MySamples”,classes,0);
}
}
Листинг 3. Регистрация компонента в кодовом модуле MyComp.cpp

5. Испытание

Вам следует испытать поведение созданного компонента до его инсталляции на Палитру. По существу, вам придется смоделировать те действия, которые производит С++ Builder, когда пользователь перемещает компонент из Палитр на форму. Этот процесс требует выполнения следующих шагов:
1. Командой File | New Application создайте тестовое приложение.
2. Командой Ргоject |Аdd to Project добавьте модуль МуСотр к проекту.
3. Включите в заголовок интерфейсного модуля формы приложения (Unit.h по умолчанию) инструкцию: #include «MyComp.h» .
4. Объявите объект испытываемого компонента в секции public класса формы вне области объявлений, которые С++ Builder делает самостоятельно.
5. В кодовом модуле (Unit.срр по умолчанию) запишите вызов конструктора компонентного объекта (компонент отвечает за самоуничтожение, когда наступит время), передав ему параметр/ указывающий на владельца. Обычно параметром служит указатель this на объект, который содержит этот метод. В нашем случае this ссылается на форму.
6. Сразу же за вызовом конструктора установите свойство Раrent — родителя компонента. Обычно значением этого свойства является указатель this. Внимание. Если ваш компонент не является элементом управления, т.е. вы не наследовали его от ТСontrol, пропустите этот шаг.
7. Инициируйте значения других компонентных свойств.
# ifdef Unit1H
#define Unit1H

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include “MyComp.h”

class TForm1:public TForm
{
_published:
private:
public:
TMyComponent* MyComponent;
_fastcall TForm1(TComponent* Owner);
};
extern PACKAGE TForm *Form1;
#endif

#include <vcl.h>
#pragma hdrstop
#include “Unit.h”
#pragma package(smart_init)
#pragma resource “*.dfm”
TForm1 *Form1;
_fastcall TForm1::TForm1(TComponent *Owner):TForm(Owner)
{
MyComponent1=new TMyComponent(this);
MyComponent->Parent=this;
MyComponent->Left=12;
}
Листинг 4. Текст модуля формы для отладки нового компонента.

Листинг 4 показывает законченный текст обеих составляющих модуля формы со включениями, пронумерованными в соответствии с перечисленными шагами. Добавьте необходимый код для проверки и установки специфических компонентных свойств. Скомпилируйте и запустите тестовое приложение. Если результат отладки компонента вас удовлетворяет, можно перейти к его установке на Палитру.

6. Инсталляция на Палитру

Перед тем, как приступить к инсталляции, надо создать пиктограмму, которой новый компонент будет представлен в Палитре. Если не сделать этого, С++ Builder подставит пиктограмму базового класса. Командой Тооls|Image Editor откройте редактор изображений.
? Из меню редактора выберите команду File|New|Component Resource Kit, а затем – Resource|New|Bitmap.
? В диалоге свойств битового образа установите размеры пиктограммы 24×24 и число цветов VGA (16 Colors). Переименуйте битовый образ компонента (ТМУСОМР) по команде Resource | Rename и дважды щелкните мышью на выбранном имени в древовидном списке ресурсных файлов. Нарисуйте подходящую картинку.

? Командой File | Save As сохраните ресурсный файл в своем рабочем каталоге (под именем МуСотр.dcr) и закройте редактор изображений.
? Теперь командой Component| Install Component откройте диалоговое окно инсталлятора. Выберите вторую вкладку Into new package, если компонент устанавливается в новый пакет:

Введите имя модуля МуСотр непосредственно в поле Unit file name или найдите его местоположение, нажав кнопку Вrowse. Годятся как файлы кодовых модулей с расширением СРР, написанные на языке С++, так и компоненты на Объектном Паскале с расширением РАS. Введите имя нового пакета (совпадающее с названием страницы Палитр) в окошко Package file Name, а его краткое описание — в область Package description.
? Добавление компонента в существующий пакет производится аналогичным образом в диалоге вкладки Into existing package.

Ознакомьтесь с текущим содержимым пакета. Все файлы, составляющие пакет МуSamples, будут созданы (или перестроены) и новый компонент установлен на ту страницу Палитр, которую вы определили как параметр функции регистрации. С помощью Редактора кода вы сможете просмотреть (и даже редактировать) проектный файл МуSamples.срр. С++ Builder 4 автоматически включает в проект все сиcтемные пакеты периода исполнения (файлы с расширением BPI), необходимые для сборки текущего пакета. Нажмите кнопку Instа11 и приготовьтесь ждать сообщения об окончании компиляции, перестройки VCL и установки нового компонента на Палитру.
Командой Component|Install Package или Project|Options откройте список инсталлированных пакетов.

Нажав кнопку Components, вы увидите список всех компонентов, включенных в выбранный пакет, вместе с их пиктограммами. Сделайте отметку в ячейке Default, если хотите, чтобы текущая конфигурация пакетов принималась по умолчанию в каждом новом создаваемом проекте. Внимание. Будьте осторожны, если вы решили удалить из списка выбранный пакет кнопкой Remove или снять отметку слева от его названия. Все компоненты, зарегистрированные в указанном пакете, станут недоступными формам ваших приложений. Чтобы восстановить потерянный компонент, придется повторять процедуру инсталляции с самого начала.

Командой Component | Configure Pallete или Тоо1s | Environment Options откройте диалог конфигурации вашей Палитры.

Используя прием перетаскивания «drag-and-drop», вы сможете мышью менять порядок страниц Палитр (в графе Pages) и установленных на них компонентов (в графе Сотропепts). Кнопка Аdd предназначена для добавления, кнопка Delete — для вычеркивания, кнопка Rename — для переименования выбранной страницы. Заметьте, что эти кнопки запрещены в графе Сотропепts, поскольку подобные действия связаны с перестройкой пакетов.

7. Справочный файл

Решившись предоставить свой компонент для внешнего использования, придется придать ему товарный облик — сопроводить контекстно-чувствительной помощью режима online. Составление НLР файла не доставляет особой радости разработчику компонентов, хотя компилятор справочных файлов НСW (Microsoft Help Workshop) из каталога \…\Неlр\Тоо1s облегчает этот неблагодарный труд. А интеграция вашего файла в единую справочную службу среды С++ Builder происходит буквально автоматически. Используя свой любимый текстовый процессор (скорее всего, это будет Мicrosoft Word), вы должны сначала подготовить текст документа в виде книги, состоящей из разделов. Справочный файл должен, по меньшей мере, содержать общее описание вашего компонента и отдельный раздел по каждому выставляемому свойству и событию.
Каждый раздел книги может иметь произвольный размер. Вы сможете легко менять шрифт текста, вставлять иллюстрации и простые таблицы. Однако не переусердствуйте — HCW может подавиться сложными элементами форматирования. Избегайте нестандартных шрифтов, сложных таблиц, используйте изображения только в формате ВМР. Не увлекайтесь режимом форматирования «Кеер with Next», посредством которого в обычных документах заголовок связывается с последующим параграфом. HCW воспринимает такие заголовки как непрокручиваемые области, которым разрешено появляться только однажды, наверху каждого раздела. Конец раздела отмечайте принудительным разделителем страниц (клавиши С1г1+Еnter в MS Word).
НСW требует специальную информацию о каждом разделе, чтобы произвести результирующий НLР файл. Необходимо озаглавить основные разделы, отметить ключевые слова и фразы для составления указателя, а также присвоить разделам идентификаторы с тем, чтобы НСW смог построить гипертекстовые переходы. Если вы хотите, чтобы читатель просматривал разделы книги в определенном порядке, вы должны присвоить им коды последовательности просмотра. Вся эта информация записывается в нижних колонтитулах документа — сносках (Footnotes). Когда вы встречаете в тексте книги маркер сноски (например, символ *), это означает, что внизу страницы появится текст, начинающийся с того же символа. НСW читает разделы сходным образом: текст сноски (например, с символом $) становится заголовком текущего раздела. Рассмотрим содержание сносок и маркерные символы, которые их идентифицируют.

7.1. Ключевое слово ‘К’
Эти ключевые слова перечисляются в указателе справочной службы (Index) команды Не1р. В каждом разделе можно определить любое число ключевых слов или фраз, используя следующую запись:
K TThreaderTimer;Timer;TThreadPriority; Priority
Когда читатель выбирает некоторое ключевое слово в указателе, выдается список заголовков всех разделов, содержащих данное слово. Щелкнув мышью по заголовку, можно просмотреть соответствующий раздел.

7.2. Код последовательности просмотра ‘+’
С помощью кнопок Next или Ргеviоs, расположенных в верхней части окна справки, можно перемещаться от странице к странице. Последовательность просмотра страниц задается кодом просмотра, например +001.
Поскольку этот код алфавитно-цифровой, он подчиняется правилам сортировки. Это очень удобно. Пусть сначала ваша последовательность была пронумерована кодами просмотра +001, +002, +003 и т.д. Если потом вам потребовалось добавить подразделы, нумеруйте их по принадлежности, например +002-01 и +002-02. Менять нумерацию всех страниц не надо.

7.3. Идентификатор раздела ‘#’

Каждый раздел должен иметь уникальный номер, например #1001. Идентификаторы разделов используются в гиперпереходах. Чтобы образовать гиперпереход, отметьте шрифт гипертекста двойным подчеркиванием и допишите к нему (без пробелов!) идентификатор раздела, к которому хотите перейти, помеченный как Hidden. В МS Word делается в диалоге команды Format | Font:

В исходном документе гиперпереход выглядит невзрачно:
… Свойство State определяет …
После компиляции справочного файла гипертекст будет выделен зеленым цветом и одиночным подчеркиванием:
… Свойство State определяет …
Щелкнув мышью по гипертексту, читатель увидит нужный раздел.

7.4. Ключевое слово ‘А’

Когда вы выбираете некоторое свойство или событие в окне Инспектора объектов и нажимаете клавишу F1, справочная служба С++ Builder производит поиск по всем ключевым словам ‘А’, чтобы вывести соответствующий раздел. Так, например, сноски разделов о свойстве и событии компонента TThreadedTimer должны записываться следующим образом:

А TThreadedTimer_Priority;Priority_Property;Priority
А TThereadedTimer_OnTimer;OnTimer_Event;OnTimer

Для включения самого компонента в список ключевых слов ‘А’ используется спецификатор _Оbject:

А TTherededTimer_Object;TThereadedTimer

Если обнаруживается несколько разделов по заданной тематике, читателю предоставляется список для выбора.

7.5. Компиляция

Подготовив текст разделов со всеми сносками, вы должны сохранить его как документ RichTextFormat (RTF). Если ваш текстовый процессор испытывает идиосинкразию к RTF, утешьтесь тем, что вы не одиноки, или тем, что формат RTF не намного сложнее, чем НТМL.
Теперь запустите компилятор HCW. Интерфейс последней версии 5.0 произведет на вас приятное впечатление. Применение настолько просто и интуитивно, что дальнейшие инструкции, возможно, покажутся излишними.
? Сначала выполните команду File|New и создайте в своем рабочем каталоге файл
оглавления МуСотр.cnt:

В открывшемся красивом диалоге нажмите кнопку Add Above (или Аdd Below). Специфицируйте разделы, включаемые в оглавление.

Теперь той же командой File | New создайте в своем рабочем каталоге проектный файл с именем МуСотр.hрj. Нажмите кнопку Options и в диалоге вкладки Files определите проектные составляющие (файлы с расширениями НLР, RTF и СNТ):

Кнопкой Save and Compile сохраните и скомпилируйте готовый к употреблению справочный файл МуСотр.hlp.

Интеграция файла в единую справочную службу среды С++ Builder происходит легко и непринужденно, если воспользоваться инструментом ОН (ОрепНеlр) из каталога \…\Bin. Командой File | Open Project откройте проект единой справочной службы ВСВ5.оhр из каталога \…\Не1р\. Выберите вкладку сводной справочной таблицы Contents и командой Edit | Add Files добавьте файл оглавления МуСотр.спt.

Остается сохранить обновленный проект ВСВ5.оhр. Рекомендуется вычеркнуть скрытые файлы с расширениями GID и FTS, чтобы заставить WinHelp создать новые. В следующий раз, когда вы попытаетесь открыть файл ВСВ5.hlp справочной службы, WinHelp считает текущую конфигурацию, а затем создаст ВСВ5.gid, который теперь будет содержать ссылки на разделы вашего файла МуСотр.hlp.
Чтобы испытать ключевые слова ‘К’ из ваших разделов, откройте файл ВСВ5.hlр и введите в указатель начальные буквы названия вашего компонента ТМуСоmр… Вас должны сразу же перенести в указанный раздел. Чтобы проверить ключевые слова ‘А’, укажите мышью свой компонент на Палитре и нажмите клавишу F1. Результат будет тем же самым. Повторите эту процедуру для каждого выставленного свойства, метода и события.

8. Редакторы компонентных свойств

Когда вы закончили с документацией, можно считать, что ваш компонент готов для широкого распространения. Почти готов… Действительно, вы можете обнаружить, что компонент выставляет какие-то свойства, значения которых не так-то удобно менять.
Типичный пример: пусть ваш компонент имеет свойство FileName, содержащее имя файла. Гораздо приятнее определять значение этого свойства в диалоге, чем вводить полное имя вручную. Редактор свойства активизируется и открывает модальный диалог класса TOpenDialog, когда пользователь нажимает кнопку с многоточием в графе значений Инспектора объектов. Прежде чем изобретать новый редактор свойства, вспомните о готовых инструментах, разделяемых зарегистрированными компонентами VCL:

Редактор… Свойство|тип Компоненты
Текстовых строк Lines|TString TMemo
Элементов списка Items|TString TListBox
TComboBox
TRadioGroup
Пиктограмм Glyph|TBitmap TBitBtn
TSpeedButton
Масок формата Editmask|99/99/00 TMaskEdit
Изображений BMP Picture|TBitmap TImage
Вкладок Tabs|TStrings TTabControl
Страниц блокнота Pages|TStrings TNotebook
Элементов дерева Items|TTreeNodes TTreeView
Элементов списка Items|TListItems TListView
Заголовков столбцов Sections|THeaderSections THeaderControl
Статусных панелей Panels|TStatusPanels TStatusBar
Панельных шторок Bands|TCoolBands TCoolBar
Имени файла FileName TAnimate
TClientDataSet
TMediaPlayer
Фильтры расширений Filter Со страницы Dialogs
Связи master-detail MasterFields TTable
Команды SQL SQL|TStrings TQuery
Параметров SQL Params|TParams TQuery
Столбцов сетки Colums|TDBGridColums TDBGrig

В тот самый момент, когда вы перенесли компонент на форму, дизайнер форм сканирует внутренний список редакторов зарегистрированных компонентов, пытаясь отыскать тот, который можно использовать с вашим компонентом. Далее Дизайнер форм создает экземпляр редактора, который, в свою очередь, повторяет тот же самый процесс — сканирует внутренний список зарегистрированных редакторов свойств и создает экземпляр редактора для каждого свойства, которое ваш компонент выставил.
В файле предкомпиляции DsgnIntf.hрр определена группа узкоспециализированных потомков базового класса редактора TPropertyEditor (хотя разрешается произвести от него свой собственный оригинальный класс):

Производный класс Типы редактируемых свойств
TOrdinalProperty Ординальные типы (int, char, enum)
TIntegerProperty Целый тип в диапазоне расширенных значений
TCharProperty Символьный тип в диапазоне расширенных значений
TEnumProperty Перечисляемый тип
TFloatProperty Числа с плавающей точкой
TStringProperty Строки AnsiString
TSetElementProperty Элементы булевых множеств (true или false)
TSetProperty Множества нельзя редактировать непосредственно, они раскрываются списком вложенных свойств
TClassProperty Имена классов раскрываются списками их свойств
TMethodProperty Указатели методов, главным образом событий
TComponentProperty Указатели компонентов той же формы. Свойства других компонентов нельзя редактировать.
TColorProperty Цвет. Выпадающий список содержит символические названия (или шестнадцатеричные эквиваленты) цветовых констант. Двойной щелчок мышью открывает диалог выбора оттенка цвета
TFontNameProperty Имена инсталлированных шрифтов с выпадающими списками их названий
TFontProperty Шрифты со списками вложенных свойств. Двойной щелчок мышью открывает диалог выбора шрифта.

Чтобы сконструировать оригинальный редактор и наделить его требуемой функциональностью, в модуль компонента необходимо внести следующие включения:
1. Произвести производный класс (прямо или косвенно от ТPropertyEditor).
2. Переопределить виртуальный метод чтения GetValue с целью преобразовать значение свойства к текстовому виду, в котором оно предъявляется Инспектором объектов. Метод записи SetValue выполняет обратное преобразование введенного значения.
3. Переопределить виртуальный метод Edit для диалогового редактирования свойства, которое само является классом (например, Font). Когда программист нажимает кнопку с многоточием (или дважды щелкает мышью), Инспектор объектов открывает диалог зарегистрированного редактора.
4. Методом GetAttributes проинформировать Инспектор объектов о специфических атрибутах данного редактора.
5. Методом RegisterPropertyEditor зарегистрировать класс редактора.

Следуя изложенной методике, создадим простой редактор некоторого текстовото свойства MyProperty типа AnsiString. Задача редактора — выбирать указанное значение из выпадающего списка, а не заставлять пользователя вводить его вручную. Надо лишь правильно запрограммировать необходимые включения в интерфейсный (Листинг 5) и кодовый (Листинг 6) модули компонента.

#ifndef MyCompH
#define MyCompH

#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <StdCtrls.hpp>
#include <DsgnIntf.hpp>

class PACKAGE TMyComponent : public TComponent
{
private:
AnsiString FMyProperty;
protected:
public:
__fastcall virtual TMyComponent (TComponent* Owner):
TComponent (Owner) {}
__published:
__property AnsyString MyProperty=
{ read=FMyProperty, write=FMyProperty };
};

class TMyEditor : public TStringProperty
{
public:
__fastcall TMyComponent (void)
:DsgnIntf::TStringProperty(Designer,0) {}
TPropertyAttributes __fastcall GetAttributes ();
void __fastcall GetValues(TGetStrProc StrVal);
void __fastcall Edit();
};

#endif

Листинг 5. Объявление класса TMyEditor в интерфейсном модуле MyComp.h

#include <vcl.h>
#pragma hdrstop
#include “MyComp.h”
#pragma package(smart_init)

static inline TMyComponent *ValidCtrCheck()
{
return new TMyComponent (NULL);
}

void __fastcall TMyEditor::Edit()
{
TOpenDialog* openfile=new TOpenDialog(NULL);
openfile->Filter=”Text file|*.txt”;
if (openfile->Execute()) SetValue(openfile->FileName);
delete openfile;
}

TPropertyAttributes __fastcall TMyEditor::GetAttributes()
{
return TPropertyAttributes()<<paDialog<<paValueList;
}
void __fastcall TMyEditor::GetValue(TGetStrProc StrVal)
{
StrVal(“0-Lowest”); StrVal(“3-Lower”);
StrVal(“5-Normal”); StrVal(“7-Higher”);
StrVal(“10-Highest”); StrVal(“99-TimeCrritical”);
}

namespace MyComp
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1]={__classid(TMyComponent)};
RegisterComponent(“MySamples”,classes,0);
PTypeInfo typeinfo=*GetPropInfo(__typeinfo(TMyComponent),”My Property”)->PropType;
RegisterPropertyEditor(typeinfo,__classid(TMyComponent),”MyProperty”,__classid(TMyEditor));
}
}

Листинг 6. Реализация редактора свойства в кодовом модуле MyComp.cpp

Установите компонент на Палитру и перетащите его на какую-нибудь форму. Если дважды щелкнуть мышью по значению свойства MyProperty, откроется стандартный диалог класса ТOpenDialog. Очевидно, что в практических разработках вам придется более разумно переопределять метод Edit:. Тогда Инспектор объектов будет вызывать специализированный диалог, давая возможность редактировать значения компонентного свойства самым удобным образом.
Итак, мы закончили разработку редактора свойства. Затея может показаться совершенно бессмысленной, ведь сам компонент абсолютно бесполезен. Однако все эти ухищрения действительно облегчают работу программиста с вашим замечательным компонентом, что будет способствовать росту его популярности.

9. Сохранение файлов нового компонента

Когда вы закончите процесс разработки, созданный компонент будет представлен следующими файлами:
• пакетные файлы МуSamples с расширениями bpl, bpk, lib, bpi, cpp, map, res
• кодовый модуль (МуСотр.срр или МуСотр.рas);
• интерфейсный модуль (МуСотр.h или МуСотр.hрр);
• пиктограмма компонента для Палитр (МуСотр.dcr);
• объектный файл МуСотр.оbj,
• файл формы МуСотр.dfm, если компонент использует форму;
• желательно создать и сохранить контекстно-справочный файл (МуСотр.hlр).

По умолчанию С++Вuilder 4 сохраняет пакет bрl в каталоге \…\Projects\Врl, а библиотеки lib, bpi — в каталоге \…\Рrojects\Lib. Внимание. Используя новый компонент в дальнейшем, не забывайте проверять вкладку Directories/Conditionals команды Рroject | Орtions, где должен быть «проложен путь» к библиотечному каталогу:

КОНТРОЛЬНЫЕ ВОПРОСЫ

1. Создание модуля компонета
2. Наследование
3. Свойства, события и методы компонента.
4. Регистрация
5. Испытание
6. Инсталляция на Палитру
7. Справочный файл

ИНДИВИДУАЛЬНЫЕ ЗАДАНИЯ

В соответствие с полученным индивидуальным заданием спроектировать следующий визуальный компонент и продемонстрировать его работу на примере приложения:
1. TLight: простейший бинарный индикатор, меняющий цвет при изменении состояния.
2. TSlider: регулятор (см. TTrackBar Win32) , изменяющий ширину области прокрутки.
3. TNextButton: кнопка перебора объектов формы по нажатию определенной клавиши.
4. TThreadedTimer: таймер с различными приоритетами точности (исп-ся производный от TThread класс таймерного потока TTimerThread).
5. TSearchDialog: диалог поиска в базе данных по вводу начальных букв слова.
6. TThePicture: вставка на определенное пользователем место формы заданного рисунка.
7. TTheHeader: вставка сверху в центр формы заголовка заданного пользователем.

Загрузка...