1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/calctrl.cpp
3 // Purpose: wxCalendarCtrl implementation
4 // Author: Vadim Zeitlin
7 // Copyright: (C) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
25 #if wxUSE_CALENDARCTRL
28 #include "wx/msw/wrapwin.h"
29 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
30 #include "wx/msw/private.h"
33 #include "wx/calctrl.h"
35 #include "wx/msw/private/datecontrols.h"
37 IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl
, wxControl
)
39 // ============================================================================
41 // ============================================================================
43 // ----------------------------------------------------------------------------
44 // wxCalendarCtrl creation
45 // ----------------------------------------------------------------------------
48 wxCalendarCtrl::Create(wxWindow
*parent
,
56 if ( !wxMSWDateControls::CheckInitialization() )
59 // initialize the base class
60 if ( !CreateControl(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
63 // create the native control
64 if ( !MSWCreateControl(MONTHCAL_CLASS
, wxEmptyString
, pos
, size
) )
67 SetDate(dt
.IsValid() ? dt
: wxDateTime::Today());
72 WXDWORD
wxCalendarCtrl::MSWGetStyle(long style
, WXDWORD
*exstyle
) const
74 WXDWORD styleMSW
= wxCalendarCtrlBase::MSWGetStyle(style
, exstyle
);
76 // right now we don't support any native styles but we should add wx styles
77 // corresponding to MCS_NOTODAY, MCS_NOTODAYCIRCLE and MCS_WEEKNUMBERS
80 // for compatibility with the other versions, just turn off today display
81 // unconditionally for now
82 styleMSW
|= MCS_NOTODAY
;
87 // TODO: handle WM_WININICHANGE
89 // ----------------------------------------------------------------------------
90 // wxCalendarCtrl geometry
91 // ----------------------------------------------------------------------------
93 wxSize
wxCalendarCtrl::DoGetBestSize() const
96 if ( !GetHwnd() || !MonthCal_GetMinReqRect(GetHwnd(), &rc
) )
98 return wxCalendarCtrlBase::DoGetBestSize();
101 const wxSize best
= wxRectFromRECT(rc
).GetSize() + GetWindowBorderSize();
106 wxCalendarHitTestResult
107 wxCalendarCtrl::HitTest(const wxPoint
& pos
,
109 wxDateTime::WeekDay
*wd
)
111 WinStruct
<MCHITTESTINFO
> hti
;
114 switch ( MonthCal_HitTest(GetHwnd(), &hti
) )
117 case MCHT_CALENDARWEEKNUM
:
118 wxFAIL_MSG( "unexpected" );
122 case MCHT_CALENDARBK
:
124 case MCHT_TITLEMONTH
:
126 return wxCAL_HITTEST_NOWHERE
;
128 case MCHT_CALENDARDATE
:
130 wxMSWDateControls::FromSystemTime(date
, hti
.st
);
131 return wxCAL_HITTEST_DAY
;
133 case MCHT_CALENDARDAY
:
136 *wd
= wx_static_cast(wxDateTime::WeekDay
, hti
.st
.wDayOfWeek
);
138 return wxCAL_HITTEST_HEADER
;
140 case MCHT_TITLEBTNNEXT
:
141 return wxCAL_HITTEST_INCMONTH
;
143 case MCHT_TITLEBTNPREV
:
144 return wxCAL_HITTEST_DECMONTH
;
146 case MCHT_CALENDARDATENEXT
:
147 case MCHT_CALENDARDATEPREV
:
148 return wxCAL_HITTEST_SURROUNDING_WEEK
;
152 // ----------------------------------------------------------------------------
153 // wxCalendarCtrl operations
154 // ----------------------------------------------------------------------------
156 bool wxCalendarCtrl::SetDate(const wxDateTime
& dt
)
158 wxCHECK_MSG( dt
.IsValid(), false, "invalid date" );
161 wxMSWDateControls::ToSystemTime(&st
, dt
);
162 if ( !MonthCal_SetCurSel(GetHwnd(), &st
) )
164 wxLogDebug(_T("DateTime_SetSystemtime() failed"));
174 wxDateTime
wxCalendarCtrl::GetDate() const
178 if ( !MonthCal_GetCurSel(GetHwnd(), &st
) )
180 wxASSERT_MSG( !m_date
.IsValid(), "mismatch between data and control" );
182 return wxDefaultDateTime
;
186 wxMSWDateControls::FromSystemTime(&dt
, st
);
188 wxASSERT_MSG( dt
== m_date
, "mismatch between data and control" );
189 #endif // __WXDEBUG__
194 bool wxCalendarCtrl::SetDateRange(const wxDateTime
& dt1
, const wxDateTime
& dt2
)
201 wxMSWDateControls::ToSystemTime(&st
[0], dt1
);
207 wxMSWDateControls::ToSystemTime(&st
[1], dt2
);
211 if ( !MonthCal_SetRange(GetHwnd(), flags
, st
) )
213 wxLogDebug(_T("MonthCal_SetRange() failed"));
219 bool wxCalendarCtrl::GetDateRange(wxDateTime
*dt1
, wxDateTime
*dt2
) const
223 DWORD flags
= MonthCal_GetRange(GetHwnd(), st
);
226 if ( flags
& GDTR_MIN
)
227 wxMSWDateControls::FromSystemTime(dt1
, st
[0]);
229 *dt1
= wxDefaultDateTime
;
234 if ( flags
& GDTR_MAX
)
235 wxMSWDateControls::FromSystemTime(dt2
, st
[1]);
237 *dt2
= wxDefaultDateTime
;
243 // ----------------------------------------------------------------------------
244 // other wxCalendarCtrl operations
245 // ----------------------------------------------------------------------------
247 bool wxCalendarCtrl::EnableMonthChange(bool enable
)
249 if ( !wxCalendarCtrlBase::EnableMonthChange(enable
) )
252 wxDateTime dtStart
, dtEnd
;
258 dtEnd
= dtStart
.GetLastMonthDay();
260 //else: leave them invalid to remove the restriction
262 SetDateRange(dtStart
, dtEnd
);
267 void wxCalendarCtrl::Mark(size_t day
, bool mark
)
269 wxFAIL_MSG( "not implemented" );
272 // ----------------------------------------------------------------------------
273 // wxCalendarCtrl events
274 // ----------------------------------------------------------------------------
276 bool wxCalendarCtrl::MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
278 NMHDR
* hdr
= (NMHDR
*)lParam
;
282 // we need to update m_date first, before calling the user code
283 // which expects GetDate() to return the new date
284 const wxDateTime dateOld
= m_date
;
285 const NMSELCHANGE
* const sch
= (NMSELCHANGE
*)lParam
;
286 wxMSWDateControls::FromSystemTime(&m_date
, sch
->stSelStart
);
288 // changing the year or the month results in a second dummy
289 // MCN_SELCHANGE event on this system which doesn't really change
290 // anything -- filter it out
291 if ( m_date
!= dateOld
)
293 GenerateAllChangeEvents(dateOld
);
300 return wxCalendarCtrlBase::MSWOnNotify(idCtrl
, lParam
, result
);
303 #endif // wxUSE_CALENDARCTRL