X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f9d2e19d216beea3ada925054f9523cc581f0cf9..a7d354c6d75a32033f62b8ecadd837519b35b3ef:/src/msw/calctrl.cpp?ds=sidebyside diff --git a/src/msw/calctrl.cpp b/src/msw/calctrl.cpp index 239abf65ca..529209551f 100644 --- a/src/msw/calctrl.cpp +++ b/src/msw/calctrl.cpp @@ -36,6 +36,27 @@ IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl, wxControl) +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +namespace +{ + +// values of week days used by the native control +enum +{ + MonthCal_Monday, + MonthCal_Tuesday, + MonthCal_Wednesday, + MonthCal_Thursday, + MonthCal_Friday, + MonthCal_Saturday, + MonthCal_Sunday +}; + +} // anonymous namespace + // ============================================================================ // implementation // ============================================================================ @@ -96,7 +117,7 @@ wxCalendarCtrl::Create(wxWindow *parent, if ( !MSWCreateControl(clsname, wxEmptyString, pos, size) ) return false; - // initialize the control + // initialize the control UpdateFirstDayOfWeek(); SetDate(dt.IsValid() ? dt : wxDateTime::Today()); @@ -199,7 +220,26 @@ wxCalendarCtrl::HitTest(const wxPoint& pos, case MCHT_CALENDARDAY: if ( wd ) { - *wd = static_cast(hti.st.wDayOfWeek); + int day = hti.st.wDayOfWeek; + + // the native control returns incorrect day of the week when + // the first day isn't Monday, i.e. the first column is always + // "Monday" even if its label is "Sunday", compensate for it + const int first = LOWORD(MonthCal_GetFirstDayOfWeek(GetHwnd())); + if ( first == MonthCal_Monday ) + { + // as MonthCal_Monday is 0 while wxDateTime::Mon is 1, + // normally we need to do this to transform from MSW + // convention to wx one + day++; + day %= 7; + } + //else: but when the first day is MonthCal_Sunday, the native + // control still returns 0 (i.e. MonthCal_Monday) for the + // first column which looks like a bug in it but to work + // around it it's enough to not apply the correction above + + *wd = static_cast(day); } return wxCAL_HITTEST_HEADER; @@ -223,8 +263,10 @@ bool wxCalendarCtrl::SetDate(const wxDateTime& dt) { wxCHECK_MSG( dt.IsValid(), false, "invalid date" ); + const wxDateTime date = dt.GetDateOnly(); + SYSTEMTIME st; - dt.GetAsMSWSysTime(&st); + date.GetAsMSWSysTime(&st); if ( !MonthCal_SetCurSel(GetHwnd(), &st) ) { wxLogDebug(wxT("DateTime_SetSystemtime() failed")); @@ -232,7 +274,7 @@ bool wxCalendarCtrl::SetDate(const wxDateTime& dt) return false; } - m_date = dt; + m_date = date; return true; } @@ -250,7 +292,12 @@ wxDateTime wxCalendarCtrl::GetDate() const wxDateTime dt(st); - wxASSERT_MSG( dt == m_date, "mismatch between data and control" ); + // Windows XP and earlier didn't include the time component into the + // returned date but Windows 7 does, so we can't compare the full objects + // in the same way under all the Windows versions, just compare their date + // parts + wxASSERT_MSG( dt.GetDateOnly() == m_date.GetDateOnly(), + "mismatch between data and control" ); #endif // wxDEBUG_LEVEL return m_date; @@ -356,27 +403,40 @@ void wxCalendarCtrl::UpdateMarks() // before it and from the one after it so days from 3 different months can // be partially shown MONTHDAYSTATE states[3] = { 0 }; - const int nMonths = MonthCal_GetMonthRange(GetHwnd(), GMR_DAYSTATE, NULL); + const DWORD nMonths = MonthCal_GetMonthRange(GetHwnd(), GMR_DAYSTATE, NULL); // although in principle the calendar might not show any days from the // preceding months, it seems like it always does, consider e.g. Feb 2010 // which starts on Monday and ends on Sunday and so could fit on 4 lines // without showing any subsequent months -- the standard control still // shows it on 6 lines and the number of visible months is still 3 - wxCHECK_RET( nMonths == (int)WXSIZEOF(states), "unexpected months range" ); - - // the fully visible month is the one in the middle - states[1] = m_marks | m_holidays; - - if ( !MonthCal_SetDayState(GetHwnd(), nMonths, states) ) + // + // OTOH Windows 7 control can show all 12 months or even years or decades + // in its window if you "zoom out" of it by double clicking on free areas + // so the return value can be (much, in case of decades view) greater than + // 3 but in this case marks are not visible anyhow so simply ignore it + if ( nMonths < WXSIZEOF(states) ) { - wxLogLastError(wxT("MonthCal_SetDayState")); + wxFAIL_MSG("unexpectedly few months shown in the control"); + } + else if ( nMonths == WXSIZEOF(states) ) + { + // the fully visible month is the one in the middle + states[1] = m_marks | m_holidays; + + if ( !MonthCal_SetDayState(GetHwnd(), nMonths, states) ) + { + wxLogLastError(wxT("MonthCal_SetDayState")); + } } + //else: not a month view at all } void wxCalendarCtrl::UpdateFirstDayOfWeek() { - MonthCal_SetFirstDayOfWeek(GetHwnd(), HasFlag(wxCAL_MONDAY_FIRST) ? 0 : 6); + MonthCal_SetFirstDayOfWeek(GetHwnd(), + HasFlag(wxCAL_MONDAY_FIRST) ? MonthCal_Monday + : MonthCal_Sunday); } // ----------------------------------------------------------------------------