1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/datectrl.cpp
3 // Purpose: wxDatePickerCtrl implementation
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2005 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
25 #if wxUSE_DATEPICKCTRL
28 #include "wx/msw/wrapwin.h"
29 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
32 #include "wx/dcclient.h"
33 #include "wx/settings.h"
34 #include "wx/msw/private.h"
37 #include "wx/datectrl.h"
38 #include "wx/dateevt.h"
40 IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl
, wxControl
)
42 // ============================================================================
44 // ============================================================================
46 // ----------------------------------------------------------------------------
47 // wxDatePickerCtrl creation
48 // ----------------------------------------------------------------------------
51 wxDatePickerCtrl::Create(wxWindow
*parent
,
57 const wxValidator
& validator
,
60 // use wxDP_SPIN if wxDP_DEFAULT (0) was given as style
61 if ( !(style
& wxDP_DROPDOWN
) )
64 return MSWCreateDateTimePicker(parent
, id
, dt
,
69 WXDWORD
wxDatePickerCtrl::MSWGetStyle(long style
, WXDWORD
*exstyle
) const
71 WXDWORD styleMSW
= wxDatePickerCtrlBase::MSWGetStyle(style
, exstyle
);
73 // although MSDN doesn't mention it, DTS_UPDOWN doesn't work with
75 if ( wxApp::GetComCtl32Version() > 472 && (style
& wxDP_SPIN
) )
76 styleMSW
|= DTS_UPDOWN
;
77 //else: drop down by default
79 #ifdef DTS_SHORTDATECENTURYFORMAT
80 if ( style
& wxDP_SHOWCENTURY
)
81 styleMSW
|= DTS_SHORTDATECENTURYFORMAT
;
83 #endif // DTS_SHORTDATECENTURYFORMAT
84 styleMSW
|= DTS_SHORTDATEFORMAT
;
86 if ( style
& wxDP_ALLOWNONE
)
87 styleMSW
|= DTS_SHOWNONE
;
92 // TODO: handle WM_WININICHANGE
94 wxLocaleInfo
wxDatePickerCtrl::MSWGetFormat() const
96 return wxLOCALE_SHORT_DATE_FMT
;
99 // ----------------------------------------------------------------------------
100 // wxDatePickerCtrl operations
101 // ----------------------------------------------------------------------------
103 void wxDatePickerCtrl::SetValue(const wxDateTime
& dt
)
107 // Don't try setting the date if it's out of range: calendar control
108 // under XP (and presumably all the other pre-Vista Windows versions)
109 // doesn't return false from DateTime_SetSystemtime() in this case but
110 // doesn't actually change the date, so we can't update our m_date
111 // unconditionally and would need to check whether it was changed
112 // before doing it. It looks simpler to just check whether it's in
113 // range here instead.
115 // If we ever drop support for XP we could rely on the return value of
116 // DateTime_SetSystemtime() but this probably won't happen in near
118 wxDateTime dtStart
, dtEnd
;
119 GetRange(&dtStart
, &dtEnd
);
120 if ( (dtStart
.IsValid() && dt
< dtStart
) ||
121 (dtEnd
.IsValid() && dt
> dtEnd
) )
123 // Fail silently, some existing code relies on SetValue() with an
124 // out of range value simply doing nothing -- so don't.
129 wxDateTimePickerCtrl::SetValue(dt
);
131 // we need to keep only the date part, times don't make sense for this
132 // control (in particular, comparisons with other dates would fail)
133 if ( m_date
.IsValid() )
137 wxDateTime
wxDatePickerCtrl::GetValue() const
142 if ( DateTime_GetSystemtime(GetHwnd(), &st
) == GDT_VALID
)
144 dt
.SetFromMSWSysDate(st
);
147 wxASSERT_MSG( m_date
.IsValid() == dt
.IsValid() &&
148 (!dt
.IsValid() || dt
== m_date
),
149 wxT("bug in wxDateTimePickerCtrl: m_date not in sync") );
150 #endif // wxDEBUG_LEVEL
152 return wxDateTimePickerCtrl::GetValue();
155 void wxDatePickerCtrl::SetRange(const wxDateTime
& dt1
, const wxDateTime
& dt2
)
162 dt1
.GetAsMSWSysTime(st
+ 0);
168 dt2
.GetAsMSWSysTime(st
+ 1);
172 if ( !DateTime_SetRange(GetHwnd(), flags
, st
) )
174 wxLogDebug(wxT("DateTime_SetRange() failed"));
178 bool wxDatePickerCtrl::GetRange(wxDateTime
*dt1
, wxDateTime
*dt2
) const
182 DWORD flags
= DateTime_GetRange(GetHwnd(), st
);
185 if ( flags
& GDTR_MIN
)
186 dt1
->SetFromMSWSysDate(st
[0]);
188 *dt1
= wxDefaultDateTime
;
193 if ( flags
& GDTR_MAX
)
194 dt2
->SetFromMSWSysDate(st
[1]);
196 *dt2
= wxDefaultDateTime
;
202 // ----------------------------------------------------------------------------
203 // wxDatePickerCtrl events
204 // ----------------------------------------------------------------------------
206 bool wxDatePickerCtrl::MSWOnDateTimeChange(const NMDATETIMECHANGE
& dtch
)
209 if ( dtch
.dwFlags
== GDT_VALID
)
210 dt
.SetFromMSWSysDate(dtch
.st
);
212 // filter out duplicate DTN_DATETIMECHANGE events which the native
213 // control sends us when using wxDP_DROPDOWN style
214 if ( (m_date
.IsValid() == dt
.IsValid()) &&
215 (!m_date
.IsValid() || dt
== m_date
) )
219 wxDateEvent
event(this, dt
, wxEVT_DATE_CHANGED
);
220 return HandleWindowEvent(event
);
223 #endif // wxUSE_DATEPICKCTRL