我按照bcb的帮助里面的那个例子,自己写了一个组件,是从TCustomGrid继承下来的,在我编译都没有问题,但在实际设计时,一把这个组件拖动到form上的时候,就报一个纯虚拟类,然后就提示什么内存访问错误,要调试,再就bcb的窗口就被自动关掉了,请各位把把脉,给点提示:
源代码:(基本上和帮助里面的例子一样)
.CPP#include <vcl.h>
#pragma hdrstop
#include "CALSAMP.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
///*
static inline void ValidCtrCheck(TSampleCalendar *)
{
new TSampleCalendar(NULL);
}static inline TSampleCalendar * ValidCtrCheck()
{
return new TSampleCalendar(NULL);
}
*/
namespace Calsamp
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TSampleCalendar)};
RegisterComponents("System", classes, 0);
}
}
//---------------------------------------------------------------------------__fastcall TSampleCalendar::TSampleCalendar(TComponent *Owner) : TCustomGrid(Owner)
{
ColCount = 7;
RowCount = 7;
FixedCols = 0;
FixedRows = 1;
ScrollBars = ssNone;
Options = (Options >> goRangeSelect) << goDrawFocusSelected; FDate = FDate.CurrentDate();
UpdateCalendar();
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::DrawCell(long ACol, long ARow, const Windows::TRect &ARect,TGridDrawState AState)
{
String TheText;
int TempDay;
if (ARow == 0) TheText = ShortDayNames[ACol + 1];
else
{
TheText = "";
TempDay = DayNum(ACol, ARow); // DayNum is defined later
if (TempDay != -1) TheText = IntToStr(TempDay);
}
Canvas->TextRect(ARect, ARect.Left + (ARect.Right - ARect.Left
- Canvas->TextWidth(TheText)) / 2,
ARect.Top + (ARect.Bottom - ARect.Top - Canvas->TextHeight(TheText)) / 2, TheText);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::WMSize(TWMSize &Message)
{
int GridLines; // temporary local variable
GridLines = 6 * GridLineWidth; // calculated combined size of all lines
DefaultColWidth = (Message.Width - GridLines) / 7; // set new default cell width
DefaultRowHeight = (Message.Height - GridLines) / 7; // and cell height
}void __fastcall TSampleCalendar::SetCalendarDate(TDateTime Value)
{
FDate = Value; // Set the new date value
//Refresh(); // Update the onscreen image
UpdateCalendar(); // this previously called Refresh
Change(); // this is the only new statement
}
//---------------------------------------------------------------------------int __fastcall TSampleCalendar::GetDateElement(int Index)
{
unsigned short AYear, AMonth, ADay;
int result;
FDate.DecodeDate(&AYear, &AMonth, &ADay); // break encoded date into elements
switch (Index)
{
case 1: result = AYear; break;
case 2: result = AMonth; break;
case 3: result = ADay; break;
default: result = -1;
}
return result;
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::SetDateElement(int Index, int Value)
{
unsigned short AYear, AMonth, ADay;
if (Value > 0) // all elements must be positive
{
FDate.DecodeDate(&AYear, &AMonth, &ADay); // get current date elements
switch (Index)
{
case 1: AYear = Value; break;
case 2: AMonth = Value; break;
case 3: ADay = Value; break;
default: return;
}
}
FDate = TDateTime(AYear, AMonth, ADay); // encode the modified date
//Refresh(); // update the visible calendar
UpdateCalendar(); // this previously called Refresh
Change(); // this is new
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::UpdateCalendar(void)
{
unsigned short AYear, AMonth, ADay;
TDateTime FirstDate; // date of first day of the month
if ((int)FDate != 0) // only calculate offset if date is valid
{
FDate.DecodeDate(&AYear, &AMonth, &ADay); // get elements of date
FirstDate = TDateTime(AYear, AMonth, 1); // date of the first
FMonthOffset = 2 - FirstDate.DayOfWeek(); // generate the offset into the grid
Row = (ADay - FMonthOffset) / 7 + 1;
Col = (ADay - FMonthOffset) % 7;
}
Refresh(); // always repaint the control
}//---------------------------------------------------------------------------
int __fastcall TSampleCalendar::DayNum(int ACol, int ARow)
{
int result = FMonthOffset + ACol + (ARow - 1) * 7; // calculate day for this cell
if ((result < 1)||(result > MonthDays[IsLeapYear(Year)][Month]))
result = -1; // return -1 if invalid
return result;
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::NextMonth()
{
DecodeDate(IncMonth(CalendarDate, 1), Year, Month, Day);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::PrevMonth()
{
DecodeDate(IncMonth(CalendarDate, -1), Year, Month, Day);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::NextYear()
{
DecodeDate(IncMonth(CalendarDate, 12), Year, Month, Day);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::PrevYear()
{
DecodeDate(IncMonth(CalendarDate, -12), Year, Month, Day);
}//---------------------------------------------------------------------------
/*void __fastcall TSampleCalendar::Click()
{
int TempDay = DayNum(Col, Row); // get the day number for the clicked cell
if (TempDay != -1) Day = TempDay; // change day if valid
}
*/
//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::Change()
{
if(FOnChange != NULL) FOnChange(this);
}//---------------------------------------------------------------------------
bool __fastcall TSampleCalendar::SelectCell(long ACol, long ARow)
{
if (DayNum(ACol,ARow) == -1) return false; // -1 indicates invalid date
else return TCustomGrid::SelectCell(ACol, ARow); // otherwise, use inherited value
}
源代码:(基本上和帮助里面的例子一样)
.CPP#include <vcl.h>
#pragma hdrstop
#include "CALSAMP.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
///*
static inline void ValidCtrCheck(TSampleCalendar *)
{
new TSampleCalendar(NULL);
}static inline TSampleCalendar * ValidCtrCheck()
{
return new TSampleCalendar(NULL);
}
*/
namespace Calsamp
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TSampleCalendar)};
RegisterComponents("System", classes, 0);
}
}
//---------------------------------------------------------------------------__fastcall TSampleCalendar::TSampleCalendar(TComponent *Owner) : TCustomGrid(Owner)
{
ColCount = 7;
RowCount = 7;
FixedCols = 0;
FixedRows = 1;
ScrollBars = ssNone;
Options = (Options >> goRangeSelect) << goDrawFocusSelected; FDate = FDate.CurrentDate();
UpdateCalendar();
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::DrawCell(long ACol, long ARow, const Windows::TRect &ARect,TGridDrawState AState)
{
String TheText;
int TempDay;
if (ARow == 0) TheText = ShortDayNames[ACol + 1];
else
{
TheText = "";
TempDay = DayNum(ACol, ARow); // DayNum is defined later
if (TempDay != -1) TheText = IntToStr(TempDay);
}
Canvas->TextRect(ARect, ARect.Left + (ARect.Right - ARect.Left
- Canvas->TextWidth(TheText)) / 2,
ARect.Top + (ARect.Bottom - ARect.Top - Canvas->TextHeight(TheText)) / 2, TheText);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::WMSize(TWMSize &Message)
{
int GridLines; // temporary local variable
GridLines = 6 * GridLineWidth; // calculated combined size of all lines
DefaultColWidth = (Message.Width - GridLines) / 7; // set new default cell width
DefaultRowHeight = (Message.Height - GridLines) / 7; // and cell height
}void __fastcall TSampleCalendar::SetCalendarDate(TDateTime Value)
{
FDate = Value; // Set the new date value
//Refresh(); // Update the onscreen image
UpdateCalendar(); // this previously called Refresh
Change(); // this is the only new statement
}
//---------------------------------------------------------------------------int __fastcall TSampleCalendar::GetDateElement(int Index)
{
unsigned short AYear, AMonth, ADay;
int result;
FDate.DecodeDate(&AYear, &AMonth, &ADay); // break encoded date into elements
switch (Index)
{
case 1: result = AYear; break;
case 2: result = AMonth; break;
case 3: result = ADay; break;
default: result = -1;
}
return result;
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::SetDateElement(int Index, int Value)
{
unsigned short AYear, AMonth, ADay;
if (Value > 0) // all elements must be positive
{
FDate.DecodeDate(&AYear, &AMonth, &ADay); // get current date elements
switch (Index)
{
case 1: AYear = Value; break;
case 2: AMonth = Value; break;
case 3: ADay = Value; break;
default: return;
}
}
FDate = TDateTime(AYear, AMonth, ADay); // encode the modified date
//Refresh(); // update the visible calendar
UpdateCalendar(); // this previously called Refresh
Change(); // this is new
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::UpdateCalendar(void)
{
unsigned short AYear, AMonth, ADay;
TDateTime FirstDate; // date of first day of the month
if ((int)FDate != 0) // only calculate offset if date is valid
{
FDate.DecodeDate(&AYear, &AMonth, &ADay); // get elements of date
FirstDate = TDateTime(AYear, AMonth, 1); // date of the first
FMonthOffset = 2 - FirstDate.DayOfWeek(); // generate the offset into the grid
Row = (ADay - FMonthOffset) / 7 + 1;
Col = (ADay - FMonthOffset) % 7;
}
Refresh(); // always repaint the control
}//---------------------------------------------------------------------------
int __fastcall TSampleCalendar::DayNum(int ACol, int ARow)
{
int result = FMonthOffset + ACol + (ARow - 1) * 7; // calculate day for this cell
if ((result < 1)||(result > MonthDays[IsLeapYear(Year)][Month]))
result = -1; // return -1 if invalid
return result;
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::NextMonth()
{
DecodeDate(IncMonth(CalendarDate, 1), Year, Month, Day);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::PrevMonth()
{
DecodeDate(IncMonth(CalendarDate, -1), Year, Month, Day);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::NextYear()
{
DecodeDate(IncMonth(CalendarDate, 12), Year, Month, Day);
}//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::PrevYear()
{
DecodeDate(IncMonth(CalendarDate, -12), Year, Month, Day);
}//---------------------------------------------------------------------------
/*void __fastcall TSampleCalendar::Click()
{
int TempDay = DayNum(Col, Row); // get the day number for the clicked cell
if (TempDay != -1) Day = TempDay; // change day if valid
}
*/
//---------------------------------------------------------------------------
void __fastcall TSampleCalendar::Change()
{
if(FOnChange != NULL) FOnChange(this);
}//---------------------------------------------------------------------------
bool __fastcall TSampleCalendar::SelectCell(long ACol, long ARow)
{
if (DayNum(ACol,ARow) == -1) return false; // -1 indicates invalid date
else return TCustomGrid::SelectCell(ACol, ARow); // otherwise, use inherited value
}
#define CALSAMPH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <Grids.hpp>
//---------------------------------------------------------------------------
class PACKAGE TSampleCalendar : public TCustomGrid
{
private:
TDateTime FDate;
void __fastcall SetCalendarDate(TDateTime Value);
int __fastcall GetDateElement(int Index); // note the Index parameter
void __fastcall SetDateElement(int Index, int Value);
int FMonthOffset; // storage for the offset
TNotifyEvent FOnChange;
protected:
virtual void __fastcall DrawCell(long ACol, long ARow, const Windows::TRect &Rect,
TGridDrawState AState);
void __fastcall WMSize(TWMSize &Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SIZE, TWMSize, WMSize)
END_MESSAGE_MAP(TCustomGrid) virtual void __fastcall UpdateCalendar(void);
int __fastcall DayNum(int ACol, int ARow);
void __fastcall NextMonth();
void __fastcall PrevMonth();
void __fastcall NextYear();
void __fastcall PrevYear();
//DYNAMIC void __fastcall Click();
virtual void __fastcall Change();
bool __fastcall TSampleCalendar::SelectCell(long ACol, long ARow);public: virtual __fastcall TSampleCalendar(TComponent* Owner);
__property TDateTime CalendarDate = {read=FDate, write=SetCalendarDate, nodefault};
__property int Day = {read=GetDateElement, write=SetDateElement, index=3, nodefault};
__property int Month = {read=GetDateElement, write=SetDateElement, index=2, nodefault};
__property int Year = {read=GetDateElement, write=SetDateElement, index=1, nodefault};
// __fastcall TSampleCalendar(TComponent *Owner); // the added constructor
__published:
__property Align ; // publish properties
__property BorderStyle ;
__property Color ;
__property Font ;
__property GridLineWidth ;
__property ParentColor ;
__property ParentFont ;
__property OnClick ; // publish events
__property OnDblClick ;
__property OnDragDrop ;
__property OnDragOver ;
__property OnEndDrag ;
__property OnKeyDown ;
__property OnKeyPress ;
__property OnKeyUp ; __property TNotifyEvent OnChange = {read=FOnChange, write=FOnChange};
};
//---------------------------------------------------------------------------
#endif在上面我把那个纯虚拟的检测注销了,因为在编译的时候就通不过,我也怀疑是这个问题导致,但我看了它自带的例子(ccalendr.cpp,ccalendr.h)基本上和我写的一样,好奇怪,为什么呢?
/*
static inline void ValidCtrCheck(TSampleCalendar *)
{
new TSampleCalendar(NULL);
}static inline TSampleCalendar * ValidCtrCheck()
{
return new TSampleCalendar(NULL);
}
*/请各位指点指点:
TGridDrawState AState);要改为:
virtual void __fastcall DrawCell(int ACol, int ARow, const Windows::TRect &Rect,
TGridDrawState AState);这样就可以了,重载的时候,参数个数和类型都的一致才行。