Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/DateTime.d @ 0:6dd524f61e62
add dwt win and basic java stuff
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 02 Mar 2009 14:44:16 +0100 |
parents | |
children | 6bf2837c50fe |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6dd524f61e62 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module org.eclipse.swt.widgets.DateTime; | |
14 | |
15 import org.eclipse.swt.widgets.Composite; | |
16 import org.eclipse.swt.SWT; | |
17 import org.eclipse.swt.SWTException; | |
18 import org.eclipse.swt.events.SelectionEvent; | |
19 import org.eclipse.swt.events.SelectionListener; | |
20 import org.eclipse.swt.graphics.Point; | |
21 import org.eclipse.swt.internal.win32.OS; | |
22 | |
23 import org.eclipse.swt.widgets.TypedListener; | |
24 | |
25 import java.lang.all; | |
26 | |
27 import Integer = tango.text.convert.Integer; | |
28 import tango.text.convert.Format; | |
29 | |
30 //TODO - features not yet implemented: read-only, drop-down calendar for date | |
31 //TODO - font, colors, background image not yet implemented (works on some platforms) | |
32 | |
33 /** | |
34 * Instances of this class are selectable user interface | |
35 * objects that allow the user to enter and modify date | |
36 * or time values. | |
37 * <p> | |
38 * Note that although this class is a subclass of <code>Composite</code>, | |
39 * it does not make sense to add children to it, or set a layout on it. | |
40 * </p> | |
41 * <dl> | |
42 * <dt><b>Styles:</b></dt> | |
43 * <dd>DATE, TIME, CALENDAR, SHORT, MEDIUM, LONG</dd> | |
44 * <dt><b>Events:</b></dt> | |
45 * <dd>Selection</dd> | |
46 * </dl> | |
47 * <p> | |
48 * Note: Only one of the styles DATE, TIME, or CALENDAR may be specified, | |
49 * and only one of the styles SHORT, MEDIUM, or LONG may be specified. | |
50 * </p><p> | |
51 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
52 * </p> | |
53 * | |
54 * @see <a href="http://www.eclipse.org/swt/snippets/#datetime">DateTime snippets</a> | |
55 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a> | |
56 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
57 * | |
58 * @since 3.3 | |
59 */ | |
60 | |
61 public class DateTime : Composite { | |
62 | |
63 alias Composite.computeSize computeSize; | |
64 alias Composite.windowProc windowProc; | |
65 | |
66 bool ignoreSelection; | |
67 SYSTEMTIME* lastSystemTime; | |
68 SYSTEMTIME time; // only used in calendar mode | |
69 static /+const+/ WNDPROC DateTimeProc; | |
70 static const TCHAR[] DateTimeClass = OS.DATETIMEPICK_CLASS; | |
71 static /+const+/ WNDPROC CalendarProc; | |
72 static const TCHAR[] CalendarClass = OS.MONTHCAL_CLASS; | |
73 | |
74 private static bool static_this_completed = false; | |
75 private static void static_this() { | |
76 if( static_this_completed ){ | |
77 return; | |
78 } | |
79 synchronized { | |
80 if( static_this_completed ){ | |
81 return; | |
82 } | |
83 INITCOMMONCONTROLSEX icex; | |
84 icex.dwSize = INITCOMMONCONTROLSEX.sizeof; | |
85 icex.dwICC = OS.ICC_DATE_CLASSES; | |
86 OS.InitCommonControlsEx (&icex); | |
87 WNDCLASS lpWndClass; | |
88 OS.GetClassInfo (null, DateTimeClass.ptr, &lpWndClass); | |
89 DateTimeProc = lpWndClass.lpfnWndProc; | |
90 /* | |
91 * Feature in Windows. The date time window class | |
92 * does not include CS_DBLCLKS. This means that these | |
93 * controls will not get double click messages such as | |
94 * WM_LBUTTONDBLCLK. The fix is to register a new | |
95 * window class with CS_DBLCLKS. | |
96 * | |
97 * NOTE: Screen readers look for the exact class name | |
98 * of the control in order to provide the correct kind | |
99 * of assistance. Therefore, it is critical that the | |
100 * new window class have the same name. It is possible | |
101 * to register a local window class with the same name | |
102 * as a global class. Since bits that affect the class | |
103 * are being changed, it is possible that other native | |
104 * code, other than SWT, could create a control with | |
105 * this class name, and fail unexpectedly. | |
106 */ | |
107 auto hInstance = OS.GetModuleHandle (null); | |
108 auto hHeap = OS.GetProcessHeap (); | |
109 lpWndClass.hInstance = hInstance; | |
110 lpWndClass.style &= ~OS.CS_GLOBALCLASS; | |
111 lpWndClass.style |= OS.CS_DBLCLKS; | |
112 int byteCount = DateTimeClass.length * TCHAR.sizeof; | |
113 auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
114 OS.MoveMemory (lpszClassName, DateTimeClass.ptr, byteCount); | |
115 lpWndClass.lpszClassName = lpszClassName; | |
116 OS.RegisterClass (&lpWndClass); | |
117 OS.HeapFree (hHeap, 0, lpszClassName); | |
118 OS.GetClassInfo (null, CalendarClass.ptr, &lpWndClass); | |
119 CalendarProc = lpWndClass.lpfnWndProc; | |
120 /* | |
121 * Feature in Windows. The date time window class | |
122 * does not include CS_DBLCLKS. This means that these | |
123 * controls will not get double click messages such as | |
124 * WM_LBUTTONDBLCLK. The fix is to register a new | |
125 * window class with CS_DBLCLKS. | |
126 * | |
127 * NOTE: Screen readers look for the exact class name | |
128 * of the control in order to provide the correct kind | |
129 * of assistance. Therefore, it is critical that the | |
130 * new window class have the same name. It is possible | |
131 * to register a local window class with the same name | |
132 * as a global class. Since bits that affect the class | |
133 * are being changed, it is possible that other native | |
134 * code, other than SWT, could create a control with | |
135 * this class name, and fail unexpectedly. | |
136 */ | |
137 hInstance = OS.GetModuleHandle (null); | |
138 hHeap = OS.GetProcessHeap (); | |
139 lpWndClass.hInstance = hInstance; | |
140 lpWndClass.style &= ~OS.CS_GLOBALCLASS; | |
141 lpWndClass.style |= OS.CS_DBLCLKS; | |
142 byteCount = CalendarClass.length * TCHAR.sizeof; | |
143 lpszClassName = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
144 OS.MoveMemory (lpszClassName, CalendarClass.ptr, byteCount); | |
145 lpWndClass.lpszClassName = lpszClassName; | |
146 OS.RegisterClass (&lpWndClass); | |
147 OS.HeapFree (hHeap, 0, lpszClassName); | |
148 static_this_completed = true; | |
149 } | |
150 } | |
151 | |
152 static const int MARGIN = 4; | |
153 static const int MAX_DIGIT = 9; | |
154 static const int MAX_DAY = 31; | |
155 static const int MAX_12HOUR = 12; | |
156 static const int MAX_24HOUR = 24; | |
157 static const int MAX_MINUTE = 60; | |
158 static const int MONTH_DAY_YEAR = 0; | |
159 static const int DAY_MONTH_YEAR = 1; | |
160 static const int YEAR_MONTH_DAY = 2; | |
161 static const char SINGLE_QUOTE = '\''; //$NON-NLS-1$ short date format may include quoted text | |
162 static const char DAY_FORMAT_CONSTANT = 'd'; //$NON-NLS-1$ 1-4 lowercase 'd's represent day | |
163 static const char MONTH_FORMAT_CONSTANT = 'M'; //$NON-NLS-1$ 1-4 uppercase 'M's represent month | |
164 static const char YEAR_FORMAT_CONSTANT = 'y'; //$NON-NLS-1$ 1-5 lowercase 'y's represent year | |
165 static const char HOURS_FORMAT_CONSTANT = 'h'; //$NON-NLS-1$ 1-2 upper or lowercase 'h's represent hours | |
166 static const char MINUTES_FORMAT_CONSTANT = 'm'; //$NON-NLS-1$ 1-2 lowercase 'm's represent minutes | |
167 static const char SECONDS_FORMAT_CONSTANT = 's'; //$NON-NLS-1$ 1-2 lowercase 's's represent seconds | |
168 static const char AMPM_FORMAT_CONSTANT = 't'; //$NON-NLS-1$ 1-2 lowercase 't's represent am/pm | |
169 static const int[] MONTH_NAMES = [OS.LOCALE_SMONTHNAME1, OS.LOCALE_SMONTHNAME2, OS.LOCALE_SMONTHNAME3, OS.LOCALE_SMONTHNAME4, OS.LOCALE_SMONTHNAME5, OS.LOCALE_SMONTHNAME6, OS.LOCALE_SMONTHNAME7, OS.LOCALE_SMONTHNAME8, OS.LOCALE_SMONTHNAME9, OS.LOCALE_SMONTHNAME10, OS.LOCALE_SMONTHNAME11, OS.LOCALE_SMONTHNAME12]; | |
170 | |
171 | |
172 /** | |
173 * Constructs a new instance of this class given its parent | |
174 * and a style value describing its behavior and appearance. | |
175 * <p> | |
176 * The style value is either one of the style constants defined in | |
177 * class <code>SWT</code> which is applicable to instances of this | |
178 * class, or must be built by <em>bitwise OR</em>'ing together | |
179 * (that is, using the <code>int</code> "|" operator) two or more | |
180 * of those <code>SWT</code> style constants. The class description | |
181 * lists the style constants that are applicable to the class. | |
182 * Style bits are also inherited from superclasses. | |
183 * </p> | |
184 * | |
185 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
186 * @param style the style of control to construct | |
187 * | |
188 * @exception IllegalArgumentException <ul> | |
189 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
190 * </ul> | |
191 * @exception SWTException <ul> | |
192 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
193 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
194 * </ul> | |
195 * | |
196 * @see SWT#DATE | |
197 * @see SWT#TIME | |
198 * @see SWT#CALENDAR | |
199 * @see Widget#checkSubclass | |
200 * @see Widget#getStyle | |
201 */ | |
202 public this (Composite parent, int style) { | |
203 static_this(); | |
204 super (parent, checkStyle (style)); | |
205 if ((this.style & SWT.SHORT) !is 0) { | |
206 String buffer = ((this.style & SWT.DATE) !is 0) ? getCustomShortDateFormat() : getCustomShortTimeFormat(); | |
207 TCHAR[] lpszFormat = StrToTCHARs (0, buffer, true); | |
208 OS.SendMessage (handle, OS.DTM_SETFORMAT, 0, lpszFormat.ptr); | |
209 } | |
210 } | |
211 | |
212 /** | |
213 * Adds the listener to the collection of listeners who will | |
214 * be notified when the control is selected by the user, by sending | |
215 * it one of the messages defined in the <code>SelectionListener</code> | |
216 * interface. | |
217 * <p> | |
218 * <code>widgetSelected</code> is called when the user changes the control's value. | |
219 * <code>widgetDefaultSelected</code> is not called. | |
220 * </p> | |
221 * | |
222 * @param listener the listener which should be notified | |
223 * | |
224 * @exception IllegalArgumentException <ul> | |
225 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
226 * </ul> | |
227 * @exception SWTException <ul> | |
228 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
229 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
230 * </ul> | |
231 * | |
232 * @see SelectionListener | |
233 * @see #removeSelectionListener | |
234 * @see SelectionEvent | |
235 */ | |
236 public void addSelectionListener (SelectionListener listener) { | |
237 checkWidget (); | |
238 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
239 TypedListener typedListener = new TypedListener (listener); | |
240 addListener (SWT.Selection, typedListener); | |
241 addListener (SWT.DefaultSelection, typedListener); | |
242 } | |
243 | |
244 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { | |
245 if (handle is null) return 0; | |
246 return OS.CallWindowProc ( cast(WNDPROC)windowProc(), hwnd, msg, wParam, lParam); | |
247 } | |
248 | |
249 static int checkStyle (int style) { | |
250 /* | |
251 * Even though it is legal to create this widget | |
252 * with scroll bars, they serve no useful purpose | |
253 * because they do not automatically scroll the | |
254 * widget's client area. The fix is to clear | |
255 * the SWT style. | |
256 */ | |
257 style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); | |
258 style = checkBits (style, SWT.DATE, SWT.TIME, SWT.CALENDAR, 0, 0, 0); | |
259 return checkBits (style, SWT.MEDIUM, SWT.SHORT, SWT.LONG, 0, 0, 0); | |
260 } | |
261 | |
262 override protected void checkSubclass () { | |
263 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); | |
264 } | |
265 | |
266 override public Point computeSize (int wHint, int hHint, bool changed) { | |
267 checkWidget (); | |
268 int width = 0, height = 0; | |
269 if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) { | |
270 if ((style & SWT.CALENDAR) !is 0) { | |
271 RECT rect; | |
272 OS.SendMessage(handle, OS.MCM_GETMINREQRECT, 0, &rect); | |
273 width = rect.right; | |
274 height = rect.bottom; | |
275 } else { | |
276 TCHAR[] buffer = new TCHAR[128]; | |
277 HFONT newFont, oldFont; | |
278 auto hDC = OS.GetDC (handle); | |
279 newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); | |
280 if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); | |
281 RECT rect; | |
282 int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX; | |
283 SYSTEMTIME systime; | |
284 if ((style & SWT.DATE) !is 0) { | |
285 /* Determine the widest/tallest year string. */ | |
286 systime.wMonth = 1; | |
287 systime.wDay = 1; | |
288 int widest = 0, secondWidest = 0, thirdWidest = 0; | |
289 for (int i = 0; i <= MAX_DIGIT; i++) { | |
290 systime.wYear = cast(short) (2000 + i); // year 2000 + i is guaranteed to exist | |
291 int size = OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, OS.DATE_SHORTDATE, &systime, null, buffer.ptr, buffer.length); | |
292 if (size is 0) { | |
293 buffer = new TCHAR[size]; | |
294 OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, OS.DATE_SHORTDATE, &systime, null, buffer.ptr, buffer.length); | |
295 } | |
296 rect.left = rect.top = rect.right = rect.bottom = 0; | |
297 OS.DrawText (hDC, buffer.ptr, size, &rect, flags); | |
298 if (rect.right - rect.left >= width) { | |
299 width = rect.right - rect.left; | |
300 thirdWidest = secondWidest; | |
301 secondWidest = widest; | |
302 widest = i; | |
303 } | |
304 height = Math.max(height, rect.bottom - rect.top); | |
305 } | |
306 if (widest > 1) widest = widest * 1000 + widest * 100 + widest * 10 + widest; | |
307 else if (secondWidest > 1) widest = secondWidest * 1000 + widest * 100 + widest * 10 + widest; | |
308 else widest = thirdWidest * 1000 + widest * 100 + widest * 10 + widest; | |
309 systime.wYear = cast(short) widest; | |
310 | |
311 /* Determine the widest/tallest month name string. */ | |
312 width = widest = 0; | |
313 for (short i = 0; i < MONTH_NAMES.length; i++) { | |
314 int name = MONTH_NAMES [i]; | |
315 int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, name, buffer.ptr, buffer.length); | |
316 if (size is 0) { | |
317 buffer = new TCHAR[size]; | |
318 OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, name, buffer.ptr, buffer.length); | |
319 } | |
320 rect.left = rect.top = rect.right = rect.bottom = 0; | |
321 OS.DrawText (hDC, buffer.ptr, size, &rect, flags); | |
322 if (rect.right - rect.left > width) { | |
323 width = rect.right - rect.left; | |
324 widest = i; | |
325 } | |
326 height = Math.max(height, rect.bottom - rect.top); | |
327 } | |
328 systime.wMonth = cast(short) (widest + 1); | |
329 | |
330 /* Determine the widest/tallest date string in the widest month of the widest year. */ | |
331 int dwFlags = ((style & SWT.MEDIUM) !is 0) ? OS.DATE_SHORTDATE : ((style & SWT.SHORT) !is 0) ? OS.DATE_YEARMONTH : OS.DATE_LONGDATE; | |
332 width = 0; | |
333 for (short i = 1; i <= MAX_DAY; i++) { | |
334 systime.wDay = i; | |
335 int size = OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
336 if (size is 0) { | |
337 buffer = new TCHAR[size]; | |
338 OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
339 } | |
340 rect.left = rect.top = rect.right = rect.bottom = 0; | |
341 OS.DrawText (hDC, buffer.ptr, size, &rect, flags); | |
342 width = Math.max(width, rect.right - rect.left); | |
343 height = Math.max(height, rect.bottom - rect.top); | |
344 if ((style & SWT.SHORT) !is 0) break; | |
345 } | |
346 } else if ((style & SWT.TIME) !is 0) { | |
347 /* Determine the widest/tallest hour string. This code allows for the possibility of ligatures. */ | |
348 int dwFlags = ((style & SWT.SHORT) !is 0) ? OS.TIME_NOSECONDS : 0; | |
349 short widest = 0; | |
350 int max = is24HourTime () ? MAX_24HOUR : MAX_12HOUR; | |
351 for (short i = 0; i < max; i++) { | |
352 systime.wHour = i; | |
353 int size = OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
354 if (size is 0) { | |
355 buffer = new TCHAR[size]; | |
356 OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
357 } | |
358 rect.left = rect.top = rect.right = rect.bottom = 0; | |
359 OS.DrawText (hDC, buffer.ptr, size, &rect, flags); | |
360 if (rect.right - rect.left > width) { | |
361 width = rect.right - rect.left; | |
362 widest = i; | |
363 } | |
364 height = Math.max(height, rect.bottom - rect.top); | |
365 } | |
366 systime.wHour = widest; | |
367 | |
368 /* Determine the widest/tallest minute and second string. */ | |
369 width = widest = 0; | |
370 for (short i = 0; i < MAX_MINUTE; i++) { | |
371 systime.wMinute = i; | |
372 int size = OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
373 if (size is 0) { | |
374 buffer = new TCHAR[size]; | |
375 OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
376 } | |
377 rect.left = rect.top = rect.right = rect.bottom = 0; | |
378 OS.DrawText (hDC, buffer.ptr, size, &rect, flags); | |
379 if (rect.right - rect.left > width) { | |
380 width = rect.right - rect.left; | |
381 widest = i; | |
382 } | |
383 height = Math.max(height, rect.bottom - rect.top); | |
384 } | |
385 systime.wMinute = widest; | |
386 systime.wSecond = widest; | |
387 | |
388 /* Determine the widest/tallest time string for the widest hour, widest minute, and if applicable, widest second. */ | |
389 int size = OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
390 if (size is 0) { | |
391 buffer = new TCHAR[size]; | |
392 OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length); | |
393 } | |
394 rect.left = rect.top = rect.right = rect.bottom = 0; | |
395 OS.DrawText (hDC, buffer.ptr, size, &rect, flags); | |
396 width = rect.right - rect.left; | |
397 height = Math.max(height, rect.bottom - rect.top); | |
398 } | |
399 if (newFont !is null) OS.SelectObject (hDC, oldFont); | |
400 OS.ReleaseDC (handle, hDC); | |
401 int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL); | |
402 width += upDownWidth + MARGIN; | |
403 int upDownHeight = OS.GetSystemMetrics (OS.SM_CYVSCROLL); | |
404 // TODO: On Vista, can send DTM_GETDATETIMEPICKERINFO to ask the Edit control what its margins are | |
405 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) upDownHeight += 7; | |
406 height = Math.max (height, upDownHeight); | |
407 } | |
408 } | |
409 if (width is 0) width = DEFAULT_WIDTH; | |
410 if (height is 0) height = DEFAULT_HEIGHT; | |
411 if (wHint !is SWT.DEFAULT) width = wHint; | |
412 if (hHint !is SWT.DEFAULT) height = hHint; | |
413 int border = getBorderWidth (); | |
414 width += border * 2; | |
415 height += border * 2; | |
416 return new Point (width, height); | |
417 } | |
418 | |
419 override void createHandle () { | |
420 super.createHandle (); | |
421 state &= ~(CANVAS | THEME_BACKGROUND); | |
422 | |
423 if ((style & SWT.BORDER) is 0) { | |
424 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
425 bits &= ~(OS.WS_EX_CLIENTEDGE | OS.WS_EX_STATICEDGE); | |
426 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits); | |
427 } | |
428 } | |
429 | |
430 override int defaultBackground () { | |
431 return OS.GetSysColor (OS.COLOR_WINDOW); | |
432 } | |
433 | |
434 String getComputeSizeString () { | |
435 // TODO: Not currently used but might need for WinCE | |
436 if ((style & SWT.DATE) !is 0) { | |
437 if ((style & SWT.SHORT) !is 0) return getCustomShortDateFormat (); | |
438 if ((style & SWT.MEDIUM) !is 0) return getShortDateFormat (); | |
439 if ((style & SWT.LONG) !is 0) return getLongDateFormat (); | |
440 } | |
441 if ((style & SWT.TIME) !is 0) { | |
442 if ((style & SWT.SHORT) !is 0) return getCustomShortTimeFormat (); | |
443 return getTimeFormat (); | |
444 } | |
445 return ""; | |
446 } | |
447 | |
448 String getCustomShortDateFormat () { | |
449 if (true) { | |
450 TCHAR[] tchar = new TCHAR[80]; | |
451 int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SYEARMONTH, tchar.ptr, 80); | |
452 return size !is 0 ? TCHARsToStr(tchar[0..size - 1]) : "M/yyyy"; //$NON-NLS-1$ | |
453 } | |
454 | |
455 //TODO: Not currently used, but may need for WinCE (or if numeric short date is required) | |
456 String buffer = getShortDateFormat (); | |
457 int length = buffer.length; | |
458 bool inQuotes = false; | |
459 int start = 0, end = 0; | |
460 while (start < length) { | |
461 char ch = buffer.charAt (start); | |
462 if (ch is SINGLE_QUOTE) inQuotes = !inQuotes; | |
463 else if (ch is DAY_FORMAT_CONSTANT && !inQuotes) { | |
464 end = start + 1; | |
465 while (end < length && buffer.charAt (end) is DAY_FORMAT_CONSTANT) end++; | |
466 int ordering = getShortDateFormatOrdering (); | |
467 switch (ordering) { | |
468 case MONTH_DAY_YEAR: | |
469 // skip the following separator | |
470 while (end < length && buffer.charAt (end) !is YEAR_FORMAT_CONSTANT) end++; | |
471 break; | |
472 case DAY_MONTH_YEAR: | |
473 // skip the following separator | |
474 while (end < length && buffer.charAt (end) !is MONTH_FORMAT_CONSTANT) end++; | |
475 break; | |
476 case YEAR_MONTH_DAY: | |
477 // skip the preceding separator | |
478 while (start > 0 && buffer.charAt (start) !is MONTH_FORMAT_CONSTANT) start--; | |
479 break; | |
480 default: | |
481 } | |
482 break; | |
483 } | |
484 start++; | |
485 } | |
486 if (start < end) buffer.length = start - 1; | |
487 return buffer; | |
488 } | |
489 | |
490 String getCustomShortTimeFormat () { | |
491 String buffer = getTimeFormat (); | |
492 int length = buffer.length; | |
493 bool inQuotes = false; | |
494 int start = 0, end = 0; | |
495 while (start < length) { | |
496 char ch = buffer.charAt (start); | |
497 if (ch is SINGLE_QUOTE) inQuotes = !inQuotes; | |
498 else if (ch is SECONDS_FORMAT_CONSTANT && !inQuotes) { | |
499 end = start + 1; | |
500 while (end < length && buffer.charAt (end) is SECONDS_FORMAT_CONSTANT) end++; | |
501 // skip the preceding separator | |
502 while (start > 0 && buffer.charAt (start) !is MINUTES_FORMAT_CONSTANT) start--; | |
503 start++; | |
504 break; | |
505 } | |
506 start++; | |
507 } | |
508 if (start < end) buffer.length = start - 1; | |
509 return buffer; | |
510 } | |
511 | |
512 String getLongDateFormat () { | |
513 //TODO: Not currently used, but may need for WinCE | |
514 TCHAR tchar[80]; | |
515 int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SLONGDATE, tchar.ptr, 80); | |
516 return size > 0 ? TCHARsToStr(tchar[0..size - 1]) : "dddd, MMMM dd, yyyy"; //$NON-NLS-1$ | |
517 } | |
518 | |
519 String getShortDateFormat () { | |
520 //TODO: Not currently used, but may need for WinCE | |
521 TCHAR tchar[80]; | |
522 //TODO: May need to OR with LOCALE_ICENTURY | |
523 int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SSHORTDATE, tchar.ptr, 80); | |
524 return size > 0 ? TCHARsToStr(tchar[0..size - 1]) : "M/d/yyyy"; //$NON-NLS-1$ | |
525 } | |
526 | |
527 int getShortDateFormatOrdering () { | |
528 //TODO: Not currently used, but may need for WinCE | |
529 TCHAR tchar[80]; | |
530 int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_IDATE, tchar.ptr, 4); | |
531 if (size > 0) { | |
532 String number = TCHARsToStr(tchar[0..size - 1]); | |
533 return Integer.parse (number); | |
534 } | |
535 return 0; | |
536 } | |
537 | |
538 String getTimeFormat () { | |
539 TCHAR tchar[80]; | |
540 int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_STIMEFORMAT, tchar.ptr, 80); | |
541 return size > 0 ? TCHARsToStr(tchar[0..size - 1]) : "h:mm:ss tt"; //$NON-NLS-1$ | |
542 } | |
543 | |
544 bool is24HourTime () { | |
545 TCHAR tchar[4]; | |
546 int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_ITIME, tchar.ptr, 4); | |
547 if (size > 0) { | |
548 String number = TCHARsToStr(tchar[0..size - 1]); | |
549 return Integer.parse (number) !is 0; | |
550 } | |
551 return true; | |
552 } | |
553 | |
554 /** | |
555 * Returns the receiver's date, or day of the month. | |
556 * <p> | |
557 * The first day of the month is 1, and the last day depends on the month and year. | |
558 * </p> | |
559 * | |
560 * @return a positive integer beginning with 1 | |
561 * | |
562 * @exception SWTException <ul> | |
563 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
564 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
565 * </ul> | |
566 */ | |
567 public int getDay () { | |
568 checkWidget (); | |
569 SYSTEMTIME systime; | |
570 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
571 OS.SendMessage (handle, msg, 0, &systime); | |
572 return systime.wDay; | |
573 } | |
574 | |
575 /** | |
576 * Returns the receiver's hours. | |
577 * <p> | |
578 * Hours is an integer between 0 and 23. | |
579 * </p> | |
580 * | |
581 * @return an integer between 0 and 23 | |
582 * | |
583 * @exception SWTException <ul> | |
584 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
585 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
586 * </ul> | |
587 */ | |
588 public int getHours () { | |
589 checkWidget (); | |
590 if ((style & SWT.CALENDAR) !is 0) return time.wHour; | |
591 SYSTEMTIME systime; | |
592 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
593 OS.SendMessage (handle, msg, 0, &systime); | |
594 return systime.wHour; | |
595 } | |
596 | |
597 /** | |
598 * Returns the receiver's minutes. | |
599 * <p> | |
600 * Minutes is an integer between 0 and 59. | |
601 * </p> | |
602 * | |
603 * @return an integer between 0 and 59 | |
604 * | |
605 * @exception SWTException <ul> | |
606 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
607 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
608 * </ul> | |
609 */ | |
610 public int getMinutes () { | |
611 checkWidget (); | |
612 if ((style & SWT.CALENDAR) !is 0) return time.wMinute; | |
613 SYSTEMTIME systime; | |
614 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
615 OS.SendMessage (handle, msg, 0, &systime); | |
616 return systime.wMinute; | |
617 } | |
618 | |
619 /** | |
620 * Returns the receiver's month. | |
621 * <p> | |
622 * The first month of the year is 0, and the last month is 11. | |
623 * </p> | |
624 * | |
625 * @return an integer between 0 and 11 | |
626 * | |
627 * @exception SWTException <ul> | |
628 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
629 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
630 * </ul> | |
631 */ | |
632 public int getMonth () { | |
633 checkWidget (); | |
634 SYSTEMTIME systime; | |
635 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
636 OS.SendMessage (handle, msg, 0, &systime); | |
637 return systime.wMonth - 1; | |
638 } | |
639 | |
640 override String getNameText () { | |
641 return (style & SWT.TIME) !is 0 ? Format( "{}:{}:{}", getHours(), getMinutes(), getSeconds()) | |
642 : Format("{}/{}/{}", (getMonth() + 1), getDay(), getYear()); | |
643 } | |
644 | |
645 /** | |
646 * Returns the receiver's seconds. | |
647 * <p> | |
648 * Seconds is an integer between 0 and 59. | |
649 * </p> | |
650 * | |
651 * @return an integer between 0 and 59 | |
652 * | |
653 * @exception SWTException <ul> | |
654 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
655 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
656 * </ul> | |
657 */ | |
658 public int getSeconds () { | |
659 checkWidget (); | |
660 if ((style & SWT.CALENDAR) !is 0) return time.wSecond; | |
661 SYSTEMTIME systime; | |
662 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
663 OS.SendMessage (handle, msg, 0, &systime); | |
664 return systime.wSecond; | |
665 } | |
666 | |
667 /** | |
668 * Returns the receiver's year. | |
669 * <p> | |
670 * The first year is 1752 and the last year is 9999. | |
671 * </p> | |
672 * | |
673 * @return an integer between 1752 and 9999 | |
674 * | |
675 * @exception SWTException <ul> | |
676 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
677 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
678 * </ul> | |
679 */ | |
680 public int getYear () { | |
681 checkWidget (); | |
682 SYSTEMTIME systime; | |
683 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
684 OS.SendMessage (handle, msg, 0, &systime); | |
685 return systime.wYear; | |
686 } | |
687 | |
688 void releaseWidget () { | |
689 super.releaseWidget (); | |
690 lastSystemTime = null; | |
691 } | |
692 | |
693 /** | |
694 * Removes the listener from the collection of listeners who will | |
695 * be notified when the control is selected by the user. | |
696 * | |
697 * @param listener the listener which should no longer be notified | |
698 * | |
699 * @exception IllegalArgumentException <ul> | |
700 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
701 * </ul> | |
702 * @exception SWTException <ul> | |
703 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
704 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
705 * </ul> | |
706 * | |
707 * @see SelectionListener | |
708 * @see #addSelectionListener | |
709 */ | |
710 public void removeSelectionListener (SelectionListener listener) { | |
711 checkWidget (); | |
712 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
713 if (eventTable is null) return; | |
714 eventTable.unhook (SWT.Selection, listener); | |
715 eventTable.unhook (SWT.DefaultSelection, listener); | |
716 } | |
717 | |
718 /** | |
719 * Sets the receiver's year, month, and day in a single operation. | |
720 * <p> | |
721 * This is the recommended way to set the date, because setting the year, | |
722 * month, and day separately may result in invalid intermediate dates. | |
723 * </p> | |
724 * | |
725 * @param year an integer between 1752 and 9999 | |
726 * @param month an integer between 0 and 11 | |
727 * @param day a positive integer beginning with 1 | |
728 * | |
729 * @exception SWTException <ul> | |
730 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
731 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
732 * </ul> | |
733 * | |
734 * @since 3.4 | |
735 */ | |
736 public void setDate (int year, int month, int day) { | |
737 checkWidget (); | |
738 SYSTEMTIME systime; | |
739 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
740 OS.SendMessage (handle, msg, 0, &systime); | |
741 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
742 systime.wYear = cast(short)year; | |
743 systime.wMonth = cast(short)(month + 1); | |
744 systime.wDay = cast(short)day; | |
745 OS.SendMessage (handle, msg, 0, &systime); | |
746 lastSystemTime = null; | |
747 } | |
748 | |
749 /** | |
750 * Sets the receiver's date, or day of the month, to the specified day. | |
751 * <p> | |
752 * The first day of the month is 1, and the last day depends on the month and year. | |
753 * </p> | |
754 * | |
755 * @param day a positive integer beginning with 1 | |
756 * | |
757 * @exception SWTException <ul> | |
758 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
759 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
760 * </ul> | |
761 */ | |
762 public void setDay (int day) { | |
763 checkWidget (); | |
764 SYSTEMTIME systime; | |
765 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
766 OS.SendMessage (handle, msg, 0, &systime); | |
767 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
768 systime.wDay = cast(short)day; | |
769 OS.SendMessage (handle, msg, 0, &systime); | |
770 lastSystemTime = null; | |
771 } | |
772 | |
773 /** | |
774 * Sets the receiver's hours. | |
775 * <p> | |
776 * Hours is an integer between 0 and 23. | |
777 * </p> | |
778 * | |
779 * @param hours an integer between 0 and 23 | |
780 * | |
781 * @exception SWTException <ul> | |
782 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
783 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
784 * </ul> | |
785 */ | |
786 public void setHours (int hours) { | |
787 checkWidget (); | |
788 SYSTEMTIME systime; | |
789 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
790 OS.SendMessage (handle, msg, 0, &systime); | |
791 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
792 systime.wHour = cast(short)hours; | |
793 OS.SendMessage (handle, msg, 0, &systime); | |
794 if ((style & SWT.CALENDAR) !is 0 && hours >= 0 && hours <= 23) time.wHour = cast(short)hours; | |
795 } | |
796 | |
797 /** | |
798 * Sets the receiver's minutes. | |
799 * <p> | |
800 * Minutes is an integer between 0 and 59. | |
801 * </p> | |
802 * | |
803 * @param minutes an integer between 0 and 59 | |
804 * | |
805 * @exception SWTException <ul> | |
806 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
807 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
808 * </ul> | |
809 */ | |
810 public void setMinutes (int minutes) { | |
811 checkWidget (); | |
812 SYSTEMTIME systime; | |
813 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
814 OS.SendMessage (handle, msg, 0, &systime); | |
815 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
816 systime.wMinute = cast(short)minutes; | |
817 OS.SendMessage (handle, msg, 0, &systime); | |
818 if ((style & SWT.CALENDAR) !is 0 && minutes >= 0 && minutes <= 59) time.wMinute = cast(short)minutes; | |
819 } | |
820 | |
821 /** | |
822 * Sets the receiver's month. | |
823 * <p> | |
824 * The first month of the year is 0, and the last month is 11. | |
825 * </p> | |
826 * | |
827 * @param month an integer between 0 and 11 | |
828 * | |
829 * @exception SWTException <ul> | |
830 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
831 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
832 * </ul> | |
833 */ | |
834 public void setMonth (int month) { | |
835 checkWidget (); | |
836 SYSTEMTIME systime; | |
837 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
838 OS.SendMessage (handle, msg, 0, &systime); | |
839 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
840 systime.wMonth = cast(short)(month + 1); | |
841 OS.SendMessage (handle, msg, 0, &systime); | |
842 lastSystemTime = null; | |
843 } | |
844 | |
845 /** | |
846 * Sets the receiver's seconds. | |
847 * <p> | |
848 * Seconds is an integer between 0 and 59. | |
849 * </p> | |
850 * | |
851 * @param seconds an integer between 0 and 59 | |
852 * | |
853 * @exception SWTException <ul> | |
854 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
855 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
856 * </ul> | |
857 */ | |
858 public void setSeconds (int seconds) { | |
859 checkWidget (); | |
860 SYSTEMTIME systime; | |
861 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
862 OS.SendMessage (handle, msg, 0, &systime); | |
863 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
864 systime.wSecond = cast(short)seconds; | |
865 OS.SendMessage (handle, msg, 0, &systime); | |
866 if ((style & SWT.CALENDAR) !is 0 && seconds >= 0 && seconds <= 59) time.wSecond = cast(short)seconds; | |
867 } | |
868 | |
869 /** | |
870 * Sets the receiver's hours, minutes, and seconds in a single operation. | |
871 * | |
872 * @param hours an integer between 0 and 23 | |
873 * @param minutes an integer between 0 and 59 | |
874 * @param seconds an integer between 0 and 59 | |
875 * | |
876 * @exception SWTException <ul> | |
877 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
878 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
879 * </ul> | |
880 * | |
881 * @since 3.4 | |
882 */ | |
883 public void setTime (int hours, int minutes, int seconds) { | |
884 checkWidget (); | |
885 SYSTEMTIME systime; | |
886 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
887 OS.SendMessage (handle, msg, 0, &systime); | |
888 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
889 systime.wHour = cast(short)hours; | |
890 systime.wMinute = cast(short)minutes; | |
891 systime.wSecond = cast(short)seconds; | |
892 OS.SendMessage (handle, msg, 0, &systime); | |
893 if ((style & SWT.CALENDAR) !is 0 | |
894 && hours >= 0 && hours <= 23 | |
895 && minutes >= 0 && minutes <= 59 | |
896 && seconds >= 0 && seconds <= 59) { | |
897 time.wHour = cast(short)hours; | |
898 time.wMinute = cast(short)minutes; | |
899 time.wSecond = cast(short)seconds; | |
900 } | |
901 } | |
902 | |
903 /** | |
904 * Sets the receiver's year. | |
905 * <p> | |
906 * The first year is 1752 and the last year is 9999. | |
907 * </p> | |
908 * | |
909 * @param year an integer between 1752 and 9999 | |
910 * | |
911 * @exception SWTException <ul> | |
912 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
913 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
914 * </ul> | |
915 */ | |
916 public void setYear (int year) { | |
917 checkWidget (); | |
918 SYSTEMTIME systime; | |
919 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
920 OS.SendMessage (handle, msg, 0, &systime); | |
921 msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; | |
922 systime.wYear = cast(short)year; | |
923 OS.SendMessage (handle, msg, 0, &systime); | |
924 lastSystemTime = null; | |
925 } | |
926 | |
927 override int widgetStyle () { | |
928 int bits = super.widgetStyle () | OS.WS_TABSTOP; | |
929 if ((style & SWT.CALENDAR) !is 0) return bits | OS.MCS_NOTODAY; | |
930 /* | |
931 * Bug in Windows: When WS_CLIPCHILDREN is set in a | |
932 * Date and Time Picker, the widget draws on top of | |
933 * the updown control. The fix is to clear the bits. | |
934 */ | |
935 bits &= ~OS.WS_CLIPCHILDREN; | |
936 if ((style & SWT.TIME) !is 0) bits |= OS.DTS_TIMEFORMAT; | |
937 if ((style & SWT.DATE) !is 0) bits |= ((style & SWT.MEDIUM) !is 0 ? OS.DTS_SHORTDATECENTURYFORMAT : OS.DTS_LONGDATEFORMAT) | OS.DTS_UPDOWN; | |
938 return bits; | |
939 } | |
940 | |
941 override String windowClass () { | |
942 return (style & SWT.CALENDAR) !is 0 ? TCHARsToStr(CalendarClass) : TCHARsToStr(DateTimeClass); | |
943 } | |
944 | |
945 override int windowProc () { | |
946 return (style & SWT.CALENDAR) !is 0 ? cast(int)CalendarProc : cast(int)DateTimeProc; | |
947 } | |
948 | |
949 override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) { | |
950 switch (hdr.code) { | |
951 case OS.MCN_SELCHANGE: | |
952 case OS.DTN_DATETIMECHANGE: | |
953 if (ignoreSelection) break; | |
954 SYSTEMTIME systime; | |
955 int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; | |
956 OS.SendMessage (handle, msg, 0, &systime); | |
957 if (lastSystemTime is null || systime.wDay !is lastSystemTime.wDay || systime.wMonth !is lastSystemTime.wMonth || systime.wYear !is lastSystemTime.wYear) { | |
958 postEvent (SWT.Selection); | |
959 if ((style & SWT.TIME) is 0) { | |
960 lastSystemTime = new SYSTEMTIME(); | |
961 *lastSystemTime = systime; | |
962 } | |
963 } | |
964 break; | |
965 default: | |
966 } | |
967 return super.wmNotifyChild (hdr, wParam, lParam); | |
968 } | |
969 | |
970 LRESULT WM_TIMER (int /*long*/ wParam, int /*long*/ lParam) { | |
971 LRESULT result = super.WM_TIMER (wParam, lParam); | |
972 if (result !is null) return result; | |
973 /* | |
974 * Feature in Windows. For some reason, Windows sends WM_NOTIFY with | |
975 * MCN_SELCHANGE at regular intervals. This is unexpected. The fix is | |
976 * to ignore MCN_SELCHANGE during WM_TIMER. | |
977 */ | |
978 ignoreSelection = true; | |
979 int /*long*/ code = callWindowProc(handle, OS.WM_TIMER, wParam, lParam); | |
980 ignoreSelection = false; | |
981 return code is 0 ? LRESULT.ZERO : new LRESULT(code); | |
982 } | |
983 } | |
984 |