From 82c6027b47b738c86cfd1225e86e445f3523e744 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 4 Apr 2008 16:26:39 +0000 Subject: [PATCH] implemented Mark() in the native MSW version of wxCalendarCtrl git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@53009 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/calctrl.h | 16 +++++++- samples/calendar/calendar.cpp | 12 ++++-- src/msw/calctrl.cpp | 75 +++++++++++++++++++++++++++-------- 3 files changed, 83 insertions(+), 20 deletions(-) diff --git a/include/wx/msw/calctrl.h b/include/wx/msw/calctrl.h index 3f527182f1..d750d54728 100644 --- a/include/wx/msw/calctrl.h +++ b/include/wx/msw/calctrl.h @@ -13,7 +13,7 @@ class WXDLLIMPEXP_ADV wxCalendarCtrl : public wxCalendarCtrlBase { public: - wxCalendarCtrl() { } + wxCalendarCtrl() { Init(); } wxCalendarCtrl(wxWindow *parent, wxWindowID id, const wxDateTime& date = wxDefaultDateTime, @@ -22,6 +22,8 @@ public: long style = wxCAL_SHOW_HOLIDAYS, const wxString& name = wxCalendarNameStr) { + Init(); + Create(parent, id, date, pos, size, style, name); } @@ -58,8 +60,20 @@ protected: 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) }; diff --git a/samples/calendar/calendar.cpp b/samples/calendar/calendar.cpp index 0c9a7892bb..6b93a7eb4e 100644 --- a/samples/calendar/calendar.cpp +++ b/samples/calendar/calendar.cpp @@ -637,9 +637,15 @@ MyPanel::MyPanel(wxWindow *parent) 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) diff --git a/src/msw/calctrl.cpp b/src/msw/calctrl.cpp index 53e802a827..69c5abeb6b 100644 --- a/src/msw/calctrl.cpp +++ b/src/msw/calctrl.cpp @@ -89,7 +89,9 @@ wxCalendarCtrl::Create(wxWindow *parent, SetDate(dt.IsValid() ? dt : wxDateTime::Today()); - Connect(wxEVT_LEFT_DOWN, + UpdateMarks(); + + Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(wxCalendarCtrl::MSWOnDoubleClick)); return true; @@ -107,6 +109,9 @@ WXDWORD wxCalendarCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const // unconditionally for now styleMSW |= MCS_NOTODAY; + // we also need this style for Mark() to work + styleMSW |= MCS_DAYSTATE; + return styleMSW; } @@ -292,7 +297,31 @@ bool wxCalendarCtrl::EnableMonthChange(bool enable) 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")); + } } // ---------------------------------------------------------------------------- @@ -305,25 +334,39 @@ bool wxCalendarCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) 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) -- 2.45.2