Разработка своих компонентов
Возвращаясь к вопросу о разработке компонентов FR3 на BCB. Я нашел ответ на
свой вопрос о initialization/finalization: необходимо использовать директивы
компилятора #pragma startup и #pragma exit. Попытался реализовать класс
TfrxBitBtn на C++ в виде класса TMyButton. Результат: в дизайнере кнопка
появляется, ее можно поместить на форму, можно удалить. При выходе из программы
она падает с ошибкой "Access violation" по разным адресам, падает также и
BCB IDE. Подозреваю, что дело в деструкторе.
Система: BCB5, FR 3.11
Может кто подскажет, где ошибка?
/****************************************************************************
/*** Файл MyButton.h ***
/****************************************************************************
//
#ifndef MyButtonH
#define MyButtonH
//
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <StdCtrls.hpp>
#include "frxClass.hpp"
#include "frxDsgnIntf.hpp"
//
//class __declspec(delphiclass) PACKAGE TMyButton : public TfrxDialogControl
class PACKAGE TMyButton : public TfrxDialogControl
{
private:
TBitBtn *FBitBtn;
Graphics::TBitmap* __fastcall GetGlyph(void);
TBitBtnKind __fastcall GetKind(void);
TButtonLayout __fastcall GetLayout(void);
int __fastcall GetMargin(void);
TModalResult __fastcall GetModalResult(void);
int __fastcall GetSpacing(void);
void __fastcall SetGlyph(Graphics::TBitmap *Value);
void __fastcall SetKind(TBitBtnKind Value);
void __fastcall SetLayout(TButtonLayout Value);
void __fastcall SetMargin(int Value);
void __fastcall SetModalResult(TModalResult Value);
void __fastcall SetSpacing(int Value);
int __fastcall GetNumGlyphs(void);
void __fastcall SetNumGlyphs(int Value);
protected:
public:
__fastcall TMyButton(TComponent* Owner);
// __fastcall ~TMyButton();
AnsiString __fastcall GetDescription(void);
__property TBitBtn *BitBtn={read=FBitBtn};
__published:
__property Graphics::TBitmap* Glyph = {read=GetGlyph, write=SetGlyph};
__property Buttons::TBitBtnKind Kind = {read=GetKind, write=SetKind, default=0};
__property Caption;
__property Buttons::TButtonLayout Layout = {read=GetLayout, write=SetLayout, default=0};
__property int Margin = {read=GetMargin, write=SetMargin, default=-1};
__property Forms::TModalResult ModalResult = {read=GetModalResult, write=SetModalResult, default=0}
;
__property int NumGlyphs = {read=GetNumGlyphs, write=SetNumGlyphs, default=1};
__property int Spacing = {read=GetSpacing, write=SetSpacing, default=4};
__property OnClick ;
__property OnEnter ;
__property OnExit ;
__property OnKeyDown ;
__property OnKeyPress ;
__property OnKeyUp ;
__property OnMouseDown ;
__property OnMouseMove ;
__property OnMouseUp;
};
//
#endif
/****************************************************************************
/*** Файл MyButton.cpp ***
/****************************************************************************
//
#include <vcl.h>
#pragma hdrstop
#include "MyButton.h"
#pragma package(smart_init)
void TMyButton_Init(void);
void TMyButton_Final(void);
#pragma startup TMyButton_Init
#pragma exit TMyButton_Final
//
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
Graphics::TBitmap *Bmp=NULL;
void TMyButton_Init(void){
// ShowMessage("TMyButton инициализация старт");
Bmp=new Graphics::TBitmap();
try{
int h=(int)HInstance;
Bmp->LoadFromResourceName(h, "TArhRxLookupEdit");
}catch(Exception &E){
ShowMessage("Ошибка Bmp->LoadFromResourceName:\n"+E.Message);
}
try{
frxObjects->RegisterObject(__classid(TMyButton), Bmp,"Other controls");
}catch(Exception &E){
ShowMessage("Ошибка frxObjects->RegisterObject:\n"+E.Message);
}
// ShowMessage("TMyButton инициализация окончание");
}
void TMyButton_Final(void){
// ShowMessage("TMyButton финализация старт");
try{
frxObjects->Unregister(__classid(TMyButton));
}catch(Exception &E){
ShowMessage("Ошибка frxObjects->UnregisterObject:\n"+E.Message);
}
try{
if(Bmp) Bmp->Free();
}catch(Exception &E){
ShowMessage("Ошибка Bmp->Free:\n"+E.Message);
}
// ShowMessage("TMyButton финализация окончание");
}
static inline void ValidCtrCheck(TMyButton *)
{
new TMyButton(NULL);
}
//
namespace Mybutton
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TMyButton)};
RegisterComponents("FastReport 3.0", classes, 0);
}
}
//
//
__fastcall TMyButton::TMyButton(TComponent* Owner)
: TfrxDialogControl(Owner)
{
// ShowMessage("TMyButton конструктор старт.");
FBitBtn=new TBitBtn(Owner);
FBitBtn->Caption="BitBtn";
InitControl(FBitBtn);
Width=75;
Height=25;
}
// __fastcall TMyButton::~TMyButton(){
// ShowMessage("TMyButton деструктор старт.");
// }
AnsiString __fastcall TMyButton::GetDescription(){
static AnsiString R="Элемент управления TMyButton";
return R;
}
Graphics::TBitmap* __fastcall TMyButton::GetGlyph(void){
return FBitBtn->Glyph;
}
TBitBtnKind __fastcall TMyButton::GetKind(void){
return FBitBtn->Kind;
}
TButtonLayout __fastcall TMyButton::GetLayout(void){
return FBitBtn->Layout;
}
int __fastcall TMyButton::GetMargin(void){
return FBitBtn->Margin;
}
TModalResult __fastcall TMyButton::GetModalResult(void){
return FBitBtn->ModalResult;
}
int __fastcall TMyButton::GetNumGlyphs(void){
return FBitBtn->NumGlyphs;
}
int __fastcall TMyButton::GetSpacing(void){
return FBitBtn->Spacing;
}
//setter
void __fastcall TMyButton::SetGlyph(Graphics::TBitmap* Value){
FBitBtn->Glyph=Value;
}
void __fastcall TMyButton::SetKind(TBitBtnKind Value){
FBitBtn->Kind=Value;
}
void __fastcall TMyButton::SetLayout(TButtonLayout Value){
FBitBtn->Layout=Value;
}
void __fastcall TMyButton::SetMargin(int Value){
FBitBtn->Margin=Value;
}
void __fastcall TMyButton::SetModalResult(TModalResult Value){
FBitBtn->ModalResult=Value;
}
void __fastcall TMyButton::SetNumGlyphs(int Value){
FBitBtn->NumGlyphs=Value;
}
void __fastcall TMyButton::SetSpacing(int Value){
FBitBtn->Spacing=Value;
}
свой вопрос о initialization/finalization: необходимо использовать директивы
компилятора #pragma startup и #pragma exit. Попытался реализовать класс
TfrxBitBtn на C++ в виде класса TMyButton. Результат: в дизайнере кнопка
появляется, ее можно поместить на форму, можно удалить. При выходе из программы
она падает с ошибкой "Access violation" по разным адресам, падает также и
BCB IDE. Подозреваю, что дело в деструкторе.
Система: BCB5, FR 3.11
Может кто подскажет, где ошибка?
/****************************************************************************
/*** Файл MyButton.h ***
/****************************************************************************
//
#ifndef MyButtonH
#define MyButtonH
//
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <StdCtrls.hpp>
#include "frxClass.hpp"
#include "frxDsgnIntf.hpp"
//
//class __declspec(delphiclass) PACKAGE TMyButton : public TfrxDialogControl
class PACKAGE TMyButton : public TfrxDialogControl
{
private:
TBitBtn *FBitBtn;
Graphics::TBitmap* __fastcall GetGlyph(void);
TBitBtnKind __fastcall GetKind(void);
TButtonLayout __fastcall GetLayout(void);
int __fastcall GetMargin(void);
TModalResult __fastcall GetModalResult(void);
int __fastcall GetSpacing(void);
void __fastcall SetGlyph(Graphics::TBitmap *Value);
void __fastcall SetKind(TBitBtnKind Value);
void __fastcall SetLayout(TButtonLayout Value);
void __fastcall SetMargin(int Value);
void __fastcall SetModalResult(TModalResult Value);
void __fastcall SetSpacing(int Value);
int __fastcall GetNumGlyphs(void);
void __fastcall SetNumGlyphs(int Value);
protected:
public:
__fastcall TMyButton(TComponent* Owner);
// __fastcall ~TMyButton();
AnsiString __fastcall GetDescription(void);
__property TBitBtn *BitBtn={read=FBitBtn};
__published:
__property Graphics::TBitmap* Glyph = {read=GetGlyph, write=SetGlyph};
__property Buttons::TBitBtnKind Kind = {read=GetKind, write=SetKind, default=0};
__property Caption;
__property Buttons::TButtonLayout Layout = {read=GetLayout, write=SetLayout, default=0};
__property int Margin = {read=GetMargin, write=SetMargin, default=-1};
__property Forms::TModalResult ModalResult = {read=GetModalResult, write=SetModalResult, default=0}
;
__property int NumGlyphs = {read=GetNumGlyphs, write=SetNumGlyphs, default=1};
__property int Spacing = {read=GetSpacing, write=SetSpacing, default=4};
__property OnClick ;
__property OnEnter ;
__property OnExit ;
__property OnKeyDown ;
__property OnKeyPress ;
__property OnKeyUp ;
__property OnMouseDown ;
__property OnMouseMove ;
__property OnMouseUp;
};
//
#endif
/****************************************************************************
/*** Файл MyButton.cpp ***
/****************************************************************************
//
#include <vcl.h>
#pragma hdrstop
#include "MyButton.h"
#pragma package(smart_init)
void TMyButton_Init(void);
void TMyButton_Final(void);
#pragma startup TMyButton_Init
#pragma exit TMyButton_Final
//
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
Graphics::TBitmap *Bmp=NULL;
void TMyButton_Init(void){
// ShowMessage("TMyButton инициализация старт");
Bmp=new Graphics::TBitmap();
try{
int h=(int)HInstance;
Bmp->LoadFromResourceName(h, "TArhRxLookupEdit");
}catch(Exception &E){
ShowMessage("Ошибка Bmp->LoadFromResourceName:\n"+E.Message);
}
try{
frxObjects->RegisterObject(__classid(TMyButton), Bmp,"Other controls");
}catch(Exception &E){
ShowMessage("Ошибка frxObjects->RegisterObject:\n"+E.Message);
}
// ShowMessage("TMyButton инициализация окончание");
}
void TMyButton_Final(void){
// ShowMessage("TMyButton финализация старт");
try{
frxObjects->Unregister(__classid(TMyButton));
}catch(Exception &E){
ShowMessage("Ошибка frxObjects->UnregisterObject:\n"+E.Message);
}
try{
if(Bmp) Bmp->Free();
}catch(Exception &E){
ShowMessage("Ошибка Bmp->Free:\n"+E.Message);
}
// ShowMessage("TMyButton финализация окончание");
}
static inline void ValidCtrCheck(TMyButton *)
{
new TMyButton(NULL);
}
//
namespace Mybutton
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TMyButton)};
RegisterComponents("FastReport 3.0", classes, 0);
}
}
//
//
__fastcall TMyButton::TMyButton(TComponent* Owner)
: TfrxDialogControl(Owner)
{
// ShowMessage("TMyButton конструктор старт.");
FBitBtn=new TBitBtn(Owner);
FBitBtn->Caption="BitBtn";
InitControl(FBitBtn);
Width=75;
Height=25;
}
// __fastcall TMyButton::~TMyButton(){
// ShowMessage("TMyButton деструктор старт.");
// }
AnsiString __fastcall TMyButton::GetDescription(){
static AnsiString R="Элемент управления TMyButton";
return R;
}
Graphics::TBitmap* __fastcall TMyButton::GetGlyph(void){
return FBitBtn->Glyph;
}
TBitBtnKind __fastcall TMyButton::GetKind(void){
return FBitBtn->Kind;
}
TButtonLayout __fastcall TMyButton::GetLayout(void){
return FBitBtn->Layout;
}
int __fastcall TMyButton::GetMargin(void){
return FBitBtn->Margin;
}
TModalResult __fastcall TMyButton::GetModalResult(void){
return FBitBtn->ModalResult;
}
int __fastcall TMyButton::GetNumGlyphs(void){
return FBitBtn->NumGlyphs;
}
int __fastcall TMyButton::GetSpacing(void){
return FBitBtn->Spacing;
}
//setter
void __fastcall TMyButton::SetGlyph(Graphics::TBitmap* Value){
FBitBtn->Glyph=Value;
}
void __fastcall TMyButton::SetKind(TBitBtnKind Value){
FBitBtn->Kind=Value;
}
void __fastcall TMyButton::SetLayout(TButtonLayout Value){
FBitBtn->Layout=Value;
}
void __fastcall TMyButton::SetMargin(int Value){
FBitBtn->Margin=Value;
}
void __fastcall TMyButton::SetModalResult(TModalResult Value){
FBitBtn->ModalResult=Value;
}
void __fastcall TMyButton::SetNumGlyphs(int Value){
FBitBtn->NumGlyphs=Value;
}
void __fastcall TMyButton::SetSpacing(int Value){
FBitBtn->Spacing=Value;
}