1 /* Unit test suite for datetime control.
3 * Copyright 2007 Kanit Therdsteerasukdi
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.
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.
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
23 #include "wine/test.h"
27 #define expect(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
29 #define expect_unsuccess(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d(unsuccessful), got %ld(successful)\n", (EXPECTED), (GOT))
31 #define NUM_MSG_SEQUENCES 1
32 #define DATETIME_SEQ_INDEX 0
34 static BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
36 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
38 static const struct message test_dtm_set_format_seq
[] = {
39 { DTM_SETFORMATA
, sent
|wparam
|lparam
, 0, 0 },
40 { DTM_SETFORMATA
, sent
|wparam
, 0 },
44 static const struct message test_dtm_set_and_get_mccolor_seq
[] = {
45 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_BACKGROUND
, 0 },
46 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_BACKGROUND
, RGB(255, 255, 255) },
47 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_BACKGROUND
, RGB(100, 180, 220) },
48 { DTM_GETMCCOLOR
, sent
|wparam
|lparam
, MCSC_BACKGROUND
, 0 },
49 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_MONTHBK
, 0 },
50 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_MONTHBK
, RGB(255, 255, 255) },
51 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_MONTHBK
, RGB(100, 180, 220) },
52 { DTM_GETMCCOLOR
, sent
|wparam
|lparam
, MCSC_MONTHBK
, 0 },
53 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TEXT
, 0 },
54 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TEXT
, RGB(255, 255, 255) },
55 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TEXT
, RGB(100, 180, 220) },
56 { DTM_GETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TEXT
, 0 },
57 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLEBK
, 0 },
58 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLEBK
, RGB(255, 255, 255) },
59 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLEBK
, RGB(100, 180, 220) },
60 { DTM_GETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLEBK
, 0 },
61 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLETEXT
, 0 },
62 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLETEXT
, RGB(255, 255, 255) },
63 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLETEXT
, RGB(100, 180, 220) },
64 { DTM_GETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TITLETEXT
, 0 },
65 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TRAILINGTEXT
, 0 },
66 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TRAILINGTEXT
, RGB(255, 255, 255) },
67 { DTM_SETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TRAILINGTEXT
, RGB(100, 180, 220) },
68 { DTM_GETMCCOLOR
, sent
|wparam
|lparam
, MCSC_TRAILINGTEXT
, 0 },
72 static const struct message test_dtm_set_and_get_mcfont_seq
[] = {
73 { DTM_SETMCFONT
, sent
|lparam
, 0, 1 },
74 { DTM_GETMCFONT
, sent
|wparam
|lparam
, 0, 0 },
78 static const struct message test_dtm_get_monthcal_seq
[] = {
79 { DTM_GETMONTHCAL
, sent
|wparam
|lparam
, 0, 0 },
83 static const struct message test_dtm_set_and_get_range_seq
[] = {
84 { DTM_SETRANGE
, sent
|wparam
, GDTR_MIN
},
85 { DTM_GETRANGE
, sent
|wparam
, 0 },
86 { DTM_SETRANGE
, sent
|wparam
, GDTR_MAX
},
87 { DTM_SETRANGE
, sent
|wparam
, GDTR_MAX
},
88 { DTM_GETRANGE
, sent
|wparam
, 0 },
89 { DTM_SETRANGE
, sent
|wparam
, GDTR_MIN
},
90 { DTM_SETRANGE
, sent
|wparam
, GDTR_MIN
| GDTR_MAX
},
91 { DTM_SETRANGE
, sent
|wparam
, GDTR_MIN
| GDTR_MAX
},
92 { DTM_GETRANGE
, sent
|wparam
, 0 },
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 },
100 static const struct message test_dtm_set_range_swap_min_max_seq
[] = {
101 { DTM_SETSYSTEMTIME
, sent
|wparam
, 0 },
102 { DTM_GETSYSTEMTIME
, sent
|wparam
, 0 },
103 { DTM_SETRANGE
, sent
|wparam
, GDTR_MIN
| GDTR_MAX
},
104 { DTM_GETRANGE
, sent
|wparam
, 0 },
105 { DTM_SETSYSTEMTIME
, sent
|wparam
, 0 },
106 { DTM_GETSYSTEMTIME
, sent
|wparam
, 0 },
107 { DTM_SETRANGE
, sent
|wparam
, GDTR_MIN
| GDTR_MAX
},
108 { DTM_GETRANGE
, 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 },
116 static const struct message test_dtm_set_and_get_system_time_seq
[] = {
117 { DTM_SETSYSTEMTIME
, sent
|wparam
, GDT_NONE
},
118 { DTM_GETSYSTEMTIME
, sent
|wparam
, 0 },
119 { DTM_SETSYSTEMTIME
, sent
|wparam
, 0 },
120 { DTM_SETSYSTEMTIME
, sent
|wparam
, 0 },
121 { DTM_SETSYSTEMTIME
, sent
|wparam
, 0 },
122 { DTM_GETSYSTEMTIME
, sent
|wparam
, 0 },
123 { DTM_SETSYSTEMTIME
, sent
|wparam
, 0 },
127 static const struct message test_dtm_set_and_get_systime_with_limits
[] = {
128 { DTM_SETRANGE
, sent
|wparam
, GDTR_MIN
| GDTR_MAX
},
129 { DTM_GETRANGE
, sent
|wparam
, 0 },
130 { DTM_SETSYSTEMTIME
, sent
|wparam
, 0 },
131 { DTM_GETSYSTEMTIME
, 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 },
139 static LRESULT WINAPI
datetime_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
141 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
142 static LONG defwndproc_counter
= 0;
143 struct message msg
= { 0 };
146 msg
.message
= message
;
147 msg
.flags
= sent
|wparam
|lparam
;
148 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
151 add_message(sequences
, DATETIME_SEQ_INDEX
, &msg
);
153 defwndproc_counter
++;
154 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
155 defwndproc_counter
--;
160 static HWND
create_datetime_control(DWORD style
)
163 HWND hWndDateTime
= NULL
;
165 hWndDateTime
= CreateWindowExA(0,
175 if (!hWndDateTime
) return NULL
;
177 oldproc
= (WNDPROC
)SetWindowLongPtrA(hWndDateTime
, GWLP_WNDPROC
,
178 (LONG_PTR
)datetime_subclass_proc
);
179 SetWindowLongPtrA(hWndDateTime
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
184 static void test_dtm_set_format(void)
191 hWnd
= create_datetime_control(DTS_SHOWNONE
);
193 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
195 r
= SendMessageA(hWnd
, DTM_SETFORMATA
, 0, 0);
198 r
= SendMessageA(hWnd
, DTM_SETFORMATA
, 0,
199 (LPARAM
)"'Today is: 'hh':'m':'s dddd MMM dd', 'yyyy");
202 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_set_format_seq
, "test_dtm_set_format", FALSE
);
204 r
= SendMessageA(hWnd
, DTM_SETFORMATA
, 0, (LPARAM
)"'hh' hh");
206 ZeroMemory(&systime
, sizeof(systime
));
207 systime
.wYear
= 2000;
208 systime
.wMonth
= systime
.wDay
= 1;
209 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, 0, (LPARAM
)&systime
);
211 GetWindowTextA(hWnd
, txt
, 256);
212 ok(strcmp(txt
, "hh 12") == 0, "String mismatch (\"%s\" vs \"hh 12\")\n", txt
);
217 static void test_mccolor_types(HWND hWndDateTime
, int mccolor_type
, const char* mccolor_name
)
219 COLORREF theColor
, prevColor
, crColor
;
222 crColor
= SendMessageA(hWndDateTime
, DTM_SETMCCOLOR
, mccolor_type
, theColor
);
223 ok(crColor
!= ~0u, "%s: Set RGB(0,0,0): Expected COLORREF of previous value, got %d\n", mccolor_name
, crColor
);
225 theColor
=RGB(255,255,255);
226 crColor
= SendMessageA(hWndDateTime
, DTM_SETMCCOLOR
, mccolor_type
, theColor
);
227 ok(crColor
==prevColor
, "%s: Set RGB(255,255,255): Expected COLORREF of previous value, got %d\n", mccolor_name
, crColor
);
229 theColor
=RGB(100,180,220);
230 crColor
= SendMessageA(hWndDateTime
, DTM_SETMCCOLOR
, mccolor_type
, theColor
);
231 ok(crColor
==prevColor
, "%s: Set RGB(100,180,220): Expected COLORREF of previous value, got %d\n", mccolor_name
, crColor
);
232 crColor
= SendMessageA(hWndDateTime
, DTM_GETMCCOLOR
, mccolor_type
, 0);
233 ok(crColor
==theColor
, "%s: GETMCCOLOR: Expected %d, got %d\n", mccolor_name
, theColor
, crColor
);
236 static void test_dtm_set_and_get_mccolor(void)
240 hWnd
= create_datetime_control(DTS_SHOWNONE
);
242 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
244 test_mccolor_types(hWnd
, MCSC_BACKGROUND
, "MCSC_BACKGROUND");
245 test_mccolor_types(hWnd
, MCSC_MONTHBK
, "MCSC_MONTHBK");
246 test_mccolor_types(hWnd
, MCSC_TEXT
, "MCSC_TEXT");
247 test_mccolor_types(hWnd
, MCSC_TITLEBK
, "MCSC_TITLEBK");
248 test_mccolor_types(hWnd
, MCSC_TITLETEXT
, "MCSC_TITLETEXT");
249 test_mccolor_types(hWnd
, MCSC_TRAILINGTEXT
, "MCSC_TRAILINGTEXT");
251 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_set_and_get_mccolor_seq
, "test_dtm_set_and_get_mccolor", FALSE
);
256 static void test_dtm_set_and_get_mcfont(void)
258 HFONT hFontOrig
, hFontNew
;
261 hWnd
= create_datetime_control(DTS_SHOWNONE
);
263 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
265 hFontOrig
= GetStockObject(DEFAULT_GUI_FONT
);
266 SendMessageA(hWnd
, DTM_SETMCFONT
, (WPARAM
)hFontOrig
, TRUE
);
267 hFontNew
= (HFONT
)SendMessageA(hWnd
, DTM_GETMCFONT
, 0, 0);
268 ok(hFontOrig
== hFontNew
, "Expected hFontOrig==hFontNew, hFontOrig=%p, hFontNew=%p\n", hFontOrig
, hFontNew
);
270 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_set_and_get_mcfont_seq
, "test_dtm_set_and_get_mcfont", FALSE
);
274 static void test_dtm_get_monthcal(void)
279 hWnd
= create_datetime_control(DTS_SHOWNONE
);
281 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
284 r
= SendMessageA(hWnd
, DTM_GETMONTHCAL
, 0, 0);
285 ok(r
== 0, "Expected NULL(no child month calendar control), got %ld\n", r
);
288 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_get_monthcal_seq
, "test_dtm_get_monthcal", FALSE
);
292 static void fill_systime_struct(SYSTEMTIME
*st
, int year
, int month
, int dayofweek
, int day
, int hour
, int minute
, int second
, int milliseconds
)
296 st
->wDayOfWeek
= dayofweek
;
299 st
->wMinute
= minute
;
300 st
->wSecond
= second
;
301 st
->wMilliseconds
= milliseconds
;
304 static LPARAM
compare_systime_date(SYSTEMTIME
*st1
, SYSTEMTIME
*st2
)
306 return (st1
->wYear
== st2
->wYear
)
307 && (st1
->wMonth
== st2
->wMonth
)
308 && (st1
->wDayOfWeek
== st2
->wDayOfWeek
)
309 && (st1
->wDay
== st2
->wDay
);
312 static LPARAM
compare_systime_time(SYSTEMTIME
*st1
, SYSTEMTIME
*st2
)
314 return (st1
->wHour
== st2
->wHour
)
315 && (st1
->wMinute
== st2
->wMinute
)
316 && (st1
->wSecond
== st2
->wSecond
)
317 && (st1
->wMilliseconds
== st2
->wMilliseconds
);
320 static LPARAM
compare_systime(SYSTEMTIME
*st1
, SYSTEMTIME
*st2
)
322 if(!compare_systime_date(st1
, st2
))
325 return compare_systime_time(st1
, st2
);
328 #define expect_systime(ST1, ST2) ok(compare_systime((ST1), (ST2))==1, "ST1 != ST2\n")
329 #define expect_systime_date(ST1, ST2) ok(compare_systime_date((ST1), (ST2))==1, "ST1.date != ST2.date\n")
330 #define expect_systime_time(ST1, ST2) ok(compare_systime_time((ST1), (ST2))==1, "ST1.time != ST2.time\n")
332 static void test_dtm_set_and_get_range(void)
339 hWnd
= create_datetime_control(DTS_SHOWNONE
);
341 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
343 /* initialize st[0] to lowest possible value */
344 fill_systime_struct(&st
[0], 1601, 1, 0, 1, 0, 0, 0, 0);
345 /* initialize st[1] to all invalid numbers */
346 fill_systime_struct(&st
[1], 0, 0, 7, 0, 24, 60, 60, 1000);
348 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
, (LPARAM
)st
);
350 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
351 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
);
352 expect_systime(&st
[0], &getSt
[0]);
354 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MAX
, (LPARAM
)st
);
355 expect_unsuccess(0, r
);
357 /* set st[0] to all invalid numbers */
358 fill_systime_struct(&st
[0], 0, 0, 7, 0, 24, 60, 60, 1000);
359 /* set st[1] to highest possible value */
360 fill_systime_struct(&st
[1], 30827, 12, 6, 31, 23, 59, 59, 999);
362 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MAX
, (LPARAM
)st
);
364 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
365 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
);
366 expect_systime(&st
[1], &getSt
[1]);
368 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
, (LPARAM
)st
);
369 expect_unsuccess(0, r
);
370 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
371 expect_unsuccess(0, r
);
373 /* set st[0] to highest possible value */
374 fill_systime_struct(&st
[0], 30827, 12, 6, 31, 23, 59, 59, 999);
376 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
378 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
379 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
);
380 expect_systime(&st
[0], &getSt
[0]);
381 expect_systime(&st
[1], &getSt
[1]);
383 /* initialize st[0] to lowest possible value */
384 fill_systime_struct(&st
[0], 1601, 1, 0, 1, 0, 0, 0, 0);
385 /* set st[1] to highest possible value */
386 fill_systime_struct(&st
[1], 30827, 12, 6, 31, 23, 59, 59, 999);
388 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
390 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
391 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
);
392 expect_systime(&st
[0], &getSt
[0]);
393 expect_systime(&st
[1], &getSt
[1]);
395 /* set st[0] to value higher than minimum */
396 fill_systime_struct(&st
[0], 1980, 1, 3, 23, 14, 34, 37, 465);
397 /* set st[1] to value lower than maximum */
398 fill_systime_struct(&st
[1], 2007, 3, 2, 31, 23, 59, 59, 999);
400 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
402 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
403 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
);
404 expect_systime(&st
[0], &getSt
[0]);
405 expect_systime(&st
[1], &getSt
[1]);
407 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_set_and_get_range_seq
, "test_dtm_set_and_get_range", FALSE
);
409 /* DTM_SETRANGE with 0 flags */
410 r
= SendMessageA(hWnd
, DTM_SETRANGE
, 0, (LPARAM
)st
);
411 ok(r
, "got %lu\n", r
);
412 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
413 ok(r
== 0, "got %lu\n", r
);
414 ok(getSt
[0].wYear
== 0 && getSt
[1].wYear
== 0, "got %u, %u\n", getSt
[0].wYear
, getSt
[1].wYear
);
419 /* when max<min for DTM_SETRANGE, Windows seems to swap the min and max values,
420 although that's undocumented. However, it doesn't seem to be implemented
421 correctly, causing some strange side effects */
422 static void test_dtm_set_range_swap_min_max(void)
430 hWnd
= create_datetime_control(DTS_SHOWNONE
);
431 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
433 fill_systime_struct(&st
[0], 2007, 2, 4, 15, 2, 2, 2, 2);
435 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
[0]);
437 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&origSt
);
438 ok(r
== GDT_VALID
, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID
, GDT_NONE
, GDT_ERROR
, r
);
439 expect_systime(&st
[0], &origSt
);
441 /* set st[0] to value higher than st[1] */
442 fill_systime_struct(&st
[0], 2007, 3, 2, 31, 23, 59, 59, 999);
443 fill_systime_struct(&st
[1], 1980, 1, 3, 23, 14, 34, 37, 465);
445 /* since min>max, min and max values should be swapped by DTM_SETRANGE
447 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
449 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
450 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
);
452 ok(compare_systime(&st
[0], &getSt
[0]) == 1 ||
453 broken(compare_systime(&st
[0], &getSt
[1]) == 1), /* comctl32 version <= 5.80 */
456 ok(compare_systime(&st
[1], &getSt
[1]) == 1 ||
457 broken(compare_systime(&st
[1], &getSt
[0]) == 1), /* comctl32 version <= 5.80 */
461 fill_systime_struct(&st
[0], 1980, 1, 3, 23, 14, 34, 37, 465);
463 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
[0]);
465 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
[0]);
466 ok(r
== GDT_VALID
, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID
, GDT_NONE
, GDT_ERROR
, r
);
467 /* the time part seems to not change after swapping the min and max values
468 and doing DTM_SETSYSTEMTIME */
469 expect_systime_date(&st
[0], &getSt
[0]);
471 ok(compare_systime_time(&origSt
, &getSt
[0]) == 1 ||
472 broken(compare_systime_time(&st
[0], &getSt
[0]) == 1), /* comctl32 version <= 5.80 */
473 "ST1.time != ST2.time\n");
476 /* set st[0] to value higher than minimum */
477 fill_systime_struct(&st
[0], 1980, 1, 3, 23, 14, 34, 37, 465);
478 /* set st[1] to value lower than maximum */
479 fill_systime_struct(&st
[1], 2007, 3, 2, 31, 23, 59, 59, 999);
481 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
483 /* for some reason after we swapped the min and max values before,
484 whenever we do a DTM_SETRANGE, the DTM_GETRANGE will return the values
486 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
487 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
);
489 ok(compare_systime(&st
[0], &getSt
[1]) == 1 ||
490 broken(compare_systime(&st
[0], &getSt
[0]) == 1), /* comctl32 version <= 5.80 */
493 ok(compare_systime(&st
[1], &getSt
[0]) == 1 ||
494 broken(compare_systime(&st
[1], &getSt
[1]) == 1), /* comctl32 version <= 5.80 */
498 /* set st[0] to value higher than st[1] */
499 fill_systime_struct(&st
[0], 2007, 3, 2, 31, 23, 59, 59, 999);
500 fill_systime_struct(&st
[1], 1980, 1, 3, 23, 14, 34, 37, 465);
502 /* set min>max again, so that the return values of DTM_GETRANGE are no
503 longer swapped the next time we do a DTM SETRANGE and DTM_GETRANGE*/
504 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
506 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
507 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
);
508 expect_systime(&st
[0], &getSt
[1]);
509 expect_systime(&st
[1], &getSt
[0]);
511 /* initialize st[0] to lowest possible value */
512 fill_systime_struct(&st
[0], 1601, 1, 0, 1, 0, 0, 0, 0);
513 /* set st[1] to highest possible value */
514 fill_systime_struct(&st
[1], 30827, 12, 6, 31, 23, 59, 59, 999);
516 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
518 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
519 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
);
520 expect_systime(&st
[0], &getSt
[0]);
521 expect_systime(&st
[1], &getSt
[1]);
523 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_set_range_swap_min_max_seq
, "test_dtm_set_range_swap_min_max", FALSE
);
528 static void test_dtm_set_and_get_system_time(void)
531 SYSTEMTIME st
, getSt
, ref
;
534 hWnd
= create_datetime_control(0);
535 ok(hWnd
!=NULL
, "Expected non NULL, got %p\n", hWnd
);
536 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_NONE
, (LPARAM
)&st
);
541 hWnd
= create_datetime_control(DTS_SHOWNONE
);
542 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
544 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_NONE
, (LPARAM
)&st
);
546 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
547 ok(r
== GDT_NONE
, "Expected %d, not %d(GDT_VALID) or %d(GDT_ERROR), got %ld\n", GDT_NONE
, GDT_VALID
, GDT_ERROR
, r
);
549 /* set st to lowest possible value */
550 fill_systime_struct(&st
, 1601, 1, 0, 1, 0, 0, 0, 0);
552 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
555 /* set st to highest possible value */
556 fill_systime_struct(&st
, 30827, 12, 6, 31, 23, 59, 59, 999);
558 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
561 /* set st to value between min and max */
562 fill_systime_struct(&st
, 1980, 1, 3, 23, 14, 34, 37, 465);
564 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
566 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
567 ok(r
== GDT_VALID
, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID
, GDT_NONE
, GDT_ERROR
, r
);
568 expect_systime(&st
, &getSt
);
570 /* set st to invalid value */
571 fill_systime_struct(&st
, 0, 0, 7, 0, 24, 60, 60, 1000);
573 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
574 expect_unsuccess(0, r
);
576 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_set_and_get_system_time_seq
, "test_dtm_set_and_get_system_time", FALSE
);
578 /* set to some valid value */
580 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&ref
);
582 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
583 expect(GDT_VALID
, r
);
584 expect_systime(&ref
, &getSt
);
589 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
590 todo_wine
expect(1, r
);
591 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
592 expect(GDT_VALID
, r
);
593 expect_systime(&ref
, &getSt
);
597 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
599 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
600 expect(GDT_VALID
, r
);
601 expect_systime(&ref
, &getSt
);
605 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
607 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
608 expect(GDT_VALID
, r
);
609 expect_systime(&ref
, &getSt
);
610 /* day invalid for current month */
614 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
616 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
617 expect(GDT_VALID
, r
);
618 expect_systime(&ref
, &getSt
);
619 /* day of week isn't validated */
622 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
624 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
625 expect(GDT_VALID
, r
);
626 expect_systime(&ref
, &getSt
);
630 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
632 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
633 expect(GDT_VALID
, r
);
634 expect_systime(&ref
, &getSt
);
638 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
640 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
641 expect(GDT_VALID
, r
);
642 expect_systime(&ref
, &getSt
);
646 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
648 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
649 expect(GDT_VALID
, r
);
650 expect_systime(&ref
, &getSt
);
653 st
.wMilliseconds
= 1000;
654 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
656 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
657 expect(GDT_VALID
, r
);
658 expect_systime(&ref
, &getSt
);
660 /* day of week should be calculated automatically,
661 actual day of week for this date is 4 */
662 fill_systime_struct(&st
, 2009, 10, 1, 1, 0, 0, 10, 200);
663 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
);
665 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
);
666 expect(GDT_VALID
, r
);
667 /* 01.10.2009 is Thursday */
668 expect(4, (LRESULT
)getSt
.wDayOfWeek
);
670 expect_systime(&st
, &getSt
);
673 static void test_dtm_set_and_get_systemtime_with_limits(void)
676 SYSTEMTIME st
[2], getSt
[2], refSt
;
679 hWnd
= create_datetime_control(DTS_SHOWNONE
);
681 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
684 fill_systime_struct(&st
[0], 1980, 1, 3, 23, 14, 34, 37, 465);
685 fill_systime_struct(&st
[1], 2007, 3, 2, 31, 23, 59, 59, 999);
687 r
= SendMessageA(hWnd
, DTM_SETRANGE
, GDTR_MIN
| GDTR_MAX
, (LPARAM
)st
);
689 r
= SendMessageA(hWnd
, DTM_GETRANGE
, 0, (LPARAM
)getSt
);
690 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
);
691 expect_systime(&st
[0], &getSt
[0]);
692 expect_systime(&st
[1], &getSt
[1]);
694 /* Initially set a valid time */
695 fill_systime_struct(&refSt
, 1999, 9, 4, 9, 19, 9, 9, 999);
696 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&refSt
);
698 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
[0]);
699 ok(r
== GDT_VALID
, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID
, GDT_NONE
, GDT_ERROR
, r
);
700 expect_systime(&refSt
, &getSt
[0]);
702 /* Now set an out-of-bounds time */
703 fill_systime_struct(&st
[0], 2010, 1, 0, 1, 0, 0, 0, 0);
705 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
[0]);
707 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
[0]);
708 ok(r
== GDT_VALID
, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID
, GDT_NONE
, GDT_ERROR
, r
);
709 expect_systime(&refSt
, &getSt
[0]);
711 fill_systime_struct(&st
[0], 1977, 1, 0, 1, 0, 0, 0, 0);
713 r
= SendMessageA(hWnd
, DTM_SETSYSTEMTIME
, GDT_VALID
, (LPARAM
)&st
[0]);
715 r
= SendMessageA(hWnd
, DTM_GETSYSTEMTIME
, 0, (LPARAM
)&getSt
[0]);
716 ok(r
== GDT_VALID
, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID
, GDT_NONE
, GDT_ERROR
, r
);
717 expect_systime(&refSt
, &getSt
[0]);
719 ok_sequence(sequences
, DATETIME_SEQ_INDEX
, test_dtm_set_and_get_systime_with_limits
, "test_dtm_set_and_get_systime_with_limits", FALSE
);
724 static void test_dtm_get_ideal_size(void)
734 hwnd
= create_datetime_control(0);
735 r
= SendMessageA(hwnd
, DTM_GETIDEALSIZE
, 0, (LPARAM
)&size
);
738 win_skip("DTM_GETIDEALSIZE is not available\n");
743 /* Set font so that the test is consistent on Wine and Windows */
744 ZeroMemory(&lf
, sizeof(lf
));
745 lf
.lfWeight
= FW_NORMAL
;
747 lstrcpyA(lf
.lfFaceName
, "Tahoma");
748 hfont
= CreateFontIndirectA(&lf
);
749 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)hfont
, (LPARAM
)TRUE
);
752 GetTextMetricsA(hdc
, &tm
);
753 ReleaseDC(hwnd
, hdc
);
755 r
= SendMessageA(hwnd
, DTM_GETIDEALSIZE
, 0, (LPARAM
)&size
);
756 ok(r
, "Expect DTM_GETIDEALSIZE message to return true\n");
757 ok(size
.cx
> 0 && size
.cy
>= tm
.tmHeight
,
758 "Expect size.cx > 0 and size.cy >= %d, got cx:%d cy:%d\n", tm
.tmHeight
, size
.cx
, size
.cy
);
764 static void test_wm_set_get_text(void)
766 static const CHAR a_str
[] = "a";
767 CHAR buff
[16], time
[16], caltype
[3];
772 hWnd
= create_datetime_control(0);
774 ret
= SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)a_str
);
776 broken(0 == ret
) || /* comctl32 <= 4.72 */
777 broken(1 == ret
), /* comctl32 <= 4.70 */
778 "Expected CB_ERR, got %ld\n", ret
);
781 ret
= SendMessageA(hWnd
, WM_GETTEXT
, sizeof(buff
), (LPARAM
)buff
);
782 ok(strcmp(buff
, a_str
) != 0, "Expected text to change, got %s\n", buff
);
783 ok(ret
!= 0, "Expected non-zero return value\n");
785 SetLastError(0xdeadbeef);
786 ret
= GetLocaleInfoA(LOCALE_USER_DEFAULT
, LOCALE_ICALENDARTYPE
, caltype
, 3);
788 skip("Must know local calendar type (%x)\n", GetLastError());
789 else if (atoi(caltype
) != CAL_GREGORIAN
)
790 skip("DateTimePicker Control only supports Gregorian calendar (type: %s)\n", caltype
);
792 SetLastError(0xdeadbeef);
793 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
, 0, NULL
, NULL
, time
, sizeof(time
));
795 skip("GetDateFormat failed, returned %ld, error %d\n", ret
, GetLastError());
798 ok(!strcmp(buff
, time
), "Expected %s, got %s\n", time
, buff
);
800 ret
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
801 ok(ret
== strlen(time
), "Got wrong length: %ld, expected %d.\n", ret
, strlen(time
));
807 /* Window text is not preserved. */
808 hWnd
= CreateWindowExA(0, DATETIMEPICK_CLASSA
, "testname", 0, 0, 50, 300, 120,
809 NULL
, NULL
, NULL
, NULL
);
812 InternalGetWindowText(hWnd
, buffW
, ARRAY_SIZE(buffW
));
813 ok(!buffW
[0], "Unexpected window text %s.\n", wine_dbgstr_w(buffW
));
818 static void test_dts_shownone(void)
823 /* it isn't allowed to change DTS_SHOWNONE after creation */
824 hwnd
= create_datetime_control(0);
825 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
826 SetWindowLongA(hwnd
, GWL_STYLE
, style
| DTS_SHOWNONE
);
827 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
828 ok(!(style
& DTS_SHOWNONE
), "Expected DTS_SHOWNONE not to be set\n");
831 hwnd
= create_datetime_control(DTS_SHOWNONE
);
832 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
833 SetWindowLongA(hwnd
, GWL_STYLE
, style
& ~DTS_SHOWNONE
);
834 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
835 ok(style
& DTS_SHOWNONE
, "Expected DTS_SHOWNONE to be set\n");
839 static void init_functions(void)
841 HMODULE hComCtl32
= LoadLibraryA("comctl32.dll");
843 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
844 X(InitCommonControlsEx
);
850 INITCOMMONCONTROLSEX iccex
;
856 iccex
.dwSize
= sizeof(iccex
);
857 iccex
.dwICC
= ICC_DATE_CLASSES
;
858 pInitCommonControlsEx(&iccex
);
860 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
862 test_dtm_set_format();
863 test_dtm_set_and_get_mccolor();
864 test_dtm_set_and_get_mcfont();
865 test_dtm_get_monthcal();
866 test_dtm_set_and_get_range();
867 test_dtm_set_range_swap_min_max();
868 test_dtm_set_and_get_system_time();
869 test_dtm_set_and_get_systemtime_with_limits();
870 test_wm_set_get_text();
873 if (!load_v6_module(&cookie
, &ctxt
))
876 test_dtm_set_format();
877 test_dtm_set_and_get_mccolor();
878 test_dtm_set_and_get_mcfont();
879 test_dtm_get_monthcal();
880 test_dtm_get_ideal_size();
881 test_wm_set_get_text();
884 unload_v6_module(cookie
, ctxt
);