我按照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
}

解决方案 »

  1.   

    .H 文件:#ifndef CALSAMPH
    #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);
    }
    */请各位指点指点:
      

  2.   

    组件声明中有一个纯虚函数没有重载,   virtual void __fastcall DrawCell(long ACol, long ARow, const Windows::TRect &Rect,
            TGridDrawState AState);要改为:
       virtual void __fastcall DrawCell(int ACol, int ARow, const Windows::TRect &Rect,
            TGridDrawState AState);这样就可以了,重载的时候,参数个数和类型都的一致才行。