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