]> git.saurik.com Git - wxWidgets.git/blame - src/msw/datectrl.cpp
make sure all wxDefault* and all wxNull* global instances are documented
[wxWidgets.git] / src / msw / datectrl.cpp
CommitLineData
feb72429 1/////////////////////////////////////////////////////////////////////////////
02e05e7e 2// Name: src/msw/datectrl.cpp
feb72429
VZ
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
02e05e7e
WS
26#if wxUSE_DATEPICKCTRL
27
feb72429 28#ifndef WX_PRECOMP
57bd4c60
WS
29 #include "wx/msw/wrapwin.h"
30 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
02e05e7e
WS
31 #include "wx/app.h"
32 #include "wx/intl.h"
33 #include "wx/dcclient.h"
02e05e7e 34 #include "wx/msw/private.h"
feb72429
VZ
35#endif
36
37#include "wx/datectrl.h"
51317496
VZ
38
39#include "wx/msw/private/datecontrols.h"
feb72429
VZ
40
41#define _WX_DEFINE_DATE_EVENTS_
42#include "wx/dateevt.h"
43
3200f37d
VZ
44// apparently some versions of mingw define these macros erroneously
45#ifndef DateTime_GetSystemtime
46 #define DateTime_GetSystemtime DateTime_GetSystemTime
47#endif
48
49#ifndef DateTime_SetSystemtime
50 #define DateTime_SetSystemtime DateTime_SetSystemTime
65ab1002
JS
51#endif
52
a69e2a0a
VZ
53IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl, wxControl)
54
feb72429
VZ
55// ============================================================================
56// implementation
57// ============================================================================
58
feb72429
VZ
59// ----------------------------------------------------------------------------
60// wxDatePickerCtrl creation
61// ----------------------------------------------------------------------------
62
63bool
64wxDatePickerCtrl::Create(wxWindow *parent,
65 wxWindowID id,
66 const wxDateTime& dt,
67 const wxPoint& pos,
68 const wxSize& size,
69 long style,
70 const wxValidator& validator,
71 const wxString& name)
72{
51317496
VZ
73 if ( !wxMSWDateControls::CheckInitialization() )
74 return false;
0aa7cb54 75
5385747e
VZ
76 // use wxDP_SPIN if wxDP_DEFAULT (0) was given as style
77 if ( !(style & wxDP_DROPDOWN) )
78 style |= wxDP_SPIN;
79
feb72429
VZ
80 // initialize the base class
81 if ( !CreateControl(parent, id, pos, size, style, validator, name) )
82 return false;
83
84 // create the native control
f31a4098 85 if ( !MSWCreateControl(DATETIMEPICK_CLASS, wxEmptyString, pos, size) )
feb72429
VZ
86 return false;
87
bab3f3ea 88 if ( dt.IsValid() || (style & wxDP_ALLOWNONE) )
feb72429 89 SetValue(dt);
4d536421
RD
90 else
91 SetValue(wxDateTime::Today());
feb72429
VZ
92
93 return true;
94}
95
96WXDWORD wxDatePickerCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
97{
98 WXDWORD styleMSW = wxDatePickerCtrlBase::MSWGetStyle(style, exstyle);
99
0aa7cb54
VZ
100 // although MSDN doesn't mention it, DTS_UPDOWN doesn't work with
101 // comctl32.dll 4.72
2a1f999f 102 if ( wxApp::GetComCtl32Version() > 472 && (style & wxDP_SPIN) )
29c86948
VZ
103 styleMSW |= DTS_UPDOWN;
104 //else: drop down by default
105
2cfbeac8
VZ
106#ifdef DTS_SHORTDATECENTURYFORMAT
107 if ( style & wxDP_SHOWCENTURY )
108 styleMSW |= DTS_SHORTDATECENTURYFORMAT;
109 else
110#endif // DTS_SHORTDATECENTURYFORMAT
111 styleMSW |= DTS_SHORTDATEFORMAT;
feb72429 112
3200f37d
VZ
113 if ( style & wxDP_ALLOWNONE )
114 styleMSW |= DTS_SHOWNONE;
115
feb72429
VZ
116 return styleMSW;
117}
118
119// TODO: handle WM_WININICHANGE
120
121// ----------------------------------------------------------------------------
122// wxDatePickerCtrl geometry
123// ----------------------------------------------------------------------------
124
125wxSize wxDatePickerCtrl::DoGetBestSize() const
126{
c01359d9
VZ
127 wxClientDC dc(wx_const_cast(wxDatePickerCtrl *, this));
128 dc.SetFont(GetFont());
feb72429 129
c01359d9
VZ
130 // we can't use FormatDate() here as the CRT doesn't always use the same
131 // format as the date picker control
132 wxString s;
133 for ( int len = 100; ; len *= 2 )
134 {
135 if ( ::GetDateFormat
136 (
137 LOCALE_USER_DEFAULT, // the control should use the same
138 DATE_SHORTDATE, // the format used by the control
139 NULL, // use current date (we don't care)
140 NULL, // no custom format
141 wxStringBuffer(s, len), // output buffer
142 len // and its length
143 ) )
144 {
145 // success
146 break;
147 }
148
149 const DWORD rc = ::GetLastError();
150 if ( rc != ERROR_INSUFFICIENT_BUFFER )
151 {
152 wxLogApiError(_T("GetDateFormat"), rc);
153
154 // fall back on wxDateTime, what else to do?
155 s = wxDateTime::Today().FormatDate();
156 break;
157 }
158 }
159
160 // the control adds a lot of extra space around separators
161 s.Replace(_T(","), _T(" , "));
162
163 int x, y;
164 dc.GetTextExtent(s, &x, &y);
165
166 wxSize best(x + 40 /* margin + arrows */, EDIT_HEIGHT_FROM_CHAR_HEIGHT(y));
31582e4e
RD
167 CacheBestSize(best);
168 return best;
feb72429
VZ
169}
170
171// ----------------------------------------------------------------------------
172// wxDatePickerCtrl operations
173// ----------------------------------------------------------------------------
174
175void wxDatePickerCtrl::SetValue(const wxDateTime& dt)
176{
3200f37d
VZ
177 wxCHECK_RET( dt.IsValid() || HasFlag(wxDP_ALLOWNONE),
178 _T("this control requires a valid date") );
feb72429
VZ
179
180 SYSTEMTIME st;
3200f37d 181 if ( dt.IsValid() )
51317496 182 wxMSWDateControls::ToSystemTime(&st, dt);
3200f37d
VZ
183 if ( !DateTime_SetSystemtime(GetHwnd(),
184 dt.IsValid() ? GDT_VALID : GDT_NONE,
185 &st) )
feb72429
VZ
186 {
187 wxLogDebug(_T("DateTime_SetSystemtime() failed"));
188 }
e4164aa9 189
5541976c
VZ
190 // we need to keep only the date part, times don't make sense for this
191 // control (in particular, comparisons with other dates would fail)
28039907 192 m_date = dt;
0bdd8074
VZ
193 if ( m_date.IsValid() )
194 m_date.ResetTime();
feb72429
VZ
195}
196
197wxDateTime wxDatePickerCtrl::GetValue() const
198{
e4164aa9 199#ifdef __WXDEBUG__
feb72429
VZ
200 wxDateTime dt;
201 SYSTEMTIME st;
202 if ( DateTime_GetSystemtime(GetHwnd(), &st) == GDT_VALID )
203 {
51317496 204 wxMSWDateControls::FromSystemTime(&dt, st);
feb72429
VZ
205 }
206
e4164aa9
VZ
207 wxASSERT_MSG( m_date.IsValid() == dt.IsValid() &&
208 (!dt.IsValid() || dt == m_date),
209 _T("bug in wxDatePickerCtrl: m_date not in sync") );
210#endif // __WXDEBUG__
211
212 return m_date;
feb72429
VZ
213}
214
215void wxDatePickerCtrl::SetRange(const wxDateTime& dt1, const wxDateTime& dt2)
216{
217 SYSTEMTIME st[2];
218
219 DWORD flags = 0;
220 if ( dt1.IsValid() )
221 {
51317496 222 wxMSWDateControls::ToSystemTime(&st[0], dt1);
feb72429
VZ
223 flags |= GDTR_MIN;
224 }
225
226 if ( dt2.IsValid() )
227 {
51317496 228 wxMSWDateControls::ToSystemTime(&st[1], dt2);
feb72429
VZ
229 flags |= GDTR_MAX;
230 }
231
232 if ( !DateTime_SetRange(GetHwnd(), flags, st) )
233 {
234 wxLogDebug(_T("DateTime_SetRange() failed"));
235 }
236}
237
238bool wxDatePickerCtrl::GetRange(wxDateTime *dt1, wxDateTime *dt2) const
239{
240 SYSTEMTIME st[2];
241
242 DWORD flags = DateTime_GetRange(GetHwnd(), st);
243 if ( dt1 )
244 {
245 if ( flags & GDTR_MIN )
51317496 246 wxMSWDateControls::FromSystemTime(dt1, st[0]);
feb72429
VZ
247 else
248 *dt1 = wxDefaultDateTime;
249 }
250
251 if ( dt2 )
252 {
253 if ( flags & GDTR_MAX )
51317496 254 wxMSWDateControls::FromSystemTime(dt2, st[1]);
feb72429
VZ
255 else
256 *dt2 = wxDefaultDateTime;
257 }
258
259 return flags != 0;
260}
261
262// ----------------------------------------------------------------------------
263// wxDatePickerCtrl events
264// ----------------------------------------------------------------------------
265
266bool
267wxDatePickerCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
268{
269 NMHDR* hdr = (NMHDR *)lParam;
270 switch ( hdr->code )
271 {
272 case DTN_DATETIMECHANGE:
b4446c24 273 {
feb72429
VZ
274 NMDATETIMECHANGE *dtch = (NMDATETIMECHANGE *)hdr;
275 wxDateTime dt;
276 if ( dtch->dwFlags == GDT_VALID )
51317496 277 wxMSWDateControls::FromSystemTime(&dt, dtch->st);
feb72429 278
e4164aa9
VZ
279 // filter out duplicate DTN_DATETIMECHANGE events which the native
280 // control sends us when using wxDP_DROPDOWN style
0c8433d0
VZ
281 if ( (m_date.IsValid() != dt.IsValid()) ||
282 (m_date.IsValid() && dt != m_date) )
feb72429 283 {
e4164aa9
VZ
284 m_date = dt;
285 wxDateEvent event(this, dt, wxEVT_DATE_CHANGED);
937013e0 286 if ( HandleWindowEvent(event) )
e4164aa9
VZ
287 {
288 *result = 0;
289 return true;
290 }
feb72429 291 }
0c8433d0 292 //else: both the old and new values are invalid, nothing changed
b4446c24 293 }
feb72429
VZ
294 }
295
296 return wxDatePickerCtrlBase::MSWOnNotify(idCtrl, lParam, result);
297}
298
9b877d18 299#endif // wxUSE_DATEPICKCTRL