// Calendar.h #ifndef Calendarh #define Calendarh #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 /* Drag out a Button on the dialog, then set the Button's [OwnerDraw] Property to checked. Derive a class of your own from CCalendar that implements OnChanging() and OnChanged() if you need to. Create an instance of your class in your Dialog class (Header File). In your dialog OnInitDlg() subclass the control to your class using: Calendar.SubclassDlgItem(IDC_Calendar, this); You can set the current Day, Month and Year in many ways. The default Constructor sets the Calendar to Today. Month and Day are 1 Based, Year is 1900 based and can go up to 137. You can also set the Background Colour, Text Colour and Specify some extra text for any day in the month using: Calendar.SetBgColor(RGB(255,255,0)); Calendar.SetTextColor(RGB(255,0,0), 17); Calendar.SetText("This is the day!", 17); After altering the Month or Year you may want to redraw the control, so use: Calendar.RedrawWindow(); to restore the default colours and Text use: Calendar.Clear(); If you change the Month or Year and don't want the Day to remain selected, set Day to -1 or 0xFF. */ class CCalendar : public CButton { static const BYTE GapWidth; static const BYTE GapHeight; static const BYTE ButtonsAcross; static const BYTE ButtonsDown; static const BYTE MaxButtons; BYTE Day,Month,Year,FirstDay; //Month and Day are 1 Based, Year is 1900 based and can go up to 137, FirstDay: Monday=0. BYTE Buttons; int ButtonWidth; int ButtonHeight; int TitleHeight; CRect* Rects; BYTE ButtonFromPoint(CPoint point); public: CCalendar() : FirstDay(0), Rects(0), ButtonWidth(0), ButtonHeight(0), TitleHeight(0), Day(Day), Month(Month), Year(Year) {Settings=new DayProps[31]; Set();} CCalendar(CTime Time) : FirstDay(0), Rects(0), ButtonWidth(0), ButtonHeight(0), TitleHeight(0) {Settings=new DayProps[31]; Set(Time);} CCalendar(BYTE _Day, BYTE _Month, BYTE _Year) : FirstDay(0), Rects(0), ButtonWidth(0), ButtonHeight(0), TitleHeight(0) {Settings=new DayProps[31]; Set(Day, Month, Year);} virtual ~CCalendar() { delete[] Rects; Rects=0; delete[] Settings; Settings=0; } virtual void OnChanging() {} virtual void OnChanged() {} //Month and Day are 1 Based, Year is 1900 based and can go up to 137 bool Set() {return Set(CTime::GetCurrentTime());} bool Set(CTime Time) {return Set(Time.GetDay(), Time.GetMonth(), Time.GetYear()-1900);} bool Set(BYTE Day, BYTE Month, BYTE Year) {return SetDay(Day) & SetMonth(Month) & SetYear(Year);} //Using & because && would only run until one call failed. bool SetDay (BYTE _Day ) {Day =_Day ; Buttons=DaysInMonth(Month,Year); return SetFirstDay();} bool SetMonth(BYTE _Month) {Month=_Month; Buttons=DaysInMonth(Month,Year); Clear(); return SetFirstDay();} bool SetYear (BYTE _Year ) {Year =_Year ; Buttons=DaysInMonth(Month,Year); Clear(); return SetFirstDay();} bool SetFirstDay() { //Monday=0 FirstDay=0; if(!IsValid(1,Month,Year) || Year>2037-1900) return false; struct tm atm; atm.tm_sec=atm.tm_min=atm.tm_hour=0; atm.tm_mday =1; //FirstDay of the Month atm.tm_mon =Month-1; //tm_mon is 0 based atm.tm_year =Year; //tm_year is 1900 based atm.tm_isdst=-1; time_t Date=mktime(&atm); if(!Date) return false; struct tm* ptm=localtime(&Date); if(!ptm) return false; FirstDay=(ptm->tm_wday ? ptm->tm_wday-1 : 6); //Monday=0 - Sunday=6 return true; } CTime GetDate() {return IsValid() ? CTime(Year+1900, Month, Day,0,0,0) : CTime::GetCurrentTime();} BYTE GetDay () const {return Day ;} BYTE GetMonth() const {return Month;} BYTE GetYear () const {return Year ;} BYTE DaysInMonth(BYTE Month, BYTE Year) { //Year is 1900 based and can go up to 137 BYTE DaysInMonth[]={31,29,31,30,31,30,31,31,30,31,30,31}; if(--Month>=12) return 0; if(Month!=2-1) return DaysInMonth[Month]; return Year & 3 ? 28 : 29; } //The unsigned arithmetic means that if Day or Month are zero, the predecrements will make them 255 bool IsValid() const {return IsValid(Day, Month, Year);} bool IsValid(BYTE Day, BYTE Month, BYTE Year) const { //Year is 1900 based and can go up to 137 BYTE DaysInMonth[]={31,29,31,30,31,30,31,31,30,31,30,31}; // Leap-year check: return (Year<137) && (--Month<12) && (--DayBgColor =GetSysColor(COLOR_BTNFACE); ptr->TextColor=GetSysColor(COLOR_BTNTEXT); ptr++->Text.Empty(); } } // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCalendar) public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); //}}AFX_VIRTUAL // Generated message map functions protected: //{{AFX_MSG(CCalendar) afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // ndef Calendarh