X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9573840bcf042dda2d273d5c8f3c2bda27e89d01..96c9640205933ad0673d5af2c96af0816c50160c:/src/msw/calctrl.cpp diff --git a/src/msw/calctrl.cpp b/src/msw/calctrl.cpp index 529209551f..467ced1e8c 100644 --- a/src/msw/calctrl.cpp +++ b/src/msw/calctrl.cpp @@ -34,8 +34,6 @@ #include "wx/msw/private/datecontrols.h" -IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl, wxControl) - // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -122,8 +120,8 @@ wxCalendarCtrl::Create(wxWindow *parent, SetDate(dt.IsValid() ? dt : wxDateTime::Today()); - if ( SetHolidayAttrs() ) - UpdateMarks(); + SetHolidayAttrs(); + UpdateMarks(); Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxCalendarCtrl::MSWOnClick)); @@ -214,7 +212,7 @@ wxCalendarCtrl::HitTest(const wxPoint& pos, case MCHT_CALENDARDATE: if ( date ) - date->SetFromMSWSysTime(hti.st); + date->SetFromMSWSysDate(hti.st); return wxCAL_HITTEST_DAY; case MCHT_CALENDARDAY: @@ -263,10 +261,8 @@ bool wxCalendarCtrl::SetDate(const wxDateTime& dt) { wxCHECK_MSG( dt.IsValid(), false, "invalid date" ); - const wxDateTime date = dt.GetDateOnly(); - SYSTEMTIME st; - date.GetAsMSWSysTime(&st); + dt.GetAsMSWSysDate(&st); if ( !MonthCal_SetCurSel(GetHwnd(), &st) ) { wxLogDebug(wxT("DateTime_SetSystemtime() failed")); @@ -274,7 +270,7 @@ bool wxCalendarCtrl::SetDate(const wxDateTime& dt) return false; } - m_date = date; + m_date = dt.GetDateOnly(); return true; } @@ -283,6 +279,7 @@ wxDateTime wxCalendarCtrl::GetDate() const { #if wxDEBUG_LEVEL SYSTEMTIME st; + if ( !MonthCal_GetCurSel(GetHwnd(), &st) ) { wxASSERT_MSG( !m_date.IsValid(), "mismatch between data and control" ); @@ -290,14 +287,14 @@ wxDateTime wxCalendarCtrl::GetDate() const return wxDefaultDateTime; } - wxDateTime dt(st); + wxDateTime dt; + dt.SetFromMSWSysDate(st); // 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" ); + wxASSERT_MSG( dt.IsSameDate(m_date), "mismatch between data and control" ); #endif // wxDEBUG_LEVEL return m_date; @@ -336,7 +333,7 @@ bool wxCalendarCtrl::GetDateRange(wxDateTime *dt1, wxDateTime *dt2) const if ( dt1 ) { if ( flags & GDTR_MIN ) - dt1->SetFromMSWSysTime(st[0]); + dt1->SetFromMSWSysDate(st[0]); else *dt1 = wxDefaultDateTime; } @@ -344,7 +341,7 @@ bool wxCalendarCtrl::GetDateRange(wxDateTime *dt1, wxDateTime *dt2) const if ( dt2 ) { if ( flags & GDTR_MAX ) - dt2->SetFromMSWSysTime(st[1]); + dt2->SetFromMSWSysDate(st[1]); else *dt2 = wxDefaultDateTime; } @@ -399,10 +396,12 @@ void wxCalendarCtrl::SetHoliday(size_t day) void wxCalendarCtrl::UpdateMarks() { - // we show only one full month but there can be some days from the month - // before it and from the one after it so days from 3 different months can - // be partially shown - MONTHDAYSTATE states[3] = { 0 }; + // Currently the native control may show more than one month if its size is + // big enough. Ideal would be to prevent this from happening but there + // doesn't seem to be any obvious way to do it, so for now just handle the + // possibility that we can display several of them: one before the current + // one and up to 12 after it. + MONTHDAYSTATE states[14] = { 0 }; const DWORD nMonths = MonthCal_GetMonthRange(GetHwnd(), GMR_DAYSTATE, NULL); // although in principle the calendar might not show any days from the @@ -415,13 +414,9 @@ void wxCalendarCtrl::UpdateMarks() // 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) ) - { - wxFAIL_MSG("unexpectedly few months shown in the control"); - } - else if ( nMonths == WXSIZEOF(states) ) + if ( nMonths >= 2 && nMonths <= WXSIZEOF(states) ) { - // the fully visible month is the one in the middle + // The current, fully visible month is always the second one. states[1] = m_marks | m_holidays; if ( !MonthCal_SetDayState(GetHwnd(), nMonths, states) ) @@ -454,7 +449,7 @@ bool wxCalendarCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // which expects GetDate() to return the new date const wxDateTime dateOld = m_date; const NMSELCHANGE * const sch = (NMSELCHANGE *)lParam; - m_date.SetFromMSWSysTime(sch->stSelStart); + m_date.SetFromMSWSysDate(sch->stSelStart); // changing the year or the month results in a second dummy // MCN_SELCHANGE event on this system which doesn't really @@ -465,8 +460,8 @@ bool wxCalendarCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { // month changed, need to update the holidays if we use // them - if ( SetHolidayAttrs() ) - UpdateMarks(); + SetHolidayAttrs(); + UpdateMarks(); } } } @@ -475,9 +470,24 @@ bool wxCalendarCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) case MCN_GETDAYSTATE: { const NMDAYSTATE * const ds = (NMDAYSTATE *)lParam; + + wxDateTime startDate; + startDate.SetFromMSWSysDate(ds->stStart); + + wxDateTime currentDate = m_date; + // Set to the start of month for comparison with startDate to + // work correctly. + currentDate.SetDay(1); + for ( int i = 0; i < ds->cDayState; i++ ) { - ds->prgDayState[i] = m_marks | m_holidays; + // set holiday/marks only for the "current" month + if ( startDate == currentDate ) + ds->prgDayState[i] = m_marks | m_holidays; + else + ds->prgDayState[i] = 0; + + startDate += wxDateSpan::Month(); } } break;