Переопределение метода CreateWnd().
При работе компоненты необходимо динамически создать экземпляры классов TMarshrut и ТShar. Хотелось бы сделать это непосредственно в конструкторе класса TOsnova, но попытка запуска окончится генерированием исключения времени выполнения: Control has no parent window (Управляющий элемент не имеет родительского окна). Решение состоит в переопределении метода CreateWnd(). //--------------------------------------------------------------------------- void __fastcall TOsnova::CreateWnd() { if (ComponentState.Contains(csDestroying)) return; //если компонента разрушается - выход TCustomControl::CreateWnd(); //базовый метод
Marshrut=new TMarshrut(this); //создаём экземпляр класса Marshrut->Parent=this; Marshrut->Width=this->Width; Marshrut->Height=this->Height; Shar=new TShar(this); //создаём экземпляр класса Shar->Parent=this; Shar->Width=(D-d)/2; Shar->Height=(D-d)/2; Shar->Left=(this->Width-D)/2+D-Shar->Width; Shar->Top=this->Height/2-Shar->Height/2;
if (ComponentState.Contains(csDesigning)) return; //если компонента разрабатывается - выход else; //иначе запускаем таймер SetTimer(Handle, 1, FSkorosty, 0); } //--------------------------------------------------------------------------- Сначала вызывается функция CreateWnd() базового класса, которая вернёт дескриптор окна. После этого мы можем создать экземпляры наших классов, а также функцией SetTimer() создать таймер.
Переопределение метода Paint()
//--------------------------------------------------------------------------- void __fastcall TOsnova::Paint() { this->Canvas->Brush->Color=clSkyBlue; this->Canvas->Font->Size=this->Height/20; this->Canvas->TextOutA(this->Width/4,3,"Моя компонента"); } //--------------------------------------------------------------------------- С помощью метода Paint() выведем текст на компоненту.
7 Переопределение метода WndProc(TMessage& Message) Каждый компонент, имеющий свой собственный дескриптор окна, имеет и виртуальный метод по имени WndProc(). Этот метод вызывается каждый раз, когда Windows или VCL посылает сообщение окну компонента.
Прежде чем начать описание применения метода WndProc(), сосредоточимся на использовании таймера в компоненте. Таймер запускается в методе CreateWnd(): SetTimer (Handle, 1, FSkorosty, 0). В эту функцию в качестве параметров передаются дескриптор окна компонента, 1 - как идентификатор таймера, FSkorosty - как интервал таймера) и 0 в качестве значения последнего параметра, который используется только в случае, если вы применяете функцию обратного вызова таймера. В этом примере сообщается, что Windows следует посылать сообщение WM_TIMER моей оконной процедуре окна. Удаление таймера осуществляется в деструкторе компоненты: KillTimer (Handle, 1); Внутри этого метода выполняется соответствующая обработка сообщения WM_TIMER: //--------------------------------------------------------------------------- void __fastcall TOsnova::WndProc(TMessage& Message) { TCustomControl::WndProc(Message); //базовый метод if (Message.Msg == WM_TIMER) { //проверяем, изменились ли размеры if ((N==true)&&(this->Width!=NewWidth)&&(this->Height!=NewHeight)) { this->Width=NewWidth; this->Height=NewHeight; D=this->Width/5*4; d=this->Width/5*3;
Marshrut->Width=this->Width; Marshrut->Height=this->Height Shar->Width=(D-d)/2; Shar->Height=(D-d)/2; Shar->Left=(this->Width-D)/2+D-Shar->Width; Shar->Top=this->Height/2-Shar->Height/2;
this->Canvas->Font->Size=this->Height/20; this->Canvas->TextOutA(this->Width/4,3,"Моя компонента"); this->Invalidate();//перерисовываем компоненту N=false;//больше сюда не заходим }
a+=0.2;//увеличиваем значение угла поворота (процесс движения) Shar->Left=(Marshrut->Width-(D-(D-d)/2))/2+(D-(D-d)/2)/2+(D-(D-d)/2)/2*cos(a)- Shar->Width/2; Shar->Top=(Marshrut->Height-(D-(D-d)/2))/2+(D-(D-d)/2)/2-(D-(D-d)/2)/2*sin(a)- Shar->Height/2; } } //--------------------------------------------------------------------------- Сначала вызывается метод базового класса TCustomControl::WndProc(Message), затем устанавливаются новые размеры (если они были изменены), вызывается функция Invalidate() для перерисовки компоненты, и присваиваются новые координаты шарику.
8 Переопределение метода CanResize(int &NewWidth, int &NewHeight).
Если пользователь изменит размеры компоненты в режиме разработки, пропорционально должны измениться размеры всех объектов, из которых состоит компонента.
//--------------------------------------------------------------------------- bool __fastcall TOsnova::CanResize(int &NewWidth, int &NewHeight) { //изменяем if (ComponentState.Contains(csDesigning)) { D=this->Width/5*4; // диаметры окружностей d=this->Width/5*3;
Marshrut->//размеры экз. класса ТMarshrut Marshrut->Height=this->Height;
Shar->//размеры экз. класса ТShar Shar->Height=(D-d)/2; Shar->Left=(this->Width-D)/2+D-Shar->Width; Shar->Top=this->Height/2-Shar->Height/2;
this->Canvas->Font->Size=this->Height/20; //размер шрифта this->Canvas->TextOutA(this->Width/4,3,"Моя компонента"); //координаты
this->Invalidate(); //перерисовываем компоненту } if (NewWidth!=NewHeight) NewWidth=NewHeight; return(NewWidth, NewHeight); } //--------------------------------------------------------------------------- Метод CanResize() возвращает новые значения ширины (NewWidth) и высоты (NewHeight), которые затем будут переданы методу WndProc(TMessage& Message), для того, чтобы компонента рисовалась в приложении с новыми размерами. Создание событий Наиболее простая форма события — это событие, просто уведомляющее о том, что оно произошло. Например, событие OnClick, которое присутствует в большинстве визуальных компонентов, имеет только один параметр — Sender: void fastcall TForml::FormClick(TObject *Sender). Этот тип события определяется в VCL как TNotifyEvent. При создании события, обеспечивающего простое уведомление, можно воспользоваться типом события TNotifyEvent. OnMyClick, событие TOsnova — простое событие уведомления. Оно объявляется следующим образом: __property TNotifyEvent OnMyClick = {read=FOnMyClick, write=FOnMyClick}; Каждое событие должно иметь виртуальный метод, который используется внутри компоненты, чтобы сообщить ей о своем возникновении. Такие методы объявляются виртуальными (чтобы классы-наследники могли получить к ним доступ) и в защищенном разделе. Виртуальный метод, сообщающий о возникновении события OnMyClick, называется DoOnMyClick(): //--------------------------------------------------------------------------- void __fastcall TOsnova::DoOnMyClick() { if (FOnMyClick) FOnMyClick(this); } //--------------------------------------------------------------------------- Сначала проверяется, был ли событию назначен обработчик. Если обработчик события был назначен, то вызывается функция, указатель на которую расположен в поле FOnMyClick, куда передается в качестве параметра указатель на компонент (this). Это событие будет отражено на вкладке Events в окне Инспектора Объектов.
При двойном клике Builder сгенерирует следующий код: //--------------------------------------------------------------------------- void __fastcall TForm1::Osnova1MyClick(TObject *Sender) { //код обработчика события } //--------------------------------------------------------------------------- Тестирование компоненты Для тестирования компоненты начнём новый проект (File®New®Application). Добавим к проекту (Project®Add to Project) файлы Osnova.cpp, Marshrut.cpp и Shar.cpp. В конструкторе формы создадим объект нашего класса //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { TOsnva *Osnova; Osnova=new TOsnova(this); Osnova->Parent=this; } //--------------------------------------------------------------------------- Теперь все изменения в компоненте мы сразу сможем увидеть при запуске этого проекта.
Регистрация компоненты Компонента регистрируется функцией Register(), которая автоматически генерируется C++ Builder. Ключевое слово namespace устанавливает локальность имён данной процедуры регистрации. После этого ключевого слова следует имя файла, содержащего компоненту. В процедуре регистрации Register первый оператор создаёт массив регистрируемых компонентов classes типа TComponentClass и заносит его в регистрируемую компоненту. Следующий оператор регистрирует функцией RegisterComponents компоненты, занесённые в classes (второй параметр функции) на странице Samples (второй параметр). //--------------------------------------------------------------------------- namespace Osnova { void __fastcall PACKAGE Register() { TComponentClass classes[1] = {__classid(TOsnova)}; RegisterComponents("Samples", classes, 0); } } //--------------------------------------------------------------------------- Инсталляция компоненты Для инсталляции компоненты выбираем меню Component, Install Component.
В появившемся окне выбираем вкладку Into new package (в новый пакет), вводим имя пакета (APPKOsnova) и нажимаем ОК. Появляется окошко с предложением инсталлировать пакет.
Отвечаем No, так как наш пакет полностью ещё не собран - в него не включены классы TMarshrut и ТShar. В окне Диспетчера Пакетов (Package Manager) выбираем Add, Add Unit и добавляем файлы Marshrut.cpp и Shar.cpp
После компиляции можно инсталлировать нашу компоненту. Деинсталлировать компоненту можно, выбрав вкладку Project -> Options ->Remove.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|