symbian 自绘日历控件

曾经项目中需要用日历控件。

头文件:

#ifndef Calendar_H_
#define Calendar_H_

#include <coecntrl.h>


class TCalendarObserver
 {
public:
 virtual void OnSelectCalendar(TDateTime sel) = 0;
 };


class CCalendar : public CCoeControl
{
public:  
 static CCalendar* NewL(CCoeControl* parent,const TRect& aRect);
 virtual ~CCalendar();
 
public: // from CCoeControl
 void Draw(const TRect& aRect) const;
 virtual void SizeChanged();
 virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent);
 virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
 
public:
 
 void SetObserver(TCalendarObserver* observer);
 
 virtual TSize MinimumSize();
 
 TDateTime GetSelDate();
private:
 void ConstructL(CCoeControl* parent,const TRect& aRect);
 CCalendar();
 
 
 TKeyResponse ClickUpSelect();
 TKeyResponse ClickDownSelect();
 TKeyResponse ClickLeftSelect();
 TKeyResponse ClickRightSelect();
private:
 //获取某年某月某天是星期几
 int GetWeek(int year, int month, int day = 1);

 //得到某月天数
 int GetDaysInMonth(int year,int month);
 
 void ClearGrid();
 
 TBool IsMoveOtherMonth(int index);
 
 void ResetAndLoad();
 void ToMonth(TBool add);
 
 void LayoutGrid();
private:
 
 struct TDayGridItem
  {
  int day;
  
  TRect position;
  };
 
 TDayGridItem m_Grid[42];
 RArray< TBuf<2> > m_Week;
 
 TBuf<12> titleYear;
 TBuf<12> titleMonth;
 TRect YearArea;
 TRect MonthArea;
 
 TBuf<2> upFlag;
 TBuf<2> DownFlag;
 TRect   YearUpArea;
 TRect  YearDownArea;
 TRect MonthUpArea;
 TRect MontyDownArea;
 
 int m_CurMonth;
 int m_CurYear;
 int m_CurDays;
 
 int m_CurDownIndex;
 int m_CurFirstIndex;
 
 TCalendarObserver* m_Observer;

};

#endif /* Calendar_H_ */

源文件:

#include "Calendar.h"
#include <e32cmn.h>
#include <EIKENV.H>
#include <GDI.H>

#define KGridRectW 25
#define KGridRectH 25

_LIT(KMonday,"\x4E00");
_LIT(KTuesday,"\x4E8C");
_LIT(KWednesday,"\x4E09");
_LIT(KThursday,"\x56DB");
_LIT(KFriday,"\x4E94");
_LIT(KSaturday,"\x516D");
_LIT(KSunday,"\x65E5");

_LIT(KFormatDate,"%d-%d-%d");

CCalendar* CCalendar::NewL(CCoeControl* parent, const TRect& aRect)
{
 CCalendar* self = new (ELeave) CCalendar;
 CleanupStack::PushL(self);
 self->ConstructL(parent, aRect);
 CleanupStack::Pop();

 return self;
}

CCalendar::CCalendar()
{
}

CCalendar::~CCalendar()
{
 m_Week.Close();

}


void CCalendar::ConstructL(CCoeControl* parent, const TRect& aRect)
{
 if (parent)
 {
  SetContainerWindowL(*parent);
 }
 else
 {
  CreateWindowL();
 }

 SetRect(aRect);

 m_Week.Append(KMonday());
 m_Week.Append(KTuesday());
 m_Week.Append(KWednesday());
 m_Week.Append(KThursday());
 m_Week.Append(KFriday());
 m_Week.Append(KSaturday());
 m_Week.Append(KSunday());
 
 upFlag = _L(">");
 DownFlag = _L("<");

 TTime curTime;
 curTime.HomeTime();
 TDateTime date = curTime.DateTime();
 
 m_CurMonth = date.Month()+1;
 m_CurYear = date.Year();
 
 ResetAndLoad();
 
 TDateTime curSelDate = GetSelDate();
 titleYear.AppendNum(curSelDate.Year());
 titleMonth.AppendNum((int)curSelDate.Month()+1);

 EnableDragEvents();

 ActivateL();
}


void CCalendar::Draw(const TRect& aRect) const
{
 CWindowGc& gc = SystemGc();

 gc.SetBrushStyle(gc.ESolidBrush);
 gc.SetBrushColor(KRgbGray);
 gc.DrawRect(aRect);

 const CFont* font = CEikonEnv::Static()->DenseFont();
 int baseline = font->HeightInPixels() + (TSize(KGridRectW,KGridRectH).iHeight - font->HeightInPixels()) / 2;
 
 gc.UseFont(font);
 
 gc.SetBrushStyle(gc.ENullBrush);
 gc.SetPenColor(KRgbBlack);
 
 TPoint tl = TPoint(Rect().iTl + TPoint((Rect().Width()-KGridRectW*7)/2,0));
 
 gc.DrawText(DownFlag,YearUpArea,baseline,CGraphicsContext::ECenter);
 gc.DrawText(titleYear,YearArea,baseline,CGraphicsContext::ECenter);
 gc.DrawText(upFlag,YearDownArea,baseline,CGraphicsContext::ECenter);
 
 gc.DrawText(DownFlag,MonthUpArea,baseline,CGraphicsContext::ECenter);
 gc.DrawText(titleMonth,MonthArea,baseline,CGraphicsContext::ECenter);
 gc.DrawText(upFlag,MontyDownArea,baseline,CGraphicsContext::ECenter);
 
 
 tl += TPoint(0,KGridRectH);
 TRect gridItemRect;
 //一二三四五六日
 for(int i=0; i<7; ++i)
  {
  gridItemRect = TRect(tl + TPoint(i*KGridRectW,0), TSize(KGridRectW,KGridRectH));
  gc.DrawRect(gridItemRect);
  
  gc.DrawText(m_Week[i],gridItemRect,baseline,CGraphicsContext::ECenter);
  }
 
 for(int i=0; i<6; ++i)
  {
  for(int j=0; j<7; ++j)
   {
   int down = (i*7)+j;
   
   if(m_CurDownIndex == down)
    {
    gc.SetBrushColor(KRgbBlue);
    gc.SetBrushStyle(gc.ESolidBrush);
    }
   else
    gc.SetBrushStyle(gc.ENullBrush);
   
   gc.DrawRect(m_Grid[down].position);
   
   if(m_Grid[down].day != 0)
    {
    TBuf<2> buf;
    buf.AppendNum(m_Grid[down].day);
    gc.DrawText(buf,m_Grid[down].position,baseline,CGraphicsContext::ECenter);
    }
   }
  }
 
 gc.DiscardFont();
}

void CCalendar::SizeChanged()
{
 LayoutGrid();
}


TKeyResponse CCalendar::OfferKeyEventL(const TKeyEvent& aKeyEvent,
  TEventCode aType)
{
 TKeyResponse r = EKeyWasNotConsumed;
 if (aType != EEventKey)
 {
  return r;
 }

 if (aKeyEvent.iCode == EKeyUpArrow)
 {
  r = ClickUpSelect();
 }
 else if (aKeyEvent.iCode == EKeyDownArrow)
 {
  r = ClickDownSelect();
 }
 else if(aKeyEvent.iCode == EKeyLeftArrow)
 {
  r = ClickLeftSelect();
 }
 else if(aKeyEvent.iCode == EKeyRightArrow)
 {
  r = ClickRightSelect();
 }
 else if(aKeyEvent.iCode == EKeyDevice3)
 {
  if(m_Observer)
   m_Observer->OnSelectCalendar(GetSelDate());
 }
 

 if (r == EKeyWasConsumed)
 {
  TDateTime curSelDate = GetSelDate();
  titleYear.Zero();
  titleYear.AppendNum(curSelDate.Year());
  titleMonth.Zero();
  titleMonth.AppendNum((int)curSelDate.Month()+1);
  DrawDeferred();
 }

 return r;
}

void CCalendar::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
 TPoint pt = aPointerEvent.iPosition;

 if (aPointerEvent.iType == TPointerEvent::EButton1Down)
  {
  for(int i=0; i<6; ++i)
   {
   for(int j=0; j<7; ++j)
    {
    int down = (i*7)+j;
   
    if(m_Grid[down].position.Contains(pt))
     {
     if(m_Observer)
      m_Observer->OnSelectCalendar(GetSelDate());
     }
    }
   }
  }
}


TKeyResponse CCalendar::ClickUpSelect()
 {
 m_CurDownIndex -= 7;
 
 if(IsMoveOtherMonth(m_CurDownIndex))
  {
  ToMonth(EFalse);
  
  ResetAndLoad();
  }
 
 return EKeyWasConsumed;
 }
TKeyResponse CCalendar::ClickDownSelect()
 {
 m_CurDownIndex += 7;
 
 if(IsMoveOtherMonth(m_CurDownIndex))
  {
  ToMonth(ETrue);
  
  ResetAndLoad();
  }
 
 return EKeyWasConsumed;
 }
TKeyResponse CCalendar::ClickLeftSelect()
 {
 m_CurDownIndex --;
 
 if(IsMoveOtherMonth(m_CurDownIndex))
  {
  ToMonth(EFalse);
  
  ResetAndLoad();
  }
 
 return EKeyWasConsumed;
 }
TKeyResponse CCalendar::ClickRightSelect()
 {
 m_CurDownIndex ++;
 
 if(IsMoveOtherMonth(m_CurDownIndex))
  {
  ToMonth(ETrue);
  
  ResetAndLoad();
  }
 
 return EKeyWasConsumed;
 }

void CCalendar::ToMonth(TBool add)
 {
 if(add)
  {
  m_CurMonth++;
  if(m_CurMonth > 12)
   {
   m_CurMonth = 1;
   m_CurYear++;
   }
  }
 else
  {
  m_CurMonth--;
  if(m_CurMonth < 1)
   {
   m_CurMonth = 12;
   m_CurYear--;
   }
  }
 }

void CCalendar::LayoutGrid()
 {
 TPoint tl = TPoint(Rect().iTl + TPoint((Rect().Width()-KGridRectW*7)/2,0));
 TPoint moveTl = tl;
 
 YearUpArea = TRect(moveTl,TSize(KGridRectW/2,KGridRectH));
 moveTl += TPoint(KGridRectW/2,0);
 YearArea = TRect(moveTl,TSize(KGridRectW*2,KGridRectH));
 moveTl += TPoint(KGridRectW*2,0);
 YearDownArea = TRect(moveTl,TSize(KGridRectW/2,KGridRectH));
 
 moveTl += TPoint(KGridRectW*2+KGridRectW/2,0);
 MonthUpArea = TRect(moveTl,TSize(KGridRectW/2,KGridRectH));
 moveTl += TPoint(KGridRectW/2,0);
 MonthArea = TRect(moveTl,TSize(KGridRectW,KGridRectH));
 moveTl += TPoint(KGridRectW,0);
 MontyDownArea = TRect(moveTl,TSize(KGridRectW/2,KGridRectH));
 
 moveTl = tl + TPoint(0, KGridRectH*2);
 TRect gridItemRect;
 for(int i=0; i<6; ++i)
  {
  for(int j=0; j<7; ++j)
   {
   int down = (i*7)+j;
   
   gridItemRect = TRect(moveTl + TPoint(j*KGridRectW,KGridRectH*i), TSize(KGridRectW,KGridRectH));

   m_Grid[down].position = gridItemRect;
   }
  }
 }

void  CCalendar::ResetAndLoad()
 {
 ClearGrid();
 
 int week = GetWeek(m_CurYear ,m_CurMonth );
 m_CurDays = GetDaysInMonth(m_CurYear, m_CurMonth);
 
 m_CurFirstIndex = week-1;
 m_CurDownIndex = week-1;
 
 for(int point = 1; point<=m_CurDays; point++)
  {
  int down = m_CurDownIndex+point-1;
  m_Grid[down].day = point;
  }
 
 DrawDeferred();
 }

TBool CCalendar::IsMoveOtherMonth(int index)
 {
 if(index < m_CurFirstIndex)
  return ETrue;
 if(index-m_CurFirstIndex >= m_CurDays)
  return ETrue;
 
 return EFalse;
 }

TSize CCalendar::MinimumSize()
{
 int h = 34*7;
 int w = 34*7;

 return TSize(w, h);
}

void CCalendar::SetObserver(TCalendarObserver* observer)
 {
 m_Observer = observer;
 }

TDateTime CCalendar::GetSelDate()
 {
 TDateTime date;
 date.SetYear(m_CurYear);
 date.SetMonth(TMonth(m_CurMonth-1));
 date.SetDay(m_Grid[m_CurDownIndex].day-1);
 
 return date;
 }

int CCalendar::GetWeek(int year, int month, int day)
 {
 int century = year/100;
 int syear = year%100;
 int smonth = month;
 int w , weekres = 0;
 
 if(month == 1)
  {
  century = (year-1)/100;
  syear = (year-1)%100;
  smonth = 13;
  }
 else if(month == 2)
  {
  century = (year-1)/100;
  syear = (year-1)%100;
  smonth = 14;
  }
 
 //蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
 
 w = syear + (syear/4) + (century/4) - 2*century + (26*(smonth+1)/10) + day - 1;
 if(w < 0)
  {
  weekres = (w+Abs(w)*7)%7;
  }
 else
  {
  weekres = w%7;
  }
 
 if(weekres == 0)
  weekres = 7;
 
 return weekres;
 }

int CCalendar::GetDaysInMonth(int year,int month)
 {
 switch(month)
  {
  case 1:
  case 3:
  case 5:
  case 7:
  case 8:
  case 10:
  case 12:
   return 31;
  case 4:
  case 6:
  case 9:
  case 11:
   return 30;
  case 2:
   {
   if((year%4==0)&&((year%100)||(year%400==0)))
    return 29;
   else
    return 28;
   }
  }
 }

void CCalendar::ClearGrid()
 {
 for(int i=0; i<42; ++i)
  {
  m_Grid[i].day = 0;
  }
 }

效果图:

图片



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值