]> git.saurik.com Git - wxWidgets.git/blame - src/msw/datectrl.cpp
Separated out book control sizing code
[wxWidgets.git] / src / msw / datectrl.cpp
CommitLineData
feb72429
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: msw/datectrl.cpp
3// Purpose: wxDatePickerCtrl implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 2005-01-09
7// RCS-ID: $Id$
8// Copyright: (c) 2005 Vadim Zeitlin <vadim@wxwindows.org>
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27#endif
28
9b877d18
WS
29#if wxUSE_DATEPICKCTRL
30
feb72429 31#include "wx/datectrl.h"
0aa7cb54
VZ
32#include "wx/app.h"
33#include "wx/intl.h"
34#include "wx/dynlib.h"
feb72429
VZ
35
36#define _WX_DEFINE_DATE_EVENTS_
37#include "wx/dateevt.h"
38
39#include "wx/msw/wrapwin.h"
40#include "wx/msw/wrapcctl.h"
4510fc80 41#include "wx/msw/private.h"
feb72429 42
3200f37d
VZ
43// apparently some versions of mingw define these macros erroneously
44#ifndef DateTime_GetSystemtime
45 #define DateTime_GetSystemtime DateTime_GetSystemTime
46#endif
47
48#ifndef DateTime_SetSystemtime
49 #define DateTime_SetSystemtime DateTime_SetSystemTime
65ab1002
JS
50#endif
51
a69e2a0a
VZ
52IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl, wxControl)
53
feb72429
VZ
54// ============================================================================
55// implementation
56// ============================================================================
57
58// ----------------------------------------------------------------------------
59// helpers for wxDateTime <-> SYSTEMTIME conversion
60// ----------------------------------------------------------------------------
61
62static inline void wxFromSystemTime(wxDateTime *dt, const SYSTEMTIME& st)
63{
64 dt->Set(st.wDay,
65 wx_static_cast(wxDateTime::Month, wxDateTime::Jan + st.wMonth - 1),
66 st.wYear,
67 0, 0, 0);
68}
69
70static inline void wxToSystemTime(SYSTEMTIME *st, const wxDateTime& dt)
71{
72 const wxDateTime::Tm tm(dt.GetTm());
73
3a0c6181
WS
74 st->wYear = (WXWORD)tm.year;
75 st->wMonth = (WXWORD)(tm.mon - wxDateTime::Jan + 1);
feb72429
VZ
76 st->wDay = tm.mday;
77
78 st->wDayOfWeek =
79 st->wHour =
80 st->wMinute =
81 st->wSecond =
82 st->wMilliseconds = 0;
83}
84
85// ----------------------------------------------------------------------------
86// wxDatePickerCtrl creation
87// ----------------------------------------------------------------------------
88
89bool
90wxDatePickerCtrl::Create(wxWindow *parent,
91 wxWindowID id,
92 const wxDateTime& dt,
93 const wxPoint& pos,
94 const wxSize& size,
95 long style,
96 const wxValidator& validator,
97 const wxString& name)
98{
0aa7cb54
VZ
99 // although we already call InitCommonControls() in app.cpp which is
100 // supposed to initialize all common controls, in comctl32.dll 4.72 (and
101 // presumably earlier versions 4.70 and 4.71, date time picker not being
102 // supported in < 4.70 anyhow) it does not do it and we have to initialize
3103e8a9 103 // it explicitly
0aa7cb54
VZ
104 static bool s_initDone = false; // MT-ok: used from GUI thread only
105 if ( !s_initDone )
106 {
2a1f999f 107 if ( wxApp::GetComCtl32Version() < 470 )
0aa7cb54
VZ
108 {
109 wxLogError(_("This system doesn't support date picker control, please upgrade your version of comctl32.dll"));
110
111 return false;
112 }
113
64c288fa 114#if wxUSE_DYNLIB_CLASS
0aa7cb54
VZ
115 INITCOMMONCONTROLSEX icex;
116 icex.dwSize = sizeof(icex);
117 icex.dwICC = ICC_DATE_CLASSES;
118
119 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
120
121 typedef BOOL (WINAPI *ICCEx_t)(INITCOMMONCONTROLSEX *);
122 wxDYNLIB_FUNCTION( ICCEx_t, InitCommonControlsEx, dllComCtl32 );
123
124 if ( pfnInitCommonControlsEx )
125 {
126 (*pfnInitCommonControlsEx)(&icex);
127 }
128
129 s_initDone = true;
64c288fa 130#endif
0aa7cb54
VZ
131 }
132
133
5385747e
VZ
134 // use wxDP_SPIN if wxDP_DEFAULT (0) was given as style
135 if ( !(style & wxDP_DROPDOWN) )
136 style |= wxDP_SPIN;
137
feb72429
VZ
138 // initialize the base class
139 if ( !CreateControl(parent, id, pos, size, style, validator, name) )
140 return false;
141
142 // create the native control
f31a4098 143 if ( !MSWCreateControl(DATETIMEPICK_CLASS, wxEmptyString, pos, size) )
feb72429
VZ
144 return false;
145
bab3f3ea 146 if ( dt.IsValid() || (style & wxDP_ALLOWNONE) )
feb72429
VZ
147 SetValue(dt);
148
149 return true;
150}
151
152WXDWORD wxDatePickerCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
153{
154 WXDWORD styleMSW = wxDatePickerCtrlBase::MSWGetStyle(style, exstyle);
155
0aa7cb54
VZ
156 // although MSDN doesn't mention it, DTS_UPDOWN doesn't work with
157 // comctl32.dll 4.72
2a1f999f 158 if ( wxApp::GetComCtl32Version() > 472 && (style & wxDP_SPIN) )
29c86948
VZ
159 styleMSW |= DTS_UPDOWN;
160 //else: drop down by default
161
2cfbeac8
VZ
162#ifdef DTS_SHORTDATECENTURYFORMAT
163 if ( style & wxDP_SHOWCENTURY )
164 styleMSW |= DTS_SHORTDATECENTURYFORMAT;
165 else
166#endif // DTS_SHORTDATECENTURYFORMAT
167 styleMSW |= DTS_SHORTDATEFORMAT;
feb72429 168
3200f37d
VZ
169 if ( style & wxDP_ALLOWNONE )
170 styleMSW |= DTS_SHOWNONE;
171
feb72429
VZ
172 return styleMSW;
173}
174
175// TODO: handle WM_WININICHANGE
176
177// ----------------------------------------------------------------------------
178// wxDatePickerCtrl geometry
179// ----------------------------------------------------------------------------
180
181wxSize wxDatePickerCtrl::DoGetBestSize() const
182{
183 const int y = GetCharHeight();
184
31582e4e
RD
185 wxSize best(DEFAULT_ITEM_WIDTH, EDIT_HEIGHT_FROM_CHAR_HEIGHT(y));
186 CacheBestSize(best);
187 return best;
feb72429
VZ
188}
189
190// ----------------------------------------------------------------------------
191// wxDatePickerCtrl operations
192// ----------------------------------------------------------------------------
193
194void wxDatePickerCtrl::SetValue(const wxDateTime& dt)
195{
3200f37d
VZ
196 wxCHECK_RET( dt.IsValid() || HasFlag(wxDP_ALLOWNONE),
197 _T("this control requires a valid date") );
feb72429
VZ
198
199 SYSTEMTIME st;
3200f37d
VZ
200 if ( dt.IsValid() )
201 wxToSystemTime(&st, dt);
202 if ( !DateTime_SetSystemtime(GetHwnd(),
203 dt.IsValid() ? GDT_VALID : GDT_NONE,
204 &st) )
feb72429
VZ
205 {
206 wxLogDebug(_T("DateTime_SetSystemtime() failed"));
207 }
208}
209
210wxDateTime wxDatePickerCtrl::GetValue() const
211{
212 wxDateTime dt;
213 SYSTEMTIME st;
214 if ( DateTime_GetSystemtime(GetHwnd(), &st) == GDT_VALID )
215 {
216 wxFromSystemTime(&dt, st);
217 }
218
219 return dt;
220}
221
222void wxDatePickerCtrl::SetRange(const wxDateTime& dt1, const wxDateTime& dt2)
223{
224 SYSTEMTIME st[2];
225
226 DWORD flags = 0;
227 if ( dt1.IsValid() )
228 {
229 wxToSystemTime(&st[0], dt1);
230 flags |= GDTR_MIN;
231 }
232
233 if ( dt2.IsValid() )
234 {
235 wxToSystemTime(&st[1], dt2);
236 flags |= GDTR_MAX;
237 }
238
239 if ( !DateTime_SetRange(GetHwnd(), flags, st) )
240 {
241 wxLogDebug(_T("DateTime_SetRange() failed"));
242 }
243}
244
245bool wxDatePickerCtrl::GetRange(wxDateTime *dt1, wxDateTime *dt2) const
246{
247 SYSTEMTIME st[2];
248
249 DWORD flags = DateTime_GetRange(GetHwnd(), st);
250 if ( dt1 )
251 {
252 if ( flags & GDTR_MIN )
253 wxFromSystemTime(dt1, st[0]);
254 else
255 *dt1 = wxDefaultDateTime;
256 }
257
258 if ( dt2 )
259 {
260 if ( flags & GDTR_MAX )
261 wxFromSystemTime(dt2, st[1]);
262 else
263 *dt2 = wxDefaultDateTime;
264 }
265
266 return flags != 0;
267}
268
269// ----------------------------------------------------------------------------
270// wxDatePickerCtrl events
271// ----------------------------------------------------------------------------
272
273bool
274wxDatePickerCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
275{
276 NMHDR* hdr = (NMHDR *)lParam;
277 switch ( hdr->code )
278 {
279 case DTN_DATETIMECHANGE:
280 NMDATETIMECHANGE *dtch = (NMDATETIMECHANGE *)hdr;
281 wxDateTime dt;
282 if ( dtch->dwFlags == GDT_VALID )
283 wxFromSystemTime(&dt, dtch->st);
284
285 wxDateEvent event(this, dt, wxEVT_DATE_CHANGED);
286 if ( GetEventHandler()->ProcessEvent(event) )
287 {
288 *result = 0;
289 return true;
290 }
291 }
292
293 return wxDatePickerCtrlBase::MSWOnNotify(idCtrl, lParam, result);
294}
295
9b877d18 296#endif // wxUSE_DATEPICKCTRL
29c86948 297