]> git.saurik.com Git - wxWidgets.git/blob - src/msw/calctrl.cpp
implemented HitTest() in the native MSW version; added test for it to the sample
[wxWidgets.git] / src / msw / calctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/calctrl.cpp
3 // Purpose: wxCalendarCtrl implementation
4 // Author: Vadim Zeitlin
5 // Created: 2008-04-04
6 // RCS-ID: $Id$
7 // Copyright: (C) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #if wxUSE_CALENDARCTRL
26
27 #ifndef WX_PRECOMP
28 #include "wx/msw/wrapwin.h"
29 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
30 #include "wx/msw/private.h"
31 #endif
32
33 #include "wx/calctrl.h"
34
35 #include "wx/msw/private/datecontrols.h"
36
37 IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl, wxControl)
38
39 // ============================================================================
40 // implementation
41 // ============================================================================
42
43 // ----------------------------------------------------------------------------
44 // wxCalendarCtrl creation
45 // ----------------------------------------------------------------------------
46
47 bool
48 wxCalendarCtrl::Create(wxWindow *parent,
49 wxWindowID id,
50 const wxDateTime& dt,
51 const wxPoint& pos,
52 const wxSize& size,
53 long style,
54 const wxString& name)
55 {
56 if ( !wxMSWDateControls::CheckInitialization() )
57 return false;
58
59 // initialize the base class
60 if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) )
61 return false;
62
63 // create the native control
64 if ( !MSWCreateControl(MONTHCAL_CLASS, wxEmptyString, pos, size) )
65 return false;
66
67 SetDate(dt.IsValid() ? dt : wxDateTime::Today());
68
69 return true;
70 }
71
72 WXDWORD wxCalendarCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
73 {
74 WXDWORD styleMSW = wxCalendarCtrlBase::MSWGetStyle(style, exstyle);
75
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
78 // probably (TODO)
79
80 // for compatibility with the other versions, just turn off today display
81 // unconditionally for now
82 styleMSW |= MCS_NOTODAY;
83
84 return styleMSW;
85 }
86
87 // TODO: handle WM_WININICHANGE
88
89 // ----------------------------------------------------------------------------
90 // wxCalendarCtrl geometry
91 // ----------------------------------------------------------------------------
92
93 wxSize wxCalendarCtrl::DoGetBestSize() const
94 {
95 RECT rc;
96 if ( !GetHwnd() || !MonthCal_GetMinReqRect(GetHwnd(), &rc) )
97 {
98 return wxCalendarCtrlBase::DoGetBestSize();
99 }
100
101 const wxSize best = wxRectFromRECT(rc).GetSize() + GetWindowBorderSize();
102 CacheBestSize(best);
103 return best;
104 }
105
106 wxCalendarHitTestResult
107 wxCalendarCtrl::HitTest(const wxPoint& pos,
108 wxDateTime *date,
109 wxDateTime::WeekDay *wd)
110 {
111 WinStruct<MCHITTESTINFO> hti;
112 hti.pt.x = pos.x;
113 hti.pt.y = pos.y;
114 switch ( MonthCal_HitTest(GetHwnd(), &hti) )
115 {
116 default:
117 case MCHT_CALENDARWEEKNUM:
118 wxFAIL_MSG( "unexpected" );
119 // fall through
120
121 case MCHT_NOWHERE:
122 case MCHT_CALENDARBK:
123 case MCHT_TITLEBK:
124 case MCHT_TITLEMONTH:
125 case MCHT_TITLEYEAR:
126 return wxCAL_HITTEST_NOWHERE;
127
128 case MCHT_CALENDARDATE:
129 if ( date )
130 wxMSWDateControls::FromSystemTime(date, hti.st);
131 return wxCAL_HITTEST_DAY;
132
133 case MCHT_CALENDARDAY:
134 if ( wd )
135 {
136 *wd = wx_static_cast(wxDateTime::WeekDay, hti.st.wDayOfWeek);
137 }
138 return wxCAL_HITTEST_HEADER;
139
140 case MCHT_TITLEBTNNEXT:
141 return wxCAL_HITTEST_INCMONTH;
142
143 case MCHT_TITLEBTNPREV:
144 return wxCAL_HITTEST_DECMONTH;
145
146 case MCHT_CALENDARDATENEXT:
147 case MCHT_CALENDARDATEPREV:
148 return wxCAL_HITTEST_SURROUNDING_WEEK;
149 }
150 }
151
152 // ----------------------------------------------------------------------------
153 // wxCalendarCtrl operations
154 // ----------------------------------------------------------------------------
155
156 bool wxCalendarCtrl::SetDate(const wxDateTime& dt)
157 {
158 wxCHECK_MSG( dt.IsValid(), false, "invalid date" );
159
160 SYSTEMTIME st;
161 wxMSWDateControls::ToSystemTime(&st, dt);
162 if ( !MonthCal_SetCurSel(GetHwnd(), &st) )
163 {
164 wxLogDebug(_T("DateTime_SetSystemtime() failed"));
165
166 return false;
167 }
168
169 return true;
170 }
171
172 wxDateTime wxCalendarCtrl::GetDate() const
173 {
174 SYSTEMTIME st;
175 if ( !MonthCal_GetCurSel(GetHwnd(), &st) )
176 return wxDefaultDateTime;
177
178 wxDateTime dt;
179 wxMSWDateControls::FromSystemTime(&dt, st);
180 return dt;
181 }
182
183 bool wxCalendarCtrl::SetDateRange(const wxDateTime& dt1, const wxDateTime& dt2)
184 {
185 SYSTEMTIME st[2];
186
187 DWORD flags = 0;
188 if ( dt1.IsValid() )
189 {
190 wxMSWDateControls::ToSystemTime(&st[0], dt1);
191 flags |= GDTR_MIN;
192 }
193
194 if ( dt2.IsValid() )
195 {
196 wxMSWDateControls::ToSystemTime(&st[1], dt2);
197 flags |= GDTR_MAX;
198 }
199
200 if ( !MonthCal_SetRange(GetHwnd(), flags, st) )
201 {
202 wxLogDebug(_T("MonthCal_SetRange() failed"));
203 }
204
205 return flags != 0;
206 }
207
208 bool wxCalendarCtrl::GetDateRange(wxDateTime *dt1, wxDateTime *dt2) const
209 {
210 SYSTEMTIME st[2];
211
212 DWORD flags = MonthCal_GetRange(GetHwnd(), st);
213 if ( dt1 )
214 {
215 if ( flags & GDTR_MIN )
216 wxMSWDateControls::FromSystemTime(dt1, st[0]);
217 else
218 *dt1 = wxDefaultDateTime;
219 }
220
221 if ( dt2 )
222 {
223 if ( flags & GDTR_MAX )
224 wxMSWDateControls::FromSystemTime(dt2, st[1]);
225 else
226 *dt2 = wxDefaultDateTime;
227 }
228
229 return flags != 0;
230 }
231
232 // ----------------------------------------------------------------------------
233 // other wxCalendarCtrl operations
234 // ----------------------------------------------------------------------------
235
236 bool wxCalendarCtrl::EnableMonthChange(bool enable)
237 {
238 if ( !wxCalendarCtrlBase::EnableMonthChange(enable) )
239 return false;
240
241 wxDateTime dtStart, dtEnd;
242 if ( !enable )
243 {
244 dtStart = GetDate();
245 dtStart.SetDay(1);
246
247 dtEnd = dtStart.GetLastMonthDay();
248 }
249 //else: leave them invalid to remove the restriction
250
251 SetDateRange(dtStart, dtEnd);
252
253 return true;
254 }
255
256 void wxCalendarCtrl::Mark(size_t day, bool mark)
257 {
258 wxFAIL_MSG( "not implemented" );
259 }
260
261 // ----------------------------------------------------------------------------
262 // wxCalendarCtrl events
263 // ----------------------------------------------------------------------------
264
265 bool wxCalendarCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
266 {
267 NMHDR* hdr = (NMHDR *)lParam;
268 switch ( hdr->code )
269 {
270 case MCN_SELECT:
271 NMSELCHANGE *sch = (NMSELCHANGE *)hdr;
272 GenerateEvent(wxEVT_CALENDAR_SEL_CHANGED);
273 *result = 0;
274 return true;
275 }
276
277 return wxCalendarCtrlBase::MSWOnNotify(idCtrl, lParam, result);
278 }
279
280 #endif // wxUSE_CALENDARCTRL