class WXDLLIMPEXP_ADV wxCalendarCtrl : public wxCalendarCtrlBase
{
public:
- wxCalendarCtrl() { }
+ wxCalendarCtrl() { Init(); }
wxCalendarCtrl(wxWindow *parent,
wxWindowID id,
const wxDateTime& date = wxDefaultDateTime,
long style = wxCAL_SHOW_HOLIDAYS,
const wxString& name = wxCalendarNameStr)
{
+ Init();
+
Create(parent, id, date, pos, size, style, name);
}
void MSWOnDoubleClick(wxMouseEvent& event);
private:
+ void Init() { m_marks = 0; }
+
+ void UpdateMarks();
+
+
+ // current date, we need to store it instead of simply retrieving it from
+ // the control as needed in order to be able to generate the correct events
+ // from MSWOnNotify()
wxDateTime m_date;
+ // bit field containing the state (marked or not) of all days in the month
+ wxUint32 m_marks;
+
+
DECLARE_DYNAMIC_CLASS(wxCalendarCtrl)
DECLARE_NO_COPY_CLASS(wxCalendarCtrl)
};
void MyPanel::OnCalendar(wxCalendarEvent& event)
{
- m_calendar->Mark(event.GetDate().GetDay(), true);
- wxLogMessage(wxT("Selected (and marked) %s from calendar."),
- event.GetDate().FormatISODate().c_str());
+ // clicking the same date twice unmarks it (convenient for testing)
+ static wxDateTime s_dateLast;
+ const bool mark = !s_dateLast.IsValid() || event.GetDate() != s_dateLast;
+
+ s_dateLast = event.GetDate();
+
+ m_calendar->Mark(event.GetDate().GetDay(), mark);
+ wxLogMessage(wxT("Selected (and %smarked) %s from calendar."),
+ mark ? "" : "un", s_dateLast.FormatISODate().c_str());
}
void MyPanel::OnCalendarChange(wxCalendarEvent& event)
SetDate(dt.IsValid() ? dt : wxDateTime::Today());
- Connect(wxEVT_LEFT_DOWN,
+ UpdateMarks();
+
+ Connect(wxEVT_LEFT_DCLICK,
wxMouseEventHandler(wxCalendarCtrl::MSWOnDoubleClick));
return true;
// unconditionally for now
styleMSW |= MCS_NOTODAY;
+ // we also need this style for Mark() to work
+ styleMSW |= MCS_DAYSTATE;
+
return styleMSW;
}
void wxCalendarCtrl::Mark(size_t day, bool mark)
{
- wxFAIL_MSG( "not implemented" );
+ wxCHECK_RET( day > 0 && day < 32, "invalid day" );
+
+ int mask = 1 << (day - 1);
+ if ( mark )
+ m_marks |= mask;
+ else
+ m_marks &= ~mask;
+
+ // calling Refresh() here is not enough to change the day appearance
+ UpdateMarks();
+}
+
+void wxCalendarCtrl::UpdateMarks()
+{
+ MONTHDAYSTATE states[3];
+ const int nMonths = MonthCal_GetMonthRange(GetHwnd(), GMR_DAYSTATE, NULL);
+ wxCHECK_RET( nMonths <= WXSIZEOF(states), "unexpected months range" );
+
+ for ( int i = 0; i < nMonths; i++ )
+ states[i] = m_marks;
+
+ if ( !MonthCal_SetDayState(GetHwnd(), nMonths, states) )
+ {
+ wxLogLastError(_T("MonthCal_SetDayState"));
+ }
}
// ----------------------------------------------------------------------------
switch ( hdr->code )
{
case MCN_SELCHANGE:
- // we need to update m_date first, before calling the user code
- // which expects GetDate() to return the new date
- const wxDateTime dateOld = m_date;
- const NMSELCHANGE * const sch = (NMSELCHANGE *)lParam;
- wxMSWDateControls::FromSystemTime(&m_date, sch->stSelStart);
-
- // changing the year or the month results in a second dummy
- // MCN_SELCHANGE event on this system which doesn't really change
- // anything -- filter it out
- if ( m_date != dateOld )
{
- GenerateAllChangeEvents(dateOld);
+ // we need to update m_date first, before calling the user code
+ // which expects GetDate() to return the new date
+ const wxDateTime dateOld = m_date;
+ const NMSELCHANGE * const sch = (NMSELCHANGE *)lParam;
+ wxMSWDateControls::FromSystemTime(&m_date, sch->stSelStart);
+
+ // changing the year or the month results in a second dummy
+ // MCN_SELCHANGE event on this system which doesn't really
+ // change anything -- filter it out
+ if ( m_date != dateOld )
+ {
+ GenerateAllChangeEvents(dateOld);
+ }
+ }
+ break;
- *result = 0;
- return true;
+ case MCN_GETDAYSTATE:
+ {
+ const NMDAYSTATE * const ds = (NMDAYSTATE *)lParam;
+ for ( int i = 0; i < ds->cDayState; i++ )
+ {
+ ds->prgDayState[i] = m_marks;
+ }
}
+ break;
+
+ default:
+ return wxCalendarCtrlBase::MSWOnNotify(idCtrl, lParam, result);
}
- return wxCalendarCtrlBase::MSWOnNotify(idCtrl, lParam, result);
+ *result = 0;
+ return true;
}
void wxCalendarCtrl::MSWOnDoubleClick(wxMouseEvent& event)