X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a4fcd589a85e735e6c17f1470e739d9fcc946e9e..7b0ccb8a603b4f97740acc65d9429bb58f7ba1bd:/src/msw/calctrl.cpp diff --git a/src/msw/calctrl.cpp b/src/msw/calctrl.cpp index 8432ccc6bd..37bd62296f 100644 --- a/src/msw/calctrl.cpp +++ b/src/msw/calctrl.cpp @@ -56,16 +56,52 @@ wxCalendarCtrl::Create(wxWindow *parent, if ( !wxMSWDateControls::CheckInitialization() ) return false; + // we need the arrows for the navigation + style |= wxWANTS_CHARS; + // initialize the base class if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) ) return false; - // create the native control - if ( !MSWCreateControl(MONTHCAL_CLASS, wxEmptyString, pos, size) ) + // create the native control: this is a bit tricky as we want to receive + // double click events but the MONTHCAL_CLASS doesn't use CS_DBLCLKS style + // and so we create our own copy of it which does + static ClassRegistrar s_clsMonthCal; + if ( !s_clsMonthCal.IsInitialized() ) + { + // get a copy of standard class and modify it + WNDCLASS wc; + if ( ::GetClassInfo(NULL, MONTHCAL_CLASS, &wc) ) + { + wc.lpszClassName = wxT("_wx_SysMonthCtl32"); + wc.style |= CS_DBLCLKS; + s_clsMonthCal.Register(wc); + } + else + { + wxLogLastError(_T("GetClassInfoEx(SysMonthCal32)")); + } + } + + const wxChar * const clsname = s_clsMonthCal.IsRegistered() + ? s_clsMonthCal.GetName().wx_str() + : MONTHCAL_CLASS; + + if ( !MSWCreateControl(clsname, wxEmptyString, pos, size) ) return false; + // initialize the control + UpdateFirstDayOfWeek(); + SetDate(dt.IsValid() ? dt : wxDateTime::Today()); + UpdateMarks(); + + Connect(wxEVT_LEFT_DOWN, + wxMouseEventHandler(wxCalendarCtrl::MSWOnClick)); + Connect(wxEVT_LEFT_DCLICK, + wxMouseEventHandler(wxCalendarCtrl::MSWOnDoubleClick)); + return true; } @@ -81,15 +117,27 @@ 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; } -// TODO: handle WM_WININICHANGE +void wxCalendarCtrl::SetWindowStyleFlag(long style) +{ + const bool hadMondayFirst = HasFlag(wxCAL_MONDAY_FIRST); + + wxCalendarCtrlBase::SetWindowStyleFlag(style); + + if ( HasFlag(wxCAL_MONDAY_FIRST) != hadMondayFirst ) + UpdateFirstDayOfWeek(); +} // ---------------------------------------------------------------------------- // wxCalendarCtrl geometry // ---------------------------------------------------------------------------- +// TODO: handle WM_WININICHANGE wxSize wxCalendarCtrl::DoGetBestSize() const { RECT rc; @@ -266,7 +314,36 @@ 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 <= (int)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")); + } +} + +void wxCalendarCtrl::UpdateFirstDayOfWeek() +{ + MonthCal_SetFirstDayOfWeek(GetHwnd(), HasFlag(wxCAL_MONDAY_FIRST) ? 0 : 6); } // ---------------------------------------------------------------------------- @@ -279,25 +356,59 @@ 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) +{ + if ( HitTest(event.GetPosition()) == wxCAL_HITTEST_DAY ) + { + if ( GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED) ) + return; // skip event.Skip() below + } + + event.Skip(); +} + +void wxCalendarCtrl::MSWOnClick(wxMouseEvent& event) +{ + // for some reason, the control doesn't get focus on its own when the user + // clicks in it + SetFocus(); + + event.Skip(); } #endif // wxUSE_CALENDARCTRL