1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/datectrl.cpp
3 // Purpose: wxDatePickerCtrl implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2005 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
29 #if wxUSE_DATEPICKCTRL
31 #include "wx/datectrl.h"
34 #include "wx/dynlib.h"
36 #define _WX_DEFINE_DATE_EVENTS_
37 #include "wx/dateevt.h"
39 #include "wx/msw/wrapwin.h"
40 #include "wx/msw/wrapcctl.h"
41 #include "wx/msw/private.h"
43 #if defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 2, 4 )
44 typedef struct tagNMDATETIMECHANGE
50 #endif // old gcc headers
52 // apparently some versions of mingw define these macros erroneously
53 #ifndef DateTime_GetSystemtime
54 #define DateTime_GetSystemtime DateTime_GetSystemTime
57 #ifndef DateTime_SetSystemtime
58 #define DateTime_SetSystemtime DateTime_SetSystemTime
61 IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl
, wxControl
)
63 // ============================================================================
65 // ============================================================================
67 // ----------------------------------------------------------------------------
68 // helpers for wxDateTime <-> SYSTEMTIME conversion
69 // ----------------------------------------------------------------------------
71 static inline void wxFromSystemTime(wxDateTime
*dt
, const SYSTEMTIME
& st
)
74 wx_static_cast(wxDateTime::Month
, wxDateTime::Jan
+ st
.wMonth
- 1),
79 static inline void wxToSystemTime(SYSTEMTIME
*st
, const wxDateTime
& dt
)
81 const wxDateTime::Tm
tm(dt
.GetTm());
83 st
->wYear
= (WXWORD
)tm
.year
;
84 st
->wMonth
= (WXWORD
)(tm
.mon
- wxDateTime::Jan
+ 1);
91 st
->wMilliseconds
= 0;
94 // ----------------------------------------------------------------------------
95 // wxDatePickerCtrl creation
96 // ----------------------------------------------------------------------------
99 wxDatePickerCtrl::Create(wxWindow
*parent
,
101 const wxDateTime
& dt
,
105 const wxValidator
& validator
,
106 const wxString
& name
)
108 // although we already call InitCommonControls() in app.cpp which is
109 // supposed to initialize all common controls, in comctl32.dll 4.72 (and
110 // presumably earlier versions 4.70 and 4.71, date time picker not being
111 // supported in < 4.70 anyhow) it does not do it and we have to initialize
113 static bool s_initDone
= false; // MT-ok: used from GUI thread only
116 if ( wxTheApp
->GetComCtl32Version() < 470 )
118 wxLogError(_("This system doesn't support date picker control, please upgrade your version of comctl32.dll"));
123 INITCOMMONCONTROLSEX icex
;
124 icex
.dwSize
= sizeof(icex
);
125 icex
.dwICC
= ICC_DATE_CLASSES
;
127 wxDynamicLibrary
dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM
);
129 typedef BOOL (WINAPI
*ICCEx_t
)(INITCOMMONCONTROLSEX
*);
130 wxDYNLIB_FUNCTION( ICCEx_t
, InitCommonControlsEx
, dllComCtl32
);
132 if ( pfnInitCommonControlsEx
)
134 (*pfnInitCommonControlsEx
)(&icex
);
141 // use wxDP_SPIN if wxDP_DEFAULT (0) was given as style
142 if ( !(style
& wxDP_DROPDOWN
) )
145 // initialize the base class
146 if ( !CreateControl(parent
, id
, pos
, size
, style
, validator
, name
) )
149 // create the native control
150 if ( !MSWCreateControl(DATETIMEPICK_CLASS
, wxEmptyString
, pos
, size
) )
159 WXDWORD
wxDatePickerCtrl::MSWGetStyle(long style
, WXDWORD
*exstyle
) const
161 WXDWORD styleMSW
= wxDatePickerCtrlBase::MSWGetStyle(style
, exstyle
);
163 // although MSDN doesn't mention it, DTS_UPDOWN doesn't work with
165 if ( wxTheApp
->GetComCtl32Version() > 472 && (style
& wxDP_SPIN
) )
166 styleMSW
|= DTS_UPDOWN
;
167 //else: drop down by default
169 #ifdef DTS_SHORTDATECENTURYFORMAT
170 if ( style
& wxDP_SHOWCENTURY
)
171 styleMSW
|= DTS_SHORTDATECENTURYFORMAT
;
173 #endif // DTS_SHORTDATECENTURYFORMAT
174 styleMSW
|= DTS_SHORTDATEFORMAT
;
176 if ( style
& wxDP_ALLOWNONE
)
177 styleMSW
|= DTS_SHOWNONE
;
182 // TODO: handle WM_WININICHANGE
184 // ----------------------------------------------------------------------------
185 // wxDatePickerCtrl geometry
186 // ----------------------------------------------------------------------------
188 wxSize
wxDatePickerCtrl::DoGetBestSize() const
190 const int y
= GetCharHeight();
192 return wxSize(DEFAULT_ITEM_WIDTH
, EDIT_HEIGHT_FROM_CHAR_HEIGHT(y
));
195 // ----------------------------------------------------------------------------
196 // wxDatePickerCtrl operations
197 // ----------------------------------------------------------------------------
199 void wxDatePickerCtrl::SetValue(const wxDateTime
& dt
)
201 wxCHECK_RET( dt
.IsValid() || HasFlag(wxDP_ALLOWNONE
),
202 _T("this control requires a valid date") );
206 wxToSystemTime(&st
, dt
);
207 if ( !DateTime_SetSystemtime(GetHwnd(),
208 dt
.IsValid() ? GDT_VALID
: GDT_NONE
,
211 wxLogDebug(_T("DateTime_SetSystemtime() failed"));
215 wxDateTime
wxDatePickerCtrl::GetValue() const
219 if ( DateTime_GetSystemtime(GetHwnd(), &st
) == GDT_VALID
)
221 wxFromSystemTime(&dt
, st
);
227 void wxDatePickerCtrl::SetRange(const wxDateTime
& dt1
, const wxDateTime
& dt2
)
234 wxToSystemTime(&st
[0], dt1
);
240 wxToSystemTime(&st
[1], dt2
);
244 if ( !DateTime_SetRange(GetHwnd(), flags
, st
) )
246 wxLogDebug(_T("DateTime_SetRange() failed"));
250 bool wxDatePickerCtrl::GetRange(wxDateTime
*dt1
, wxDateTime
*dt2
) const
254 DWORD flags
= DateTime_GetRange(GetHwnd(), st
);
257 if ( flags
& GDTR_MIN
)
258 wxFromSystemTime(dt1
, st
[0]);
260 *dt1
= wxDefaultDateTime
;
265 if ( flags
& GDTR_MAX
)
266 wxFromSystemTime(dt2
, st
[1]);
268 *dt2
= wxDefaultDateTime
;
274 // ----------------------------------------------------------------------------
275 // wxDatePickerCtrl events
276 // ----------------------------------------------------------------------------
279 wxDatePickerCtrl::MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM
*result
)
281 NMHDR
* hdr
= (NMHDR
*)lParam
;
284 case DTN_DATETIMECHANGE
:
285 NMDATETIMECHANGE
*dtch
= (NMDATETIMECHANGE
*)hdr
;
287 if ( dtch
->dwFlags
== GDT_VALID
)
288 wxFromSystemTime(&dt
, dtch
->st
);
290 wxDateEvent
event(this, dt
, wxEVT_DATE_CHANGED
);
291 if ( GetEventHandler()->ProcessEvent(event
) )
298 return wxDatePickerCtrlBase::MSWOnNotify(idCtrl
, lParam
, result
);
301 #endif // wxUSE_DATEPICKCTRL