[COMCTL32_WINETEST]
[reactos.git] / rostests / winetests / comctl32 / datetime.c
1 /* Unit test suite for datetime control.
2 *
3 * Copyright 2007 Kanit Therdsteerasukdi
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 //#include <windows.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <wingdi.h>
25 #include <winuser.h>
26 #include <winnls.h>
27 #include <commctrl.h>
28 //#include "wine/test.h"
29 #include "msg.h"
30
31 #define expect(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
32
33 #define expect_unsuccess(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d(unsuccessful), got %ld(successful)\n", (EXPECTED), (GOT))
34
35 #define NUM_MSG_SEQUENCES 1
36 #define DATETIME_SEQ_INDEX 0
37
38 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
39
40 static const struct message test_dtm_set_format_seq[] = {
41 { DTM_SETFORMATA, sent|wparam|lparam, 0, 0 },
42 { DTM_SETFORMATA, sent|wparam, 0 },
43 { 0 }
44 };
45
46 static const struct message test_dtm_set_and_get_mccolor_seq[] = {
47 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0 },
48 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(255, 255, 255) },
49 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(100, 180, 220) },
50 { DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0 },
51 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0 },
52 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(255, 255, 255) },
53 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(100, 180, 220) },
54 { DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0 },
55 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, 0 },
56 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(255, 255, 255) },
57 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(100, 180, 220) },
58 { DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, 0 },
59 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0 },
60 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(255, 255, 255) },
61 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(100, 180, 220) },
62 { DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0 },
63 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0 },
64 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(255, 255, 255) },
65 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(100, 180, 220) },
66 { DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0 },
67 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0 },
68 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(255, 255, 255) },
69 { DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(100, 180, 220) },
70 { DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0 },
71 { 0 }
72 };
73
74 static const struct message test_dtm_set_and_get_mcfont_seq[] = {
75 { DTM_SETMCFONT, sent|lparam, 0, 1 },
76 { DTM_GETMCFONT, sent|wparam|lparam, 0, 0 },
77 { 0 }
78 };
79
80 static const struct message test_dtm_get_monthcal_seq[] = {
81 { DTM_GETMONTHCAL, sent|wparam|lparam, 0, 0 },
82 { 0 }
83 };
84
85 static const struct message test_dtm_set_and_get_range_seq[] = {
86 { DTM_SETRANGE, sent|wparam, GDTR_MIN },
87 { DTM_GETRANGE, sent|wparam, 0 },
88 { DTM_SETRANGE, sent|wparam, GDTR_MAX },
89 { DTM_SETRANGE, sent|wparam, GDTR_MAX },
90 { DTM_GETRANGE, sent|wparam, 0 },
91 { DTM_SETRANGE, sent|wparam, GDTR_MIN },
92 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
93 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
94 { DTM_GETRANGE, sent|wparam, 0 },
95 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
96 { DTM_GETRANGE, sent|wparam, 0 },
97 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
98 { DTM_GETRANGE, sent|wparam, 0 },
99 { 0 }
100 };
101
102 static const struct message test_dtm_set_range_swap_min_max_seq[] = {
103 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
104 { DTM_GETSYSTEMTIME, sent|wparam, 0 },
105 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
106 { DTM_GETRANGE, sent|wparam, 0 },
107 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
108 { DTM_GETSYSTEMTIME, sent|wparam, 0 },
109 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
110 { DTM_GETRANGE, sent|wparam, 0 },
111 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
112 { DTM_GETRANGE, sent|wparam, 0 },
113 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
114 { DTM_GETRANGE, sent|wparam, 0 },
115 { 0 }
116 };
117
118 static const struct message test_dtm_set_and_get_system_time_seq[] = {
119 { DTM_SETSYSTEMTIME, sent|wparam, GDT_NONE },
120 { DTM_GETSYSTEMTIME, sent|wparam, 0 },
121 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
122 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
123 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
124 { DTM_GETSYSTEMTIME, sent|wparam, 0 },
125 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
126 { 0 }
127 };
128
129 static const struct message test_dtm_set_and_get_systime_with_limits[] = {
130 { DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
131 { DTM_GETRANGE, sent|wparam, 0 },
132 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
133 { DTM_GETSYSTEMTIME, sent|wparam, 0 },
134 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
135 { DTM_GETSYSTEMTIME, sent|wparam, 0 },
136 { DTM_SETSYSTEMTIME, sent|wparam, 0 },
137 { DTM_GETSYSTEMTIME, sent|wparam, 0 },
138 { 0 }
139 };
140
141 static LRESULT WINAPI datetime_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
142 {
143 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
144 static LONG defwndproc_counter = 0;
145 LRESULT ret;
146 struct message msg;
147
148 msg.message = message;
149 msg.flags = sent|wparam|lparam;
150 if (defwndproc_counter) msg.flags |= defwinproc;
151 msg.wParam = wParam;
152 msg.lParam = lParam;
153 msg.id = 0;
154 add_message(sequences, DATETIME_SEQ_INDEX, &msg);
155
156 defwndproc_counter++;
157 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
158 defwndproc_counter--;
159
160 return ret;
161 }
162
163 static HWND create_datetime_control(DWORD style)
164 {
165 WNDPROC oldproc;
166 HWND hWndDateTime = NULL;
167
168 hWndDateTime = CreateWindowExA(0,
169 DATETIMEPICK_CLASSA,
170 NULL,
171 style,
172 0,50,300,120,
173 NULL,
174 NULL,
175 NULL,
176 NULL);
177
178 if (!hWndDateTime) return NULL;
179
180 oldproc = (WNDPROC)SetWindowLongPtrA(hWndDateTime, GWLP_WNDPROC,
181 (LONG_PTR)datetime_subclass_proc);
182 SetWindowLongPtrA(hWndDateTime, GWLP_USERDATA, (LONG_PTR)oldproc);
183
184 return hWndDateTime;
185 }
186
187 static void test_dtm_set_format(void)
188 {
189 HWND hWnd;
190 CHAR txt[256];
191 SYSTEMTIME systime;
192 LRESULT r;
193
194 hWnd = create_datetime_control(DTS_SHOWNONE);
195
196 flush_sequences(sequences, NUM_MSG_SEQUENCES);
197
198 r = SendMessageA(hWnd, DTM_SETFORMATA, 0, 0);
199 expect(1, r);
200
201 r = SendMessageA(hWnd, DTM_SETFORMATA, 0,
202 (LPARAM)"'Today is: 'hh':'m':'s dddd MMM dd', 'yyyy");
203 expect(1, r);
204
205 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_format_seq, "test_dtm_set_format", FALSE);
206
207 r = SendMessageA(hWnd, DTM_SETFORMATA, 0, (LPARAM)"'hh' hh");
208 expect(1, r);
209 ZeroMemory(&systime, sizeof(systime));
210 systime.wYear = 2000;
211 systime.wMonth = systime.wDay = 1;
212 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, 0, (LPARAM)&systime);
213 expect(1, r);
214 GetWindowTextA(hWnd, txt, 256);
215 ok(strcmp(txt, "hh 12") == 0, "String mismatch (\"%s\" vs \"hh 12\")\n", txt);
216
217 DestroyWindow(hWnd);
218 }
219
220 static void test_mccolor_types(HWND hWndDateTime, int mccolor_type, const char* mccolor_name)
221 {
222 COLORREF theColor, prevColor, crColor;
223
224 theColor=RGB(0,0,0);
225 crColor = SendMessageA(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
226 ok(crColor != ~0u, "%s: Set RGB(0,0,0): Expected COLORREF of previous value, got %d\n", mccolor_name, crColor);
227 prevColor=theColor;
228 theColor=RGB(255,255,255);
229 crColor = SendMessageA(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
230 ok(crColor==prevColor, "%s: Set RGB(255,255,255): Expected COLORREF of previous value, got %d\n", mccolor_name, crColor);
231 prevColor=theColor;
232 theColor=RGB(100,180,220);
233 crColor = SendMessageA(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
234 ok(crColor==prevColor, "%s: Set RGB(100,180,220): Expected COLORREF of previous value, got %d\n", mccolor_name, crColor);
235 crColor = SendMessageA(hWndDateTime, DTM_GETMCCOLOR, mccolor_type, 0);
236 ok(crColor==theColor, "%s: GETMCCOLOR: Expected %d, got %d\n", mccolor_name, theColor, crColor);
237 }
238
239 static void test_dtm_set_and_get_mccolor(void)
240 {
241 HWND hWnd;
242
243 hWnd = create_datetime_control(DTS_SHOWNONE);
244
245 flush_sequences(sequences, NUM_MSG_SEQUENCES);
246
247 test_mccolor_types(hWnd, MCSC_BACKGROUND, "MCSC_BACKGROUND");
248 test_mccolor_types(hWnd, MCSC_MONTHBK, "MCSC_MONTHBK");
249 test_mccolor_types(hWnd, MCSC_TEXT, "MCSC_TEXT");
250 test_mccolor_types(hWnd, MCSC_TITLEBK, "MCSC_TITLEBK");
251 test_mccolor_types(hWnd, MCSC_TITLETEXT, "MCSC_TITLETEXT");
252 test_mccolor_types(hWnd, MCSC_TRAILINGTEXT, "MCSC_TRAILINGTEXT");
253
254 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_mccolor_seq, "test_dtm_set_and_get_mccolor", FALSE);
255
256 DestroyWindow(hWnd);
257 }
258
259 static void test_dtm_set_and_get_mcfont(void)
260 {
261 HFONT hFontOrig, hFontNew;
262 HWND hWnd;
263
264 hWnd = create_datetime_control(DTS_SHOWNONE);
265
266 flush_sequences(sequences, NUM_MSG_SEQUENCES);
267
268 hFontOrig = GetStockObject(DEFAULT_GUI_FONT);
269 SendMessageA(hWnd, DTM_SETMCFONT, (WPARAM)hFontOrig, TRUE);
270 hFontNew = (HFONT)SendMessageA(hWnd, DTM_GETMCFONT, 0, 0);
271 ok(hFontOrig == hFontNew, "Expected hFontOrig==hFontNew, hFontOrig=%p, hFontNew=%p\n", hFontOrig, hFontNew);
272
273 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_mcfont_seq, "test_dtm_set_and_get_mcfont", FALSE);
274 DestroyWindow(hWnd);
275 }
276
277 static void test_dtm_get_monthcal(void)
278 {
279 LRESULT r;
280 HWND hWnd;
281
282 hWnd = create_datetime_control(DTS_SHOWNONE);
283
284 flush_sequences(sequences, NUM_MSG_SEQUENCES);
285
286 todo_wine {
287 r = SendMessageA(hWnd, DTM_GETMONTHCAL, 0, 0);
288 ok(r == 0, "Expected NULL(no child month calendar control), got %ld\n", r);
289 }
290
291 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_get_monthcal_seq, "test_dtm_get_monthcal", FALSE);
292 DestroyWindow(hWnd);
293 }
294
295 static void fill_systime_struct(SYSTEMTIME *st, int year, int month, int dayofweek, int day, int hour, int minute, int second, int milliseconds)
296 {
297 st->wYear = year;
298 st->wMonth = month;
299 st->wDayOfWeek = dayofweek;
300 st->wDay = day;
301 st->wHour = hour;
302 st->wMinute = minute;
303 st->wSecond = second;
304 st->wMilliseconds = milliseconds;
305 }
306
307 static LPARAM compare_systime_date(SYSTEMTIME *st1, SYSTEMTIME *st2)
308 {
309 return (st1->wYear == st2->wYear)
310 && (st1->wMonth == st2->wMonth)
311 && (st1->wDayOfWeek == st2->wDayOfWeek)
312 && (st1->wDay == st2->wDay);
313 }
314
315 static LPARAM compare_systime_time(SYSTEMTIME *st1, SYSTEMTIME *st2)
316 {
317 return (st1->wHour == st2->wHour)
318 && (st1->wMinute == st2->wMinute)
319 && (st1->wSecond == st2->wSecond)
320 && (st1->wMilliseconds == st2->wMilliseconds);
321 }
322
323 static LPARAM compare_systime(SYSTEMTIME *st1, SYSTEMTIME *st2)
324 {
325 if(!compare_systime_date(st1, st2))
326 return 0;
327
328 return compare_systime_time(st1, st2);
329 }
330
331 #define expect_systime(ST1, ST2) ok(compare_systime((ST1), (ST2))==1, "ST1 != ST2\n")
332 #define expect_systime_date(ST1, ST2) ok(compare_systime_date((ST1), (ST2))==1, "ST1.date != ST2.date\n")
333 #define expect_systime_time(ST1, ST2) ok(compare_systime_time((ST1), (ST2))==1, "ST1.time != ST2.time\n")
334
335 static void test_dtm_set_and_get_range(void)
336 {
337 LRESULT r;
338 SYSTEMTIME st[2];
339 SYSTEMTIME getSt[2];
340 HWND hWnd;
341
342 hWnd = create_datetime_control(DTS_SHOWNONE);
343
344 flush_sequences(sequences, NUM_MSG_SEQUENCES);
345
346 /* initialize st[0] to lowest possible value */
347 fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
348 /* initialize st[1] to all invalid numbers */
349 fill_systime_struct(&st[1], 0, 0, 7, 0, 24, 60, 60, 1000);
350
351 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
352 expect(1, r);
353 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
354 ok(r == GDTR_MIN, "Expected %x, not %x(GDTR_MAX) or %x(GDTR_MIN | GDTR_MAX), got %lx\n", GDTR_MIN, GDTR_MAX, GDTR_MIN | GDTR_MAX, r);
355 expect_systime(&st[0], &getSt[0]);
356
357 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
358 expect_unsuccess(0, r);
359
360 /* set st[0] to all invalid numbers */
361 fill_systime_struct(&st[0], 0, 0, 7, 0, 24, 60, 60, 1000);
362 /* set st[1] to highest possible value */
363 fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
364
365 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
366 expect(1, r);
367 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
368 todo_wine {
369 ok(r == GDTR_MAX, "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MIN | GDTR_MAX), got %lx\n", GDTR_MAX, GDTR_MIN, GDTR_MIN | GDTR_MAX, r);
370 }
371 expect_systime(&st[1], &getSt[1]);
372
373 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
374 expect_unsuccess(0, r);
375 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
376 expect_unsuccess(0, r);
377
378 /* set st[0] to highest possible value */
379 fill_systime_struct(&st[0], 30827, 12, 6, 31, 23, 59, 59, 999);
380
381 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
382 expect(1, r);
383 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
384 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
385 expect_systime(&st[0], &getSt[0]);
386 expect_systime(&st[1], &getSt[1]);
387
388 /* initialize st[0] to lowest possible value */
389 fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
390 /* set st[1] to highest possible value */
391 fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
392
393 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
394 expect(1, r);
395 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
396 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
397 expect_systime(&st[0], &getSt[0]);
398 expect_systime(&st[1], &getSt[1]);
399
400 /* set st[0] to value higher than minimum */
401 fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
402 /* set st[1] to value lower than maximum */
403 fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
404
405 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
406 expect(1, r);
407 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
408 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
409 expect_systime(&st[0], &getSt[0]);
410 expect_systime(&st[1], &getSt[1]);
411
412 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_range_seq, "test_dtm_set_and_get_range", FALSE);
413
414 DestroyWindow(hWnd);
415 }
416
417 /* when max<min for DTM_SETRANGE, Windows seems to swap the min and max values,
418 although that's undocumented. However, it doesn't seem to be implemented
419 correctly, causing some strange side effects */
420 static void test_dtm_set_range_swap_min_max(void)
421 {
422 LRESULT r;
423 SYSTEMTIME st[2];
424 SYSTEMTIME getSt[2];
425 SYSTEMTIME origSt;
426 HWND hWnd;
427
428 hWnd = create_datetime_control(DTS_SHOWNONE);
429 flush_sequences(sequences, NUM_MSG_SEQUENCES);
430
431 fill_systime_struct(&st[0], 2007, 2, 4, 15, 2, 2, 2, 2);
432
433 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
434 expect(1, r);
435 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&origSt);
436 ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
437 expect_systime(&st[0], &origSt);
438
439 /* set st[0] to value higher than st[1] */
440 fill_systime_struct(&st[0], 2007, 3, 2, 31, 23, 59, 59, 999);
441 fill_systime_struct(&st[1], 1980, 1, 3, 23, 14, 34, 37, 465);
442
443 /* since min>max, min and max values should be swapped by DTM_SETRANGE
444 automatically */
445 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
446 expect(1, r);
447 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
448 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
449 todo_wine {
450 ok(compare_systime(&st[0], &getSt[0]) == 1 ||
451 broken(compare_systime(&st[0], &getSt[1]) == 1), /* comctl32 version <= 5.80 */
452 "ST1 != ST2\n");
453
454 ok(compare_systime(&st[1], &getSt[1]) == 1 ||
455 broken(compare_systime(&st[1], &getSt[0]) == 1), /* comctl32 version <= 5.80 */
456 "ST1 != ST2\n");
457 }
458
459 fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
460
461 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
462 expect(1, r);
463 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
464 ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
465 /* the time part seems to not change after swapping the min and max values
466 and doing DTM_SETSYSTEMTIME */
467 expect_systime_date(&st[0], &getSt[0]);
468 todo_wine {
469 ok(compare_systime_time(&origSt, &getSt[0]) == 1 ||
470 broken(compare_systime_time(&st[0], &getSt[0]) == 1), /* comctl32 version <= 5.80 */
471 "ST1.time != ST2.time\n");
472 }
473
474 /* set st[0] to value higher than minimum */
475 fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
476 /* set st[1] to value lower than maximum */
477 fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
478
479 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
480 expect(1, r);
481 /* for some reason after we swapped the min and max values before,
482 whenever we do a DTM_SETRANGE, the DTM_GETRANGE will return the values
483 swapped*/
484 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
485 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
486 todo_wine {
487 ok(compare_systime(&st[0], &getSt[1]) == 1 ||
488 broken(compare_systime(&st[0], &getSt[0]) == 1), /* comctl32 version <= 5.80 */
489 "ST1 != ST2\n");
490
491 ok(compare_systime(&st[1], &getSt[0]) == 1 ||
492 broken(compare_systime(&st[1], &getSt[1]) == 1), /* comctl32 version <= 5.80 */
493 "ST1 != ST2\n");
494 }
495
496 /* set st[0] to value higher than st[1] */
497 fill_systime_struct(&st[0], 2007, 3, 2, 31, 23, 59, 59, 999);
498 fill_systime_struct(&st[1], 1980, 1, 3, 23, 14, 34, 37, 465);
499
500 /* set min>max again, so that the return values of DTM_GETRANGE are no
501 longer swapped the next time we do a DTM SETRANGE and DTM_GETRANGE*/
502 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
503 expect(1, r);
504 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
505 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
506 expect_systime(&st[0], &getSt[1]);
507 expect_systime(&st[1], &getSt[0]);
508
509 /* initialize st[0] to lowest possible value */
510 fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
511 /* set st[1] to highest possible value */
512 fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
513
514 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
515 expect(1, r);
516 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
517 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
518 expect_systime(&st[0], &getSt[0]);
519 expect_systime(&st[1], &getSt[1]);
520
521 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_range_swap_min_max_seq, "test_dtm_set_range_swap_min_max", FALSE);
522
523 DestroyWindow(hWnd);
524 }
525
526 static void test_dtm_set_and_get_system_time(void)
527 {
528 LRESULT r;
529 SYSTEMTIME st, getSt, ref;
530 HWND hWnd, hWndDateTime_test_gdt_none;
531
532 hWndDateTime_test_gdt_none = create_datetime_control(0);
533
534 ok(hWndDateTime_test_gdt_none!=NULL, "Expected non NULL, got %p\n", hWndDateTime_test_gdt_none);
535 if(hWndDateTime_test_gdt_none) {
536 r = SendMessageA(hWndDateTime_test_gdt_none, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
537 expect(0, r);
538 }
539 else {
540 skip("hWndDateTime_test_gdt_none is NULL\n");
541 flush_sequences(sequences, NUM_MSG_SEQUENCES);
542
543 return;
544 }
545
546 DestroyWindow(hWndDateTime_test_gdt_none);
547
548 hWnd = create_datetime_control(DTS_SHOWNONE);
549 flush_sequences(sequences, NUM_MSG_SEQUENCES);
550
551 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
552 expect(1, r);
553 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
554 ok(r == GDT_NONE, "Expected %d, not %d(GDT_VALID) or %d(GDT_ERROR), got %ld\n", GDT_NONE, GDT_VALID, GDT_ERROR, r);
555
556 /* set st to lowest possible value */
557 fill_systime_struct(&st, 1601, 1, 0, 1, 0, 0, 0, 0);
558
559 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
560 expect(1, r);
561
562 /* set st to highest possible value */
563 fill_systime_struct(&st, 30827, 12, 6, 31, 23, 59, 59, 999);
564
565 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
566 expect(1, r);
567
568 /* set st to value between min and max */
569 fill_systime_struct(&st, 1980, 1, 3, 23, 14, 34, 37, 465);
570
571 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
572 expect(1, r);
573 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
574 ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
575 expect_systime(&st, &getSt);
576
577 /* set st to invalid value */
578 fill_systime_struct(&st, 0, 0, 7, 0, 24, 60, 60, 1000);
579
580 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
581 expect_unsuccess(0, r);
582
583 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_system_time_seq, "test_dtm_set_and_get_system_time", FALSE);
584
585 /* set to some valid value */
586 GetSystemTime(&ref);
587 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&ref);
588 expect(1, r);
589 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
590 expect(GDT_VALID, r);
591 expect_systime(&ref, &getSt);
592
593 /* year invalid */
594 st = ref;
595 st.wYear = 0;
596 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
597 todo_wine expect(1, r);
598 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
599 expect(GDT_VALID, r);
600 expect_systime(&ref, &getSt);
601 /* month invalid */
602 st = ref;
603 st.wMonth = 13;
604 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
605 expect(0, r);
606 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
607 expect(GDT_VALID, r);
608 expect_systime(&ref, &getSt);
609 /* day invalid */
610 st = ref;
611 st.wDay = 32;
612 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
613 expect(0, r);
614 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
615 expect(GDT_VALID, r);
616 expect_systime(&ref, &getSt);
617 /* day invalid for current month */
618 st = ref;
619 st.wDay = 30;
620 st.wMonth = 2;
621 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
622 expect(0, r);
623 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
624 expect(GDT_VALID, r);
625 expect_systime(&ref, &getSt);
626 /* day of week isn't validated */
627 st = ref;
628 st.wDayOfWeek = 10;
629 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
630 expect(1, r);
631 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
632 expect(GDT_VALID, r);
633 expect_systime(&ref, &getSt);
634 /* hour invalid */
635 st = ref;
636 st.wHour = 25;
637 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
638 expect(0, r);
639 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
640 expect(GDT_VALID, r);
641 expect_systime(&ref, &getSt);
642 /* minute invalid */
643 st = ref;
644 st.wMinute = 60;
645 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
646 expect(0, r);
647 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
648 expect(GDT_VALID, r);
649 expect_systime(&ref, &getSt);
650 /* sec invalid */
651 st = ref;
652 st.wSecond = 60;
653 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
654 expect(0, r);
655 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
656 expect(GDT_VALID, r);
657 expect_systime(&ref, &getSt);
658 /* msec invalid */
659 st = ref;
660 st.wMilliseconds = 1000;
661 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
662 expect(0, r);
663 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
664 expect(GDT_VALID, r);
665 expect_systime(&ref, &getSt);
666
667 /* day of week should be calculated automatically,
668 actual day of week for this date is 4 */
669 fill_systime_struct(&st, 2009, 10, 1, 1, 0, 0, 10, 200);
670 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
671 expect(1, r);
672 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
673 expect(GDT_VALID, r);
674 /* 01.10.2009 is Thursday */
675 expect(4, (LRESULT)getSt.wDayOfWeek);
676 st.wDayOfWeek = 4;
677 expect_systime(&st, &getSt);
678 }
679
680 static void test_dtm_set_and_get_systemtime_with_limits(void)
681 {
682 LRESULT r;
683 SYSTEMTIME st[2], getSt[2], refSt;
684 HWND hWnd;
685
686 hWnd = create_datetime_control(DTS_SHOWNONE);
687
688 flush_sequences(sequences, NUM_MSG_SEQUENCES);
689
690 /* set range */
691 fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
692 fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
693
694 r = SendMessageA(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
695 expect(1, r);
696 r = SendMessageA(hWnd, DTM_GETRANGE, 0, (LPARAM)getSt);
697 ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
698 expect_systime(&st[0], &getSt[0]);
699 expect_systime(&st[1], &getSt[1]);
700
701 /* Initially set a valid time */
702 fill_systime_struct(&refSt, 1999, 9, 4, 9, 19, 9, 9, 999);
703 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&refSt);
704 expect(1, r);
705 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
706 ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
707 expect_systime(&refSt, &getSt[0]);
708
709 /* Now set an out-of-bounds time */
710 fill_systime_struct(&st[0], 2010, 1, 0, 1, 0, 0, 0, 0);
711
712 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
713 expect(1, r);
714 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
715 ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
716 expect_systime(&refSt, &getSt[0]);
717
718 fill_systime_struct(&st[0], 1977, 1, 0, 1, 0, 0, 0, 0);
719
720 r = SendMessageA(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
721 expect(1, r);
722 r = SendMessageA(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
723 ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
724 expect_systime(&refSt, &getSt[0]);
725
726 ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_systime_with_limits, "test_dtm_set_and_get_systime_with_limits", FALSE);
727
728 DestroyWindow(hWnd);
729 }
730
731 static void test_wm_set_get_text(void)
732 {
733 static const CHAR a_str[] = "a";
734 CHAR buff[16], time[16], caltype[3];
735 HWND hWnd;
736 LRESULT ret;
737
738 hWnd = create_datetime_control(0);
739
740 ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)a_str);
741 ok(CB_ERR == ret ||
742 broken(0 == ret) || /* comctl32 <= 4.72 */
743 broken(1 == ret), /* comctl32 <= 4.70 */
744 "Expected CB_ERR, got %ld\n", ret);
745
746 buff[0] = 0;
747 ret = SendMessageA(hWnd, WM_GETTEXT, sizeof(buff), (LPARAM)buff);
748 ok(strcmp(buff, a_str) != 0, "Expected text to change, got %s\n", buff);
749 ok(ret != 0, "Expected non-zero return value\n");
750
751 SetLastError(0xdeadbeef);
752 ret = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ICALENDARTYPE, caltype, 3);
753 if (ret == 0)
754 skip("Must know local calendar type (%x)\n", GetLastError());
755 else if (atoi(caltype) != CAL_GREGORIAN)
756 skip("DateTimePicker Control only supports Gregorian calendar (type: %s)\n", caltype);
757 else {
758 SetLastError(0xdeadbeef);
759 ret = GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, time, sizeof(time));
760 if (ret == 0)
761 skip("GetDateFormat failed, returned %ld, error %d\n", ret, GetLastError());
762 else
763 ok(!strcmp(buff, time), "Expected %s, got %s\n", time, buff);
764 }
765
766 DestroyWindow(hWnd);
767 }
768
769 static void test_dts_shownone(void)
770 {
771 HWND hwnd;
772 DWORD style;
773
774 /* it isn't allowed to change DTS_SHOWNONE after creation */
775 hwnd = create_datetime_control(0);
776 style = GetWindowLongA(hwnd, GWL_STYLE);
777 SetWindowLongA(hwnd, GWL_STYLE, style | DTS_SHOWNONE);
778 style = GetWindowLongA(hwnd, GWL_STYLE);
779 ok(!(style & DTS_SHOWNONE), "Expected DTS_SHOWNONE not to be set\n");
780 DestroyWindow(hwnd);
781
782 hwnd = create_datetime_control(DTS_SHOWNONE);
783 style = GetWindowLongA(hwnd, GWL_STYLE);
784 SetWindowLongA(hwnd, GWL_STYLE, style & ~DTS_SHOWNONE);
785 style = GetWindowLongA(hwnd, GWL_STYLE);
786 ok(style & DTS_SHOWNONE, "Expected DTS_SHOWNONE to be set\n");
787 DestroyWindow(hwnd);
788 }
789
790 START_TEST(datetime)
791 {
792 HMODULE hComctl32;
793 BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
794 INITCOMMONCONTROLSEX iccex;
795
796 hComctl32 = GetModuleHandleA("comctl32.dll");
797 pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
798 if (!pInitCommonControlsEx)
799 {
800 skip("InitCommonControlsEx() is missing. Skipping the tests\n");
801 return;
802 }
803 iccex.dwSize = sizeof(iccex);
804 iccex.dwICC = ICC_DATE_CLASSES;
805 pInitCommonControlsEx(&iccex);
806
807 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
808
809 test_dtm_set_format();
810 test_dtm_set_and_get_mccolor();
811 test_dtm_set_and_get_mcfont();
812 test_dtm_get_monthcal();
813 test_dtm_set_and_get_range();
814 test_dtm_set_range_swap_min_max();
815 test_dtm_set_and_get_system_time();
816 test_dtm_set_and_get_systemtime_with_limits();
817 test_wm_set_get_text();
818 test_dts_shownone();
819 }