SlideShare a Scribd company logo
1 of 8
Download to read offline
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
1
Лекция 13-3
Разработка компонент в C++Builder
Как уже было отмечено, среда С++Builder содержит большое количество
стандартных компонент, позволяющих упростить разработку приложений.
Программисты могут расширять функциональность системы благодаря
возможности создания собственных пользовательских компонент. Созданные
компоненты могут быть помещены в палитру компонент, для них могут быть
созданы редактор компонента, редакторы свойств, а также файл помощи. Таким
образом, дальнейшая работа с созданным компонентом ничем не отличается от
работы со стандартными компонентами. Созданные компоненты могут быть
объединены в пакеты для упрощения их установки. Существует большое
количество коммерческих и свободно распространяемых дополнительных пакетов
компонент. Кроме того, программисты могут сами создавать компоненты для
упрощения дальнейшей разработки приложений. Рассмотрим процесс создания
компонент более подробно.
1. Процедура разработки компонента C++Builder
При разработке нового компонента необходимо наследовать его от какого-
либо стандартного класса в соответствии с принципами наследования ООП. Как
уже было отмечено, все компоненты должны быть наследованы как минимум от
класса TComponent. Процедура создания и установки компонентов в среде
С++Builder автоматизирована. Для автоматической генерации заготовки нового
компонента можно выбрать пункт главного меню Component | New Component.
Далее в появившемся окне список выбора “Ancestor Type” позволяет выбрать имя
класса, от которого будет наследован компонент. В поле “Class Name” указывается
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
2
имя будущего класса. В соответствии с нотацией, принятой в среде С++Builder,
имена классов должны начинаться с заглавной буквы “T”. В поле “Palette Page”
указывается закладка, на которой будет располагаться компонент. В поле “Unit file
name” указывается полный путь и имя файла, который будет содержать новый
класс. После нажатия на кнопку “ОК” по указанному пути будет сгенерировано два
файла c расширениями *.cpp и *.h и именами, совпадающими с именем класса без
начальной буквы “T”. Кроме того, будет отображено окно редактирования этих
файлов. В самих файлах уже будет содержаться код для определения класса и
инсталляции компонента. Программист должен добавить в этот код все
необходимые функциональные возможности нового компонента. Допустим, мы
выбрали в поле “Ancestor Type” класс TComponent, в поле “Class Name” –
TOurComponent, в поле “Palette Page” – OurSample, тогда будет сгенерирован файл
OurComponent.h
#ifndef OurComponentH
#define OurComponentH
#include <SysUtils.hpp>
#include <Classes.hpp>
class PACKAGE TOurComponent : public TComponent
{private:
protected:
public:
__fastcall TOurComponent(TComponent* Owner);
__published:};
#endif
Вместе с заголовочным файлом будет создан файл OurComponent.cpp
#include <basepch.h>
#pragma hdrstop
#include "OurComponent.h"
#pragma package(smart_init)
static inline void ValidCtrCheck(TOurComponent *)
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
3
{ new TOurComponent(NULL); }
__fastcall TOurComponent::TOurComponent(TComponent* Owner)
: TComponent(Owner){ }
namespace Ourcomponent
{ void __fastcall PACKAGE Register()
{TComponentClass classes[1] = {__classid(TOurComponent)};
RegisterComponents("OurSamples", classes, 0);}}
Как видно из приведенного примера создается заготовка для конструктора, а
также определяются две функции ValidCtrCheck и Register. Функция ValidCtrCheck
необходима для проверки наличия в создаваемом компоненте чистых виртуальных
функций. Данная функция будет вызвана при установке компонента. В ней просто
производится попытка создания экземпляра компонента, что в случае наличия
чистой виртуальной функции приведет к генерации ошибки и отмене инсталляции.
Функция Register регистрирует компонент в палитре компонентов. В первом
параметре указывается имя закладки в палитре компонент, второй - параметр-
массив указателей на метаклассы регистрируемых компонент, третий содержит
количество регистрируемых компонентов минус 1.
Для компонента может быть создана пиктограмма, которая будет
отображаться в палитре компонентов. Для этого необходимо использовать Image
Editor из пункта главного меню Tools. В этом редакторе необходимо выбрать пункт
File | New | Component Resource File (.dcr), а затем пункт Resource | New | Bitmap и
задать размер 24х24 пиксела. Необходимо переименовать созданный Bitmap,
назвав его так же, как и будущий класс компонента, но заглавными буквами. Для
нашего случая это будет имя TOURCOMPONENT. Далее можно нарисовать
необходимый рисунок, учитывая, что цвет левого нижнего квадрата будет
считаться прозрачным. Сам файл ресурса необходимо сохранить в том же каталоге,
что и файлы .cpp и .h, с тем же именем, но с расширением .dcr. Для нашего случая
это будет имя ourcomponent.dcr. После внесения изменений в файлы .cpp и .h
можно приступать к установке нового компонента. Для этого необходимо выбрать
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
4
пункт главного меню Component | Install Component и в появившемся окне в поле
“Unit file name” указать имя .cpp файла, содержащего исходный код компонента. В
поле “Packege File Name” выбрать пакет, в который будет помещен компонент. По
умолчанию пользовательские компоненты помещаются в пакет “Borland User
Components”. После нажатия кнопки “Ok” необходимо согласиться с
перекомпиляцией пакета и сохранить изменения в пакете. После этого новый
компонент появится в палитре компонентов той закладки, которая была указана
при регистрации компонента. Для удаления/добавления или перекомпиляции
модулей в пакетах можно также использовать пункт Component | Install Package. В
появившемся окне необходимо выбрать нужный пакет и нажать кнопку «Edit».
2. Определение свойств и событий компонента
В рассмотренном выше примере была создана всего лишь заготовка
компонента. В реальной ситуации программист должен реализовать некоторый
код, обеспечивающий функциональность нового компонента. Принцип работы с
новым компонентом ничем не отличается от обычной процедуры наследования
ООП. Таким образом, программист может определять новые компонентные
данные или функции, а также использовать наследуемые. Новым в среде
С++Builder является возможность использования свойств и событий. Как уже
отмечалось, свойства предоставляют дополнительный интерфейс для доступа к
защищенным данным класса. События позволяют определить реакцию на
изменение состояния компонента. Свойства и события могут быть определены в
одной из стандартных областей видимости класса (private, protected, public), в этом
случае их доступность определяется также как и для данных класса. Однако в
среде С++Builder введена еще одна директива для области видимости __published.
Если свойство или событие будет размещено в этой секции, то оно будет доступно
в инспекторе объектов на этапе проектирования. Для описания свойств и событий
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
5
используется ключевое слово __property. Описание свойств и событий в общем
случае выглядит следующим образом
__property <type> <id> { read = <data/function id>, write = <data/function id>}
Кроме атрибутов read и write для свойств можно устанавливать
дополнительные атрибуты, которые также называются спецификаторами свойств,
однако их рассмотрение выходит за рамки данного учебного пособия. <id>
определяет имя свойства и задается по стандартным правилам для
идентификаторов С++. Согласно нотации среды С++Builder имена событий
начинаются с букв “On”. Описание свойств и событий отличаются только типом
<type>. События должны иметь специальный тип «событие», указатель на
функцию, описанный с ключевым словом __closure. Видя такой тип, инспектор
объектов размещает события на закладке Events. Свойства могут иметь любой
стандартный или производный тип, доступный для переменных. При
использовании классов VCL необходимо использовать тип указатель на класс,
поскольку статические экземпляры классов VCL не допустимы. Кроме того, в этом
случае необходимо создать экземпляр класса в конструкторе и уничтожить его в
деструкторе. Присваивание переменных, содержащих указатели на класс,
необходимо осуществлять с помощью метода Assign. Свойства на самом деле не
хранят никаких данных и являются как бы интерфейсом для доступа к внутренним
данным компонента. Где на самом деле будут храниться данные, и как будет
происходить доступ к ним, определяется с помощью спецификаторов read и write.
И read, и write могут указывать и на метод, и на переменную (обычно объявленную
в private секции класса). Чаще всего write указывает на функцию, а read просто на
переменную. В самой функции также происходит запись значения в переменную,
однако использование функции позволяет реализовать дополнительные
возможности, например, проверку допустимых значений при записи в свойство
или изменение значения других свойств и переменных в зависимости от данного.
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
6
Имя свойства может не иметь ничего общего с именем переменной, которую оно
модифицирует. Однако согласно нотации среды С++Builder имя связанной со
свойством должно быть таким же, как и имя свойства, но с префиксом F. Если write
отсутствует, то свойство будет только для чтения (но значение переменной, на
которую оно указывает, может быть изменено какими-либо другими способами,
например из других методов класса). Как уже отмечалось, события позволяют
определить пользователю компонента собственный обработчик событий.
Обработчик события представляет собой обычную функцию класса (обычно
принадлежащую классу формы), в которую передается указатель на объект,
который сгенерировал события и некоторые дополнительные данные,
специфичные для каждого типа события. Если произошло какое-либо событие, то
компонент просто вызывает назначенный этому событию обработчик, таким
образом позволяя пользователю компонента выполнить необходимые действия при
возникновении этого события. Рассмотрим пример определения свойств и
событий.
Заголовочный .h файл
class PACKAGE TOurComponent : public TComponent
{private:
int FMyInteger; char FMyChar;
Graphics::TFont *FMyFont;
TNotifyEvent FOnMyError;
void __fastcall SetMyInteger(const int Value);
__published:
__property int MyInteger = {read=FMyInteger, write=SetMyInteger};
__property char MyChar = {read=FMyChar, write=FMyChar};
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
7
__property Graphics::TFont* MyFont = {read=FMyFont, write=SetMyFont};
__property TNotifyEvent OnMyError = {read=FOnMyError, write=FOnMyError};}
Исходный .cpp файл
__fastcall TOurComponent::TOurComponent(TComponent* Owner)
: TComponent(Owner)
{FMyInteger=10;FMyChar='s';
FMyFont= new Graphics::TFont();}
__fastcall TOurComponent::~TOurComponent()
{delete FMyFont;}
void __fastcall TOurComponent::SetMyFont(const Graphics::TFont *Value)
{ FMyFont->Assign((TPersistent*)Value); }
void __fastcall TOurComponent::SetMyInteger(const int Value)
{if (Value%2) FMyInteger = Value;
else if (!ComponentState.Contains(csDesigning))
if (FOnMyError) FOnMyError (this);}
В данном примере определяется три свойства: MyChar, MyFont и MyInteger.
Свойство MyChar обеспечивает доступ к защищенной переменной FMyChar без
каких-либо дополнительных возможностей. Свойство MyFont обеспечивает доступ
к защищенной переменной FMyFont, являющейся указателем на класс типа TFont.
Еще раз отметим, что в этом случае объект должен быть создан в конструкторе и
уничтожен в деструкторе. Кроме того, как видно из функции SetMyFont, значение
переменной FMyFont присваивается с помощью метода Assign. Данный метод
обеспечит корректное копирование всех внутренних данных и свойств класса
TFont. При выполнении же присваивания вида FMyFont=Value произойдет
Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки
программирования»
8
присваивание указателей. В результате мы потерям доступ к блоку памяти,
выделенному ранее под FMyFont, и при удалении объекта Value, указатель
FMyFont станет некорректным. Свойство MyInteger обеспечивает доступ к
защищенной переменной FMyInteger. При чтении значения свойства происходит
просто чтение этой переменной, при записи же происходит проверка: для записи в
переменную доступны лишь четные значения. При попытке же записи нечетного
значения будет сгенерировано событие FOnMyError, причем генерация события
происходит, только если компонент находится на этапе выполнения, а не на этапе
проектирования. Для проверки на каком этапе находится компонент, можно
использовать свойство ComponentState: если это свойство содержит флаг
csDesigning, то компонент находится на этапе проектирования. Далее происходит
проверка, назначил ли программист, использующий наш компонент, обработчик
события OnMyError. Поскольку переменная FOnMyError содержит адрес функции
обработчика, то, если программист не назначил обработчик, в ней будет
содержаться значение NULL. В противном случае происходит вызов назначенной
функции обработчика, при этом в качестве параметра передается указатель this, т.е.
указатель на текущий экземпляр класса, для которого была вызвана функция
SetMyInteger. В обработчике этот параметр будет доступен как указатель Sender,
что позволит программисту определить в обработчике, какой именно экземпляр
класса вызвал данное событие.
Вывод
Среда С++Builder предоставляет удобные средства для создания
пользовательских компонент. Работа с созданными компонентами ничем не
отличается от работы со стандартными, и они позволяют существенно расширить
функциональность среды С++Builder.

More Related Content

What's hot

Лекция #3. Введение в языки разметки web-страниц
Лекция #3. Введение в языки разметки web-страницЛекция #3. Введение в языки разметки web-страниц
Лекция #3. Введение в языки разметки web-страницЯковенко Кирилл
 
Candidates for-php-developers-tests
Candidates for-php-developers-testsCandidates for-php-developers-tests
Candidates for-php-developers-testsguest5fa21c
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7Technopark
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.Igor Shkulipa
 
C++ осень 2013 лекция 3
C++ осень 2013 лекция 3C++ осень 2013 лекция 3
C++ осень 2013 лекция 3Technopark
 
C++ осень 2013 лекция 2
C++ осень 2013 лекция 2C++ осень 2013 лекция 2
C++ осень 2013 лекция 2Technopark
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansmetaform
 
C++ осень 2013 лекция 9
C++ осень 2013 лекция 9C++ осень 2013 лекция 9
C++ осень 2013 лекция 9Technopark
 
Trening modul2-webinar11
Trening modul2-webinar11Trening modul2-webinar11
Trening modul2-webinar11olgaoov
 
C++ STL & Qt. Занятие 07.
C++ STL & Qt. Занятие 07.C++ STL & Qt. Занятие 07.
C++ STL & Qt. Занятие 07.Igor Shkulipa
 
C++ осень 2013 лекция 1
C++ осень 2013 лекция 1C++ осень 2013 лекция 1
C++ осень 2013 лекция 1Technopark
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.Igor Shkulipa
 
подпрограммы в языке программирования паскаль
подпрограммы в языке программирования паскальподпрограммы в языке программирования паскаль
подпрограммы в языке программирования паскальArtem German
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.Igor Shkulipa
 
Ігор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerІгор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerLEDC 2016
 
Работа с БД в Java
Работа с БД в JavaРабота с БД в Java
Работа с БД в Javametaform
 

What's hot (20)

Лекция #3. Введение в языки разметки web-страниц
Лекция #3. Введение в языки разметки web-страницЛекция #3. Введение в языки разметки web-страниц
Лекция #3. Введение в языки разметки web-страниц
 
лекция 3
лекция 3лекция 3
лекция 3
 
Drupal Migrate
Drupal MigrateDrupal Migrate
Drupal Migrate
 
лек13 6
лек13 6лек13 6
лек13 6
 
Candidates for-php-developers-tests
Candidates for-php-developers-testsCandidates for-php-developers-tests
Candidates for-php-developers-tests
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
 
лек11 2
лек11 2лек11 2
лек11 2
 
C++ осень 2013 лекция 3
C++ осень 2013 лекция 3C++ осень 2013 лекция 3
C++ осень 2013 лекция 3
 
C++ осень 2013 лекция 2
C++ осень 2013 лекция 2C++ осень 2013 лекция 2
C++ осень 2013 лекция 2
 
Глава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeansГлава 2: Среда разработки NetBeans
Глава 2: Среда разработки NetBeans
 
C++ осень 2013 лекция 9
C++ осень 2013 лекция 9C++ осень 2013 лекция 9
C++ осень 2013 лекция 9
 
Trening modul2-webinar11
Trening modul2-webinar11Trening modul2-webinar11
Trening modul2-webinar11
 
C++ STL & Qt. Занятие 07.
C++ STL & Qt. Занятие 07.C++ STL & Qt. Занятие 07.
C++ STL & Qt. Занятие 07.
 
C++ осень 2013 лекция 1
C++ осень 2013 лекция 1C++ осень 2013 лекция 1
C++ осень 2013 лекция 1
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.
 
подпрограммы в языке программирования паскаль
подпрограммы в языке программирования паскальподпрограммы в языке программирования паскаль
подпрограммы в языке программирования паскаль
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.
 
Ігор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerІгор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developer
 
Работа с БД в Java
Работа с БД в JavaРабота с БД в Java
Работа с БД в Java
 

Similar to лек13 3

C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Javametaform
 
Drupal организация разработки
Drupal   организация разработкиDrupal   организация разработки
Drupal организация разработкиAnna Fedoruk
 
Drupal -organizaciya_razrabotki
Drupal  -organizaciya_razrabotkiDrupal  -organizaciya_razrabotki
Drupal -organizaciya_razrabotkidrupalconf
 
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...Декларативное программирование клиент-серверных приложений на андроид - UA Mo...
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...UA Mobile
 
C++ осень 2012 лекция 6
C++ осень 2012 лекция 6C++ осень 2012 лекция 6
C++ осень 2012 лекция 6Technopark
 
C++ весна 2014 лекция 5
C++ весна 2014 лекция 5C++ весна 2014 лекция 5
C++ весна 2014 лекция 5Technopark
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Javametaform
 
Selenium RC + python: история одного проекта
Selenium RC + python: история одного проектаSelenium RC + python: история одного проекта
Selenium RC + python: история одного проектаKonstantin Prishchenko
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.Igor Shkulipa
 
массивы Php
массивы Phpмассивы Php
массивы PhpVasya Petrov
 
Разработка модуля для Cms Drupal
Разработка модуля для Cms DrupalРазработка модуля для Cms Drupal
Разработка модуля для Cms DrupalDrupal Camp Kyiv
 
разработка модуля для Cms Drupal
разработка модуля для Cms Drupalразработка модуля для Cms Drupal
разработка модуля для Cms DrupalInna Tuyeva
 

Similar to лек13 3 (20)

лек11 3
лек11 3лек11 3
лек11 3
 
C++ теория
C++ теорияC++ теория
C++ теория
 
C++ теория
C++ теорияC++ теория
C++ теория
 
C++ теория
C++ теорияC++ теория
C++ теория
 
лек11 4
лек11 4лек11 4
лек11 4
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 
Drupal организация разработки
Drupal   организация разработкиDrupal   организация разработки
Drupal организация разработки
 
Drupal -organizaciya_razrabotki
Drupal  -organizaciya_razrabotkiDrupal  -organizaciya_razrabotki
Drupal -organizaciya_razrabotki
 
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...Декларативное программирование клиент-серверных приложений на андроид - UA Mo...
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...
 
лек11 5
лек11 5лек11 5
лек11 5
 
лек11 5
лек11 5лек11 5
лек11 5
 
C++ осень 2012 лекция 6
C++ осень 2012 лекция 6C++ осень 2012 лекция 6
C++ осень 2012 лекция 6
 
C++ весна 2014 лекция 5
C++ весна 2014 лекция 5C++ весна 2014 лекция 5
C++ весна 2014 лекция 5
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 
Selenium RC + python: история одного проекта
Selenium RC + python: история одного проектаSelenium RC + python: история одного проекта
Selenium RC + python: история одного проекта
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
 
массивы Php
массивы Phpмассивы Php
массивы Php
 
Разработка модуля для Cms Drupal
Разработка модуля для Cms DrupalРазработка модуля для Cms Drupal
Разработка модуля для Cms Drupal
 
разработка модуля для Cms Drupal
разработка модуля для Cms Drupalразработка модуля для Cms Drupal
разработка модуля для Cms Drupal
 
Lecture 11 2
Lecture 11 2Lecture 11 2
Lecture 11 2
 

More from Anastasia Snegina

птп по ппп 2013 2014
птп по ппп 2013 2014 птп по ппп 2013 2014
птп по ппп 2013 2014 Anastasia Snegina
 
прикл.прогр птп 13 14
прикл.прогр птп 13 14прикл.прогр птп 13 14
прикл.прогр птп 13 14Anastasia Snegina
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошинаAnastasia Snegina
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошинаAnastasia Snegina
 
рп по у пп практике в
рп по у пп практике врп по у пп практике в
рп по у пп практике вAnastasia Snegina
 
рп по пр практике в
рп по пр практике врп по пр практике в
рп по пр практике вAnastasia Snegina
 
рп по у сп практике в
рп по у сп практике врп по у сп практике в
рп по у сп практике вAnastasia Snegina
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике втAnastasia Snegina
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике втAnastasia Snegina
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике втAnastasia Snegina
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике втAnastasia Snegina
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике втAnastasia Snegina
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике втAnastasia Snegina
 

More from Anastasia Snegina (20)

птп по ппп 2013 2014
птп по ппп 2013 2014 птп по ппп 2013 2014
птп по ппп 2013 2014
 
прикл.прогр птп 13 14
прикл.прогр птп 13 14прикл.прогр птп 13 14
прикл.прогр птп 13 14
 
я.прогр птп
я.прогр птпя.прогр птп
я.прогр птп
 
пп кос вт
пп кос втпп кос вт
пп кос вт
 
пп кос в
пп кос впп кос в
пп кос в
 
пп кос в
пп кос впп кос в
пп кос в
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошина
 
2012 2013 пм спп провидошина
2012 2013  пм спп провидошина2012 2013  пм спп провидошина
2012 2013 пм спп провидошина
 
пп кос вт
пп кос втпп кос вт
пп кос вт
 
рп по у пп практике в
рп по у пп практике врп по у пп практике в
рп по у пп практике в
 
рп по пр практике в
рп по пр практике врп по пр практике в
рп по пр практике в
 
рп по у сп практике в
рп по у сп практике врп по у сп практике в
рп по у сп практике в
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике вт
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике вт
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике вт
 
рп по у пп практике вт
рп по у пп практике втрп по у пп практике вт
рп по у пп практике вт
 
рп по пр практике вт
рп по пр практике втрп по пр практике вт
рп по пр практике вт
 
рп по у сп практике вт
рп по у сп практике втрп по у сп практике вт
рп по у сп практике вт
 
лр18
лр18лр18
лр18
 
лр15
лр15лр15
лр15
 

лек13 3

  • 1. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 1 Лекция 13-3 Разработка компонент в C++Builder Как уже было отмечено, среда С++Builder содержит большое количество стандартных компонент, позволяющих упростить разработку приложений. Программисты могут расширять функциональность системы благодаря возможности создания собственных пользовательских компонент. Созданные компоненты могут быть помещены в палитру компонент, для них могут быть созданы редактор компонента, редакторы свойств, а также файл помощи. Таким образом, дальнейшая работа с созданным компонентом ничем не отличается от работы со стандартными компонентами. Созданные компоненты могут быть объединены в пакеты для упрощения их установки. Существует большое количество коммерческих и свободно распространяемых дополнительных пакетов компонент. Кроме того, программисты могут сами создавать компоненты для упрощения дальнейшей разработки приложений. Рассмотрим процесс создания компонент более подробно. 1. Процедура разработки компонента C++Builder При разработке нового компонента необходимо наследовать его от какого- либо стандартного класса в соответствии с принципами наследования ООП. Как уже было отмечено, все компоненты должны быть наследованы как минимум от класса TComponent. Процедура создания и установки компонентов в среде С++Builder автоматизирована. Для автоматической генерации заготовки нового компонента можно выбрать пункт главного меню Component | New Component. Далее в появившемся окне список выбора “Ancestor Type” позволяет выбрать имя класса, от которого будет наследован компонент. В поле “Class Name” указывается
  • 2. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 2 имя будущего класса. В соответствии с нотацией, принятой в среде С++Builder, имена классов должны начинаться с заглавной буквы “T”. В поле “Palette Page” указывается закладка, на которой будет располагаться компонент. В поле “Unit file name” указывается полный путь и имя файла, который будет содержать новый класс. После нажатия на кнопку “ОК” по указанному пути будет сгенерировано два файла c расширениями *.cpp и *.h и именами, совпадающими с именем класса без начальной буквы “T”. Кроме того, будет отображено окно редактирования этих файлов. В самих файлах уже будет содержаться код для определения класса и инсталляции компонента. Программист должен добавить в этот код все необходимые функциональные возможности нового компонента. Допустим, мы выбрали в поле “Ancestor Type” класс TComponent, в поле “Class Name” – TOurComponent, в поле “Palette Page” – OurSample, тогда будет сгенерирован файл OurComponent.h #ifndef OurComponentH #define OurComponentH #include <SysUtils.hpp> #include <Classes.hpp> class PACKAGE TOurComponent : public TComponent {private: protected: public: __fastcall TOurComponent(TComponent* Owner); __published:}; #endif Вместе с заголовочным файлом будет создан файл OurComponent.cpp #include <basepch.h> #pragma hdrstop #include "OurComponent.h" #pragma package(smart_init) static inline void ValidCtrCheck(TOurComponent *)
  • 3. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 3 { new TOurComponent(NULL); } __fastcall TOurComponent::TOurComponent(TComponent* Owner) : TComponent(Owner){ } namespace Ourcomponent { void __fastcall PACKAGE Register() {TComponentClass classes[1] = {__classid(TOurComponent)}; RegisterComponents("OurSamples", classes, 0);}} Как видно из приведенного примера создается заготовка для конструктора, а также определяются две функции ValidCtrCheck и Register. Функция ValidCtrCheck необходима для проверки наличия в создаваемом компоненте чистых виртуальных функций. Данная функция будет вызвана при установке компонента. В ней просто производится попытка создания экземпляра компонента, что в случае наличия чистой виртуальной функции приведет к генерации ошибки и отмене инсталляции. Функция Register регистрирует компонент в палитре компонентов. В первом параметре указывается имя закладки в палитре компонент, второй - параметр- массив указателей на метаклассы регистрируемых компонент, третий содержит количество регистрируемых компонентов минус 1. Для компонента может быть создана пиктограмма, которая будет отображаться в палитре компонентов. Для этого необходимо использовать Image Editor из пункта главного меню Tools. В этом редакторе необходимо выбрать пункт File | New | Component Resource File (.dcr), а затем пункт Resource | New | Bitmap и задать размер 24х24 пиксела. Необходимо переименовать созданный Bitmap, назвав его так же, как и будущий класс компонента, но заглавными буквами. Для нашего случая это будет имя TOURCOMPONENT. Далее можно нарисовать необходимый рисунок, учитывая, что цвет левого нижнего квадрата будет считаться прозрачным. Сам файл ресурса необходимо сохранить в том же каталоге, что и файлы .cpp и .h, с тем же именем, но с расширением .dcr. Для нашего случая это будет имя ourcomponent.dcr. После внесения изменений в файлы .cpp и .h можно приступать к установке нового компонента. Для этого необходимо выбрать
  • 4. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 4 пункт главного меню Component | Install Component и в появившемся окне в поле “Unit file name” указать имя .cpp файла, содержащего исходный код компонента. В поле “Packege File Name” выбрать пакет, в который будет помещен компонент. По умолчанию пользовательские компоненты помещаются в пакет “Borland User Components”. После нажатия кнопки “Ok” необходимо согласиться с перекомпиляцией пакета и сохранить изменения в пакете. После этого новый компонент появится в палитре компонентов той закладки, которая была указана при регистрации компонента. Для удаления/добавления или перекомпиляции модулей в пакетах можно также использовать пункт Component | Install Package. В появившемся окне необходимо выбрать нужный пакет и нажать кнопку «Edit». 2. Определение свойств и событий компонента В рассмотренном выше примере была создана всего лишь заготовка компонента. В реальной ситуации программист должен реализовать некоторый код, обеспечивающий функциональность нового компонента. Принцип работы с новым компонентом ничем не отличается от обычной процедуры наследования ООП. Таким образом, программист может определять новые компонентные данные или функции, а также использовать наследуемые. Новым в среде С++Builder является возможность использования свойств и событий. Как уже отмечалось, свойства предоставляют дополнительный интерфейс для доступа к защищенным данным класса. События позволяют определить реакцию на изменение состояния компонента. Свойства и события могут быть определены в одной из стандартных областей видимости класса (private, protected, public), в этом случае их доступность определяется также как и для данных класса. Однако в среде С++Builder введена еще одна директива для области видимости __published. Если свойство или событие будет размещено в этой секции, то оно будет доступно в инспекторе объектов на этапе проектирования. Для описания свойств и событий
  • 5. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 5 используется ключевое слово __property. Описание свойств и событий в общем случае выглядит следующим образом __property <type> <id> { read = <data/function id>, write = <data/function id>} Кроме атрибутов read и write для свойств можно устанавливать дополнительные атрибуты, которые также называются спецификаторами свойств, однако их рассмотрение выходит за рамки данного учебного пособия. <id> определяет имя свойства и задается по стандартным правилам для идентификаторов С++. Согласно нотации среды С++Builder имена событий начинаются с букв “On”. Описание свойств и событий отличаются только типом <type>. События должны иметь специальный тип «событие», указатель на функцию, описанный с ключевым словом __closure. Видя такой тип, инспектор объектов размещает события на закладке Events. Свойства могут иметь любой стандартный или производный тип, доступный для переменных. При использовании классов VCL необходимо использовать тип указатель на класс, поскольку статические экземпляры классов VCL не допустимы. Кроме того, в этом случае необходимо создать экземпляр класса в конструкторе и уничтожить его в деструкторе. Присваивание переменных, содержащих указатели на класс, необходимо осуществлять с помощью метода Assign. Свойства на самом деле не хранят никаких данных и являются как бы интерфейсом для доступа к внутренним данным компонента. Где на самом деле будут храниться данные, и как будет происходить доступ к ним, определяется с помощью спецификаторов read и write. И read, и write могут указывать и на метод, и на переменную (обычно объявленную в private секции класса). Чаще всего write указывает на функцию, а read просто на переменную. В самой функции также происходит запись значения в переменную, однако использование функции позволяет реализовать дополнительные возможности, например, проверку допустимых значений при записи в свойство или изменение значения других свойств и переменных в зависимости от данного.
  • 6. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 6 Имя свойства может не иметь ничего общего с именем переменной, которую оно модифицирует. Однако согласно нотации среды С++Builder имя связанной со свойством должно быть таким же, как и имя свойства, но с префиксом F. Если write отсутствует, то свойство будет только для чтения (но значение переменной, на которую оно указывает, может быть изменено какими-либо другими способами, например из других методов класса). Как уже отмечалось, события позволяют определить пользователю компонента собственный обработчик событий. Обработчик события представляет собой обычную функцию класса (обычно принадлежащую классу формы), в которую передается указатель на объект, который сгенерировал события и некоторые дополнительные данные, специфичные для каждого типа события. Если произошло какое-либо событие, то компонент просто вызывает назначенный этому событию обработчик, таким образом позволяя пользователю компонента выполнить необходимые действия при возникновении этого события. Рассмотрим пример определения свойств и событий. Заголовочный .h файл class PACKAGE TOurComponent : public TComponent {private: int FMyInteger; char FMyChar; Graphics::TFont *FMyFont; TNotifyEvent FOnMyError; void __fastcall SetMyInteger(const int Value); __published: __property int MyInteger = {read=FMyInteger, write=SetMyInteger}; __property char MyChar = {read=FMyChar, write=FMyChar};
  • 7. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 7 __property Graphics::TFont* MyFont = {read=FMyFont, write=SetMyFont}; __property TNotifyEvent OnMyError = {read=FOnMyError, write=FOnMyError};} Исходный .cpp файл __fastcall TOurComponent::TOurComponent(TComponent* Owner) : TComponent(Owner) {FMyInteger=10;FMyChar='s'; FMyFont= new Graphics::TFont();} __fastcall TOurComponent::~TOurComponent() {delete FMyFont;} void __fastcall TOurComponent::SetMyFont(const Graphics::TFont *Value) { FMyFont->Assign((TPersistent*)Value); } void __fastcall TOurComponent::SetMyInteger(const int Value) {if (Value%2) FMyInteger = Value; else if (!ComponentState.Contains(csDesigning)) if (FOnMyError) FOnMyError (this);} В данном примере определяется три свойства: MyChar, MyFont и MyInteger. Свойство MyChar обеспечивает доступ к защищенной переменной FMyChar без каких-либо дополнительных возможностей. Свойство MyFont обеспечивает доступ к защищенной переменной FMyFont, являющейся указателем на класс типа TFont. Еще раз отметим, что в этом случае объект должен быть создан в конструкторе и уничтожен в деструкторе. Кроме того, как видно из функции SetMyFont, значение переменной FMyFont присваивается с помощью метода Assign. Данный метод обеспечит корректное копирование всех внутренних данных и свойств класса TFont. При выполнении же присваивания вида FMyFont=Value произойдет
  • 8. Лекция №13-3 для дисциплин: «Прикладное программирование» и «Языки программирования» 8 присваивание указателей. В результате мы потерям доступ к блоку памяти, выделенному ранее под FMyFont, и при удалении объекта Value, указатель FMyFont станет некорректным. Свойство MyInteger обеспечивает доступ к защищенной переменной FMyInteger. При чтении значения свойства происходит просто чтение этой переменной, при записи же происходит проверка: для записи в переменную доступны лишь четные значения. При попытке же записи нечетного значения будет сгенерировано событие FOnMyError, причем генерация события происходит, только если компонент находится на этапе выполнения, а не на этапе проектирования. Для проверки на каком этапе находится компонент, можно использовать свойство ComponentState: если это свойство содержит флаг csDesigning, то компонент находится на этапе проектирования. Далее происходит проверка, назначил ли программист, использующий наш компонент, обработчик события OnMyError. Поскольку переменная FOnMyError содержит адрес функции обработчика, то, если программист не назначил обработчик, в ней будет содержаться значение NULL. В противном случае происходит вызов назначенной функции обработчика, при этом в качестве параметра передается указатель this, т.е. указатель на текущий экземпляр класса, для которого была вызвана функция SetMyInteger. В обработчике этот параметр будет доступен как указатель Sender, что позволит программисту определить в обработчике, какой именно экземпляр класса вызвал данное событие. Вывод Среда С++Builder предоставляет удобные средства для создания пользовательских компонент. Работа с созданными компонентами ничем не отличается от работы со стандартными, и они позволяют существенно расширить функциональность среды С++Builder.