1 /* 2 * comctl32 month calendar unit tests 3 * 4 * Copyright (C) 2006 Vitaliy Margolen 5 * Copyright (C) 2007 Farshad Agah 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 24 #include "windef.h" 25 #include "winbase.h" 26 #include "winuser.h" 27 28 #include "commctrl.h" 29 30 #include "wine/test.h" 31 #include "v6util.h" 32 #include <windows.h> 33 #include "msg.h" 34 35 #define expect(expected, got) ok(expected == got, "Expected %d, got %d\n", expected, got); 36 #define expect_hex(expected, got) ok(expected == got, "Expected %x, got %x\n", expected, got); 37 #define expect_d(expected, got) ok(abs((expected) - (got)) <= 2, "Expected %d, got %d\n", expected, got); 38 39 #define NUM_MSG_SEQUENCES 2 40 #define PARENT_SEQ_INDEX 0 41 #define MONTHCAL_SEQ_INDEX 1 42 43 #define SEL_NOTIFY_TEST_ID 100 44 45 static BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); 46 47 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES]; 48 49 static HWND parent_wnd; 50 51 static const struct message create_parent_window_seq[] = { 52 { WM_GETMINMAXINFO, sent }, 53 { WM_NCCREATE, sent }, 54 { WM_NCCALCSIZE, sent|wparam, 0 }, 55 { WM_CREATE, sent }, 56 { WM_SHOWWINDOW, sent|wparam, 1 }, 57 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, 58 { WM_QUERYNEWPALETTE, sent|optional }, 59 { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, 60 { WM_WINDOWPOSCHANGED, sent|optional }, 61 { WM_ACTIVATEAPP, sent|wparam, 1 }, 62 { WM_NCACTIVATE, sent }, 63 { WM_ACTIVATE, sent|wparam, 1 }, 64 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, 65 { WM_IME_NOTIFY, sent|defwinproc|optional }, 66 { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, 67 /* Win9x adds SWP_NOZORDER below */ 68 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, 69 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, 70 { WM_SIZE, sent }, 71 { WM_MOVE, sent }, 72 { 0 } 73 }; 74 75 static const struct message create_monthcal_control_seq[] = { 76 { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY }, 77 { WM_QUERYUISTATE, sent|optional }, 78 { WM_GETFONT, sent }, 79 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE}, 80 { 0 } 81 }; 82 83 static const struct message create_monthcal_multi_sel_style_seq[] = { 84 { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY }, 85 { WM_QUERYUISTATE, sent|optional }, 86 { WM_GETFONT, sent }, 87 { WM_PARENTNOTIFY, sent }, 88 { 0 } 89 }; 90 91 static const struct message monthcal_curr_date_seq[] = { 92 { MCM_SETCURSEL, sent|wparam, 0}, 93 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0}, 94 { MCM_SETCURSEL, sent|wparam, 0}, 95 { MCM_SETCURSEL, sent|wparam, 0}, 96 { MCM_GETCURSEL, sent|wparam, 0}, 97 { MCM_GETCURSEL, sent|wparam|lparam, 0, 0}, 98 { 0 } 99 }; 100 101 static const struct message monthcal_first_day_seq[] = { 102 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 103 104 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -5}, 105 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 106 107 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -4}, 108 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 109 110 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -3}, 111 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 112 113 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -2}, 114 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 115 116 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -1}, 117 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 118 119 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 120 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 121 122 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 1}, 123 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 124 125 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 2}, 126 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 127 128 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 3}, 129 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 130 131 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 4}, 132 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 133 134 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 5}, 135 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 136 137 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 6}, 138 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 139 140 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 7}, 141 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 142 143 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 8}, 144 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 145 146 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 9}, 147 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 148 149 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 10}, 150 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 151 152 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 11}, 153 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0}, 154 { 0 } 155 }; 156 157 static const struct message monthcal_unicode_seq[] = { 158 { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0}, 159 { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0}, 160 { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0}, 161 { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0}, 162 { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0}, 163 { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0}, 164 { 0 } 165 }; 166 167 static const struct message monthcal_hit_test_seq[] = { 168 { MCM_SETCURSEL, sent|wparam, 0}, 169 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0}, 170 { MCM_HITTEST, sent|wparam, 0}, 171 { MCM_HITTEST, sent|wparam, 0}, 172 { MCM_HITTEST, sent|wparam, 0}, 173 { MCM_HITTEST, sent|wparam, 0}, 174 { MCM_HITTEST, sent|wparam, 0}, 175 { MCM_HITTEST, sent|wparam, 0}, 176 { MCM_HITTEST, sent|wparam, 0}, 177 { MCM_HITTEST, sent|wparam, 0}, 178 { MCM_HITTEST, sent|wparam, 0}, 179 { MCM_HITTEST, sent|wparam, 0}, 180 { 0 } 181 }; 182 183 static const struct message monthcal_todaylink_seq[] = { 184 { MCM_HITTEST, sent|wparam, 0}, 185 { MCM_SETTODAY, sent|wparam, 0}, 186 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0}, 187 { MCM_GETTODAY, sent|wparam, 0}, 188 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON}, 189 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0}, 190 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0}, 191 { MCM_GETCURSEL, sent|wparam, 0}, 192 { 0 } 193 }; 194 195 static const struct message monthcal_today_seq[] = { 196 { MCM_SETTODAY, sent|wparam, 0}, 197 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0}, 198 { MCM_GETTODAY, sent|wparam, 0}, 199 { MCM_SETTODAY, sent|wparam, 0}, 200 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0}, 201 { MCM_GETTODAY, sent|wparam, 0}, 202 { 0 } 203 }; 204 205 static const struct message monthcal_scroll_seq[] = { 206 { MCM_SETMONTHDELTA, sent|wparam|lparam, 2, 0}, 207 { MCM_SETMONTHDELTA, sent|wparam|lparam, 3, 0}, 208 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0}, 209 { MCM_SETMONTHDELTA, sent|wparam|lparam, 12, 0}, 210 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0}, 211 { MCM_SETMONTHDELTA, sent|wparam|lparam, 15, 0}, 212 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0}, 213 { MCM_SETMONTHDELTA, sent|wparam|lparam, -5, 0}, 214 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0}, 215 { 0 } 216 }; 217 218 static const struct message monthcal_monthrange_seq[] = { 219 { MCM_GETMONTHRANGE, sent|wparam, GMR_VISIBLE}, 220 { MCM_GETMONTHRANGE, sent|wparam, GMR_DAYSTATE}, 221 { 0 } 222 }; 223 224 static const struct message monthcal_max_sel_day_seq[] = { 225 { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 5, 0}, 226 { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0}, 227 { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 15, 0}, 228 { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0}, 229 { MCM_SETMAXSELCOUNT, sent|wparam|lparam, -1, 0}, 230 { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0}, 231 { 0 } 232 }; 233 234 /* expected message sequence for parent*/ 235 static const struct message destroy_monthcal_parent_msgs_seq[] = { 236 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY}, 237 { 0 } 238 }; 239 240 /* expected message sequence for child*/ 241 static const struct message destroy_monthcal_child_msgs_seq[] = { 242 { 0x0090, sent|optional }, /* Vista */ 243 { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0}, 244 { WM_WINDOWPOSCHANGING, sent|wparam, 0}, 245 { WM_WINDOWPOSCHANGED, sent|wparam, 0}, 246 { WM_DESTROY, sent|wparam|lparam, 0, 0}, 247 { WM_NCDESTROY, sent|wparam|lparam, 0, 0}, 248 { 0 } 249 }; 250 251 static const struct message destroy_monthcal_multi_sel_style_seq[] = { 252 { 0x0090, sent|optional }, /* Vista */ 253 { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0}, 254 { WM_WINDOWPOSCHANGING, sent|wparam, 0}, 255 { WM_WINDOWPOSCHANGED, sent|wparam, 0}, 256 { WM_DESTROY, sent|wparam|lparam, 0, 0}, 257 { WM_NCDESTROY, sent|wparam|lparam, 0, 0}, 258 { 0 } 259 }; 260 261 static void test_monthcal(void) 262 { 263 HWND hwnd; 264 SYSTEMTIME st[2], st1[2], today; 265 int res, month_range; 266 DWORD limits; 267 BOOL r; 268 269 hwnd = CreateWindowA(MONTHCAL_CLASSA, "MonthCal", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT, 270 0, 300, 300, 0, 0, NULL, NULL); 271 ok(hwnd != NULL, "Failed to create MonthCal\n"); 272 273 /* test range just after creation */ 274 memset(&st, 0xcc, sizeof(st)); 275 limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st); 276 ok(limits == 0 || 277 broken(limits == GDTR_MIN), /* comctl32 <= 4.70 */ 278 "No limits should be set (%d)\n", limits); 279 if (limits == GDTR_MIN) 280 { 281 win_skip("comctl32 <= 4.70 is broken\n"); 282 DestroyWindow(hwnd); 283 return; 284 } 285 286 ok(0 == st[0].wYear || 287 broken(1752 == st[0].wYear), /* comctl32 <= 4.72 */ 288 "Expected 0, got %d\n", st[0].wYear); 289 ok(0 == st[0].wMonth || 290 broken(9 == st[0].wMonth), /* comctl32 <= 4.72 */ 291 "Expected 0, got %d\n", st[0].wMonth); 292 ok(0 == st[0].wDay || 293 broken(14 == st[0].wDay), /* comctl32 <= 4.72 */ 294 "Expected 0, got %d\n", st[0].wDay); 295 expect(0, st[0].wDayOfWeek); 296 expect(0, st[0].wHour); 297 expect(0, st[0].wMinute); 298 expect(0, st[0].wSecond); 299 expect(0, st[0].wMilliseconds); 300 301 expect(0, st[1].wYear); 302 expect(0, st[1].wMonth); 303 expect(0, st[1].wDay); 304 expect(0, st[1].wDayOfWeek); 305 expect(0, st[1].wHour); 306 expect(0, st[1].wMinute); 307 expect(0, st[1].wSecond); 308 expect(0, st[1].wMilliseconds); 309 310 limits = SendMessageA(hwnd, MCM_GETRANGE, 0, 0); 311 ok(limits == 0, "got %u\n", limits); 312 313 GetSystemTime(&st[0]); 314 st[1] = st[0]; 315 316 SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&today); 317 318 /* Invalid date/time */ 319 st[0].wYear = 2000; 320 /* Time should not matter */ 321 st[1].wHour = st[1].wMinute = st[1].wSecond = 70; 322 st[1].wMilliseconds = 1200; 323 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n"); 324 /* invalid timestamp is written back with today data and msecs untouched */ 325 expect(today.wHour, st[1].wHour); 326 expect(today.wMinute, st[1].wMinute); 327 expect(today.wSecond, st[1].wSecond); 328 expect(1200, st[1].wMilliseconds); 329 330 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n"); 331 ok(st1[0].wYear != 2000, "Lower limit changed\n"); 332 /* invalid timestamp should be replaced with today data, except msecs */ 333 expect(today.wHour, st1[1].wHour); 334 expect(today.wMinute, st1[1].wMinute); 335 expect(today.wSecond, st1[1].wSecond); 336 expect(1200, st1[1].wMilliseconds); 337 338 /* Invalid date/time with invalid milliseconds only */ 339 GetSystemTime(&st[0]); 340 st[1] = st[0]; 341 /* Time should not matter */ 342 st[1].wMilliseconds = 1200; 343 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n"); 344 /* invalid milliseconds field doesn't lead to invalid timestamp */ 345 expect(st[0].wHour, st[1].wHour); 346 expect(st[0].wMinute, st[1].wMinute); 347 expect(st[0].wSecond, st[1].wSecond); 348 expect(1200, st[1].wMilliseconds); 349 350 GetSystemTime(&st[0]); 351 352 st[1].wMonth = 0; 353 ok(!SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), 354 "Should have failed to set limits\n"); 355 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n"); 356 ok(st1[0].wYear != 2000, "Lower limit changed\n"); 357 ok(!SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), 358 "Should have failed to set MAX limit\n"); 359 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n"); 360 ok(st1[0].wYear != 2000, "Lower limit changed\n"); 361 362 GetSystemTime(&st[0]); 363 st[0].wDay = 20; 364 st[0].wMonth = 5; 365 st[1] = st[0]; 366 367 month_range = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1); 368 st[1].wMonth--; 369 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), 370 "Failed to set both min and max limits\n"); 371 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1); 372 ok(res == month_range, "Invalid month range (%d)\n", res); 373 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX), 374 "Limits should be set\n"); 375 376 st[1].wMonth += 2; 377 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), 378 "Failed to set both min and max limits\n"); 379 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1); 380 ok(res == month_range, "Invalid month range (%d)\n", res); 381 382 st[1].wYear --; 383 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), 384 "Failed to set both min and max limits\n"); 385 st[1].wYear += 1; 386 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), 387 "Failed to set both min and max limits\n"); 388 389 st[1].wMonth -= 3; 390 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n"); 391 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, 392 "Only MAX limit should be set\n"); 393 st[1].wMonth += 4; 394 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n"); 395 st[1].wYear -= 3; 396 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n"); 397 st[1].wYear += 4; 398 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n"); 399 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, 400 "Only MAX limit should be set\n"); 401 402 /* set both limits, then set max < min */ 403 GetSystemTime(&st[0]); 404 st[0].wDay = 25; 405 st[1] = st[0]; 406 st[1].wYear++; 407 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN|GDTR_MAX, (LPARAM)st), "Failed to set limits\n"); 408 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX), 409 "Min limit expected\n"); 410 st[1].wYear -= 2; 411 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set limits\n"); 412 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "Max limit expected\n"); 413 414 expect(0, st1[0].wYear); 415 expect(0, st1[0].wMonth); 416 expect(0, st1[0].wDay); 417 expect(0, st1[0].wDayOfWeek); 418 expect(0, st1[0].wHour); 419 expect(0, st1[0].wMinute); 420 expect(0, st1[0].wSecond); 421 expect(0, st1[0].wMilliseconds); 422 423 expect(st[1].wYear, st1[1].wYear); 424 expect(st[1].wMonth, st1[1].wMonth); 425 expect(st[1].wDay, st1[1].wDay); 426 expect(st[1].wDayOfWeek, st1[1].wDayOfWeek); 427 expect(st[1].wHour, st1[1].wHour); 428 expect(st[1].wMinute, st1[1].wMinute); 429 expect(st[1].wSecond, st1[1].wSecond); 430 expect(st[1].wMilliseconds, st1[1].wMilliseconds); 431 432 st[1] = st[0]; 433 st[1].wYear++; 434 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN|GDTR_MAX, (LPARAM)st), "Failed to set limits\n"); 435 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX), 436 "Min limit expected\n"); 437 st[0].wYear++; /* start == end now */ 438 ok(SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN, (LPARAM)st), "Failed to set limits\n"); 439 ok(SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MIN, "Min limit expected\n"); 440 441 expect(st[0].wYear, st1[0].wYear); 442 expect(st[0].wMonth, st1[0].wMonth); 443 expect(st[0].wDay, st1[0].wDay); 444 expect(st[0].wDayOfWeek, st1[0].wDayOfWeek); 445 expect(st[0].wHour, st1[0].wHour); 446 expect(st[0].wMinute, st1[0].wMinute); 447 expect(st[0].wSecond, st1[0].wSecond); 448 expect(st[0].wMilliseconds, st1[0].wMilliseconds); 449 450 expect(0, st1[1].wYear); 451 expect(0, st1[1].wMonth); 452 expect(0, st1[1].wDay); 453 expect(0, st1[1].wDayOfWeek); 454 expect(0, st1[1].wHour); 455 expect(0, st1[1].wMinute); 456 expect(0, st1[1].wSecond); 457 expect(0, st1[1].wMilliseconds); 458 459 /* 0 limit flags */ 460 limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1); 461 ok(limits == GDTR_MIN, "got 0x%08x\n", limits); 462 463 GetSystemTime(st); 464 st[1] = st[0]; 465 st[1].wYear++; 466 r = SendMessageA(hwnd, MCM_SETRANGE, 0, (LPARAM)st); 467 ok(r, "got %d\n", r); 468 469 limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st); 470 ok(limits == 0, "got 0x%08x\n", limits); 471 ok(st[0].wYear == 0 && st[1].wYear == 0, "got %u, %u\n", st[0].wYear, st[1].wYear); 472 473 /* flags are 0, set min limit */ 474 GetSystemTime(st); 475 st[1] = st[0]; 476 st[1].wYear++; 477 478 r = SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN, (LPARAM)st); 479 ok(r, "got %d\n", r); 480 481 limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1); 482 ok(limits == GDTR_MIN, "got 0x%08x\n", limits); 483 ok(st1[1].wYear == 0, "got %u\n", st1[1].wYear); 484 485 /* now set max limit, check flags */ 486 r = SendMessageA(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st); 487 ok(r, "got %d\n", r); 488 489 limits = SendMessageA(hwnd, MCM_GETRANGE, 0, (LPARAM)st1); 490 ok(limits == GDTR_MAX, "got 0x%08x\n", limits); 491 ok(st1[0].wYear == 0, "got %u\n", st1[0].wYear); 492 493 DestroyWindow(hwnd); 494 } 495 496 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 497 { 498 static LONG defwndproc_counter = 0; 499 LRESULT ret; 500 struct message msg; 501 502 /* log system messages, except for painting */ 503 if (message < WM_USER && 504 message != WM_PAINT && 505 message != WM_ERASEBKGND && 506 message != WM_NCPAINT && 507 message != WM_NCHITTEST && 508 message != WM_GETTEXT && 509 message != WM_GETICON && 510 message != WM_DEVICECHANGE) 511 { 512 msg.message = message; 513 msg.flags = sent|wparam|lparam; 514 if (defwndproc_counter) msg.flags |= defwinproc; 515 msg.wParam = wParam; 516 msg.lParam = lParam; 517 add_message(sequences, PARENT_SEQ_INDEX, &msg); 518 } 519 520 if (message == WM_NOTIFY) 521 { 522 NMHDR *hdr = (NMHDR*)lParam; 523 switch (hdr->code) 524 { 525 case MCN_GETDAYSTATE: 526 { 527 NMDAYSTATE *nmstate = (NMDAYSTATE*)lParam; 528 static MONTHDAYSTATE months[14] = { 0 }; 529 530 ok(nmstate->cDayState > 0, "got %d\n", nmstate->cDayState); 531 ok(nmstate->cDayState <= 14, "got %d\n", nmstate->cDayState); 532 ok(nmstate->prgDayState != NULL, "got %p\n", nmstate->prgDayState); 533 534 nmstate->prgDayState = months; 535 536 return TRUE; 537 } 538 case MCN_SELECT: 539 case MCN_SELCHANGE: 540 { 541 NMSELCHANGE *nmchg = (NMSELCHANGE*)lParam; 542 SYSTEMTIME st[2]; 543 BOOL is_multisel = GetWindowLongPtrA(nmchg->nmhdr.hwndFrom, GWL_STYLE) & MCS_MULTISELECT; 544 545 if(GetWindowLongPtrA(nmchg->nmhdr.hwndFrom, GWLP_ID) != SEL_NOTIFY_TEST_ID) 546 break; 547 SendMessageA(nmchg->nmhdr.hwndFrom, is_multisel ? MCM_GETSELRANGE : MCM_GETCURSEL, 548 0, (LPARAM)st); 549 550 expect(st[0].wYear, nmchg->stSelStart.wYear); 551 expect(st[0].wMonth, nmchg->stSelStart.wMonth); 552 expect(0, nmchg->stSelStart.wDayOfWeek); 553 expect(st[0].wDay, nmchg->stSelStart.wDay); 554 555 if(is_multisel) 556 { 557 expect(st[1].wYear, nmchg->stSelEnd.wYear); 558 expect(st[1].wMonth, nmchg->stSelEnd.wMonth); 559 expect(0, nmchg->stSelEnd.wDayOfWeek); 560 expect(st[1].wDay, nmchg->stSelEnd.wDay); 561 } 562 else 563 ok(!(nmchg->stSelEnd.wYear | nmchg->stSelEnd.wMonth | 564 nmchg->stSelEnd.wDayOfWeek | nmchg->stSelEnd.wDay | 565 nmchg->stSelEnd.wHour | nmchg->stSelEnd.wMinute | 566 nmchg->stSelEnd.wSecond | nmchg->stSelEnd.wMilliseconds), 567 "Non-zero member in stSelEnd\n"); 568 return TRUE; 569 } 570 default: 571 break; 572 } 573 } 574 575 defwndproc_counter++; 576 ret = DefWindowProcA(hwnd, message, wParam, lParam); 577 defwndproc_counter--; 578 579 return ret; 580 } 581 582 static BOOL register_parent_wnd_class(void) 583 { 584 WNDCLASSA cls; 585 586 cls.style = 0; 587 cls.lpfnWndProc = parent_wnd_proc; 588 cls.cbClsExtra = 0; 589 cls.cbWndExtra = 0; 590 cls.hInstance = GetModuleHandleA(NULL); 591 cls.hIcon = 0; 592 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 593 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 594 cls.lpszMenuName = NULL; 595 cls.lpszClassName = "Month-Cal test parent class"; 596 return RegisterClassA(&cls); 597 } 598 599 static HWND create_parent_window(void) 600 { 601 HWND hwnd; 602 603 /* flush message sequences, so we can check the new sequence by the end of function */ 604 flush_sequences(sequences, NUM_MSG_SEQUENCES); 605 606 if (!register_parent_wnd_class()) 607 return NULL; 608 609 hwnd = CreateWindowExA(0, "Month-Cal test parent class", "Month-Cal test parent window", 610 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 611 0, 0, 500, 500, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL); 612 ok(hwnd != NULL, "failed to create parent wnd\n"); 613 614 /* check for message sequences */ 615 ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_window_seq, "create parent window", FALSE); 616 617 return hwnd; 618 } 619 620 static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 621 { 622 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 623 static LONG defwndproc_counter = 0; 624 struct message msg = { 0 }; 625 LRESULT ret; 626 627 msg.message = message; 628 msg.flags = sent|wparam|lparam; 629 if (defwndproc_counter) msg.flags |= defwinproc; 630 msg.wParam = wParam; 631 msg.lParam = lParam; 632 add_message(sequences, MONTHCAL_SEQ_INDEX, &msg); 633 634 /* some debug output for style changing */ 635 if ((message == WM_STYLECHANGING || 636 message == WM_STYLECHANGED) && lParam) 637 { 638 STYLESTRUCT *style = (STYLESTRUCT*)lParam; 639 trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew); 640 } 641 642 defwndproc_counter++; 643 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 644 defwndproc_counter--; 645 646 return ret; 647 } 648 649 static HWND create_monthcal_control(DWORD style) 650 { 651 WNDPROC oldproc; 652 RECT rect; 653 HWND hwnd; 654 BOOL ret; 655 656 hwnd = CreateWindowExA(0, MONTHCAL_CLASSA, "", WS_CHILD | WS_BORDER | WS_VISIBLE | style, 657 0, 0, 300, 400, parent_wnd, NULL, GetModuleHandleA(NULL), NULL); 658 ok(hwnd != NULL, "failed to create monthcal wnd\n"); 659 if (!hwnd) return NULL; 660 661 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, 662 (LONG_PTR)monthcal_subclass_proc); 663 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 664 665 SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0); 666 667 /* make sure calendar grid is 2x1 */ 668 ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&rect); 669 ok(ret, "got %d\n", ret); 670 671 ret = SetWindowPos(hwnd, NULL, 0, 0, rect.right * 5 / 2, rect.bottom * 3 / 2, SWP_NOMOVE); 672 ok(ret, "got %d\n", ret); 673 674 return hwnd; 675 } 676 677 678 /* Setter and Getters Tests */ 679 680 static void test_color(void) 681 { 682 COLORREF color, prev; 683 HWND hwnd; 684 685 hwnd = create_monthcal_control(0); 686 687 /* invalid color index */ 688 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT + 1, 0); 689 expect(~0u, color); 690 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT + 1, RGB(255,255,255)); 691 expect(~0u, prev); 692 693 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0); 694 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(0,0,0)); 695 expect(color, prev); 696 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0); 697 expect(RGB(0,0,0), color); 698 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(255,255,255)); 699 expect(color, prev); 700 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0); 701 expect(RGB(255,255,255), color); 702 703 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0); 704 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(0,0,0)); 705 expect(color, prev); 706 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0); 707 expect(RGB(0,0,0), color); 708 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(255,255,255)); 709 expect(color, prev); 710 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0); 711 expect(RGB(255,255,255), color); 712 713 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0); 714 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(0,0,0)); 715 expect(color, prev); 716 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0); 717 expect(RGB(0,0,0), color); 718 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(255,255,255)); 719 expect(color, prev); 720 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0); 721 expect(RGB(255,255,255), color); 722 723 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0); 724 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(0,0,0)); 725 expect(color, prev); 726 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0); 727 expect(RGB(0,0,0), color); 728 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(255,255,255)); 729 expect(color, prev); 730 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0); 731 expect(RGB(255,255,255), color); 732 733 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0); 734 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(0,0,0)); 735 expect(color, prev); 736 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0); 737 expect(RGB(0,0,0), color); 738 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(255,255,255)); 739 expect(color, prev); 740 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0); 741 expect(RGB(255,255,255), color); 742 743 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0); 744 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(0,0,0)); 745 expect(color, prev); 746 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0); 747 expect(RGB(0,0,0), color); 748 prev = SendMessageA(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(255,255,255)); 749 expect(color, prev); 750 color = SendMessageA(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0); 751 expect(RGB(255,255,255), color); 752 753 DestroyWindow(hwnd); 754 } 755 756 static void test_currdate(void) 757 { 758 SYSTEMTIME st_original, st_new, st_test; 759 int res; 760 HWND hwnd; 761 762 hwnd = create_monthcal_control(0); 763 764 flush_sequences(sequences, NUM_MSG_SEQUENCES); 765 766 /* Setter and Getters for current date selected */ 767 st_original.wYear = 2000; 768 st_original.wMonth = 11; 769 st_original.wDay = 28; 770 st_original.wHour = 11; 771 st_original.wMinute = 59; 772 st_original.wSecond = 30; 773 st_original.wMilliseconds = 0; 774 st_original.wDayOfWeek = 0; 775 776 st_new = st_test = st_original; 777 778 /* Should not validate the time */ 779 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test); 780 expect(1,res); 781 782 /* Overflow matters, check for wDay */ 783 st_test.wDay += 4; 784 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test); 785 expect(0,res); 786 787 /* correct wDay before checking for wMonth */ 788 st_test.wDay -= 4; 789 expect(st_original.wDay, st_test.wDay); 790 791 /* Overflow matters, check for wMonth */ 792 st_test.wMonth += 4; 793 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test); 794 expect(0,res); 795 796 /* checking if gets the information right, modify st_new */ 797 st_new.wYear += 4; 798 st_new.wMonth += 4; 799 st_new.wDay += 4; 800 st_new.wHour += 4; 801 st_new.wMinute += 4; 802 st_new.wSecond += 4; 803 804 res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new); 805 expect(1, res); 806 807 /* st_new change to st_origin, above settings with overflow */ 808 /* should not change the current settings */ 809 expect(st_original.wYear, st_new.wYear); 810 expect(st_original.wMonth, st_new.wMonth); 811 expect(st_original.wDay, st_new.wDay); 812 ok(st_original.wHour == st_new.wHour || 813 broken(0 == st_new.wHour), /* comctl32 <= 4.70 */ 814 "Expected %d, got %d\n", st_original.wHour, st_new.wHour); 815 ok(st_original.wMinute == st_new.wMinute || 816 broken(0 == st_new.wMinute), /* comctl32 <= 4.70 */ 817 "Expected %d, got %d\n", st_original.wMinute, st_new.wMinute); 818 ok(st_original.wSecond == st_new.wSecond || 819 broken(0 == st_new.wSecond), /* comctl32 <= 4.70 */ 820 "Expected %d, got %d\n", st_original.wSecond, st_new.wSecond); 821 822 /* lparam cannot be NULL */ 823 res = SendMessageA(hwnd, MCM_GETCURSEL, 0, 0); 824 expect(0, res); 825 826 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_curr_date_seq, "monthcal currDate", TRUE); 827 828 /* December, 31, 9999 is the maximum allowed date */ 829 memset(&st_new, 0, sizeof(st_new)); 830 st_new.wYear = 9999; 831 st_new.wMonth = 12; 832 st_new.wDay = 31; 833 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new); 834 expect(1, res); 835 memset(&st_test, 0, sizeof(st_test)); 836 res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test); 837 expect(1, res); 838 expect(st_new.wYear, st_test.wYear); 839 expect(st_new.wMonth, st_test.wMonth); 840 expect(st_new.wDay, st_test.wDay); 841 expect(st_new.wHour, st_test.wHour); 842 expect(st_new.wMinute, st_test.wMinute); 843 expect(st_new.wSecond, st_test.wSecond); 844 /* try one day later */ 845 st_original = st_new; 846 st_new.wYear = 10000; 847 st_new.wMonth = 1; 848 st_new.wDay = 1; 849 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new); 850 ok(0 == res || 851 broken(1 == res), /* comctl32 <= 4.72 */ 852 "Expected 0, got %d\n", res); 853 if (0 == res) 854 { 855 memset(&st_test, 0, sizeof(st_test)); 856 res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test); 857 expect(1, res); 858 expect(st_original.wYear, st_test.wYear); 859 expect(st_original.wMonth, st_test.wMonth); 860 expect(st_original.wDay, st_test.wDay); 861 expect(st_original.wHour, st_test.wHour); 862 expect(st_original.wMinute, st_test.wMinute); 863 expect(st_original.wSecond, st_test.wSecond); 864 } 865 866 /* setting selection equal to current reports success even if out range */ 867 memset(&st_new, 0, sizeof(st_new)); 868 st_new.wYear = 2009; 869 st_new.wDay = 5; 870 st_new.wMonth = 10; 871 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new); 872 expect(1, res); 873 memset(&st_test, 0, sizeof(st_test)); 874 st_test.wYear = 2009; 875 st_test.wDay = 6; 876 st_test.wMonth = 10; 877 res = SendMessageA(hwnd, MCM_SETRANGE, GDTR_MIN, (LPARAM)&st_test); 878 expect(1, res); 879 /* set to current again */ 880 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new); 881 expect(1, res); 882 883 /* set with invalid day of week */ 884 memset(&st_test, 0, sizeof(st_test)); 885 st_test.wYear = 2009; 886 st_test.wDay = 7; 887 st_test.wMonth = 10; 888 st_test.wDayOfWeek = 100; 889 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test); 890 expect(1, res); 891 892 memset(&st_test, 0, sizeof(st_test)); 893 res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test); 894 expect(1, res); 895 expect(2009, st_test.wYear); 896 expect(7, st_test.wDay); 897 expect(10, st_test.wMonth); 898 expect(3, st_test.wDayOfWeek); 899 900 DestroyWindow(hwnd); 901 } 902 903 static void test_firstDay(void) 904 { 905 int res, fday, i, prev; 906 CHAR b[128], caltype[3]; 907 LCID lcid = LOCALE_USER_DEFAULT; 908 HWND hwnd; 909 LRESULT ret; 910 911 SetLastError(0xdeadbeef); 912 ret = GetLocaleInfoA(lcid, LOCALE_ICALENDARTYPE, caltype, 3); 913 if (ret == 0) { 914 skip("Must know local calendar type (%x)\n", GetLastError()); 915 return; 916 } else if (atoi(caltype) != CAL_GREGORIAN) { 917 skip("MonthCalendar Control only supports Gregorian calendar (type: %s)\n", caltype); 918 return; 919 } 920 921 hwnd = create_monthcal_control(0); 922 923 flush_sequences(sequences, NUM_MSG_SEQUENCES); 924 925 /* Setter and Getters for first day of week */ 926 /* check for locale first day */ 927 if(GetLocaleInfoA(lcid, LOCALE_IFIRSTDAYOFWEEK, b, 128)){ 928 fday = atoi(b); 929 res = SendMessageA(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0); 930 expect(fday, res); 931 prev = fday; 932 933 /* checking for the values that actually will be stored as */ 934 /* current first day when we set a new value */ 935 for (i = -5; i < 12; i++){ 936 res = SendMessageA(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, i); 937 expect(prev, res); 938 res = SendMessageA(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0); 939 prev = res; 940 941 if (i == -1){ 942 expect(MAKELONG(fday, FALSE), res); 943 }else if (i >= 7){ 944 /* out of range sets max first day of week, locale is ignored */ 945 expect(MAKELONG(6, TRUE), res); 946 }else{ 947 expect(MAKELONG(i, TRUE), res); 948 } 949 } 950 951 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_first_day_seq, "monthcal firstDay", FALSE); 952 953 }else{ 954 skip("Cannot retrieve first day of the week\n"); 955 } 956 957 DestroyWindow(hwnd); 958 } 959 960 static void test_unicode(void) 961 { 962 int res, temp; 963 HWND hwnd; 964 965 hwnd = create_monthcal_control(0); 966 967 flush_sequences(sequences, NUM_MSG_SEQUENCES); 968 969 /* Setter and Getters for Unicode format */ 970 971 /* getting the current settings */ 972 temp = SendMessageA(hwnd, MCM_GETUNICODEFORMAT, 0, 0); 973 974 /* setting to 1, should return previous settings */ 975 res = SendMessageA(hwnd, MCM_SETUNICODEFORMAT, 1, 0); 976 expect(temp, res); 977 978 /* current setting is 1, so, should return 1 */ 979 res = SendMessageA(hwnd, MCM_GETUNICODEFORMAT, 0, 0); 980 ok(1 == res || 981 broken(0 == res), /* comctl32 <= 4.70 */ 982 "Expected 1, got %d\n", res); 983 984 /* setting to 0, should return previous settings */ 985 res = SendMessageA(hwnd, MCM_SETUNICODEFORMAT, 0, 0); 986 ok(1 == res || 987 broken(0 == res), /* comctl32 <= 4.70 */ 988 "Expected 1, got %d\n", res); 989 990 /* current setting is 0, so, it should return 0 */ 991 res = SendMessageA(hwnd, MCM_GETUNICODEFORMAT, 0, 0); 992 expect(0, res); 993 994 /* should return previous settings */ 995 res = SendMessageA(hwnd, MCM_SETUNICODEFORMAT, 1, 0); 996 expect(0, res); 997 998 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_unicode_seq, "monthcal unicode", FALSE); 999 1000 DestroyWindow(hwnd); 1001 } 1002 1003 static void test_hittest(void) 1004 { 1005 typedef struct hittest_test 1006 { 1007 UINT ht; 1008 BOOL todo; 1009 } hittest_test_t; 1010 1011 static const hittest_test_t title_hits[] = { 1012 /* Start is the same everywhere */ 1013 { MCHT_TITLE, FALSE }, 1014 { MCHT_TITLEBTNPREV, FALSE }, 1015 /* The middle piece is only tested for presence of items */ 1016 /* End is the same everywhere */ 1017 { MCHT_TITLEBTNNEXT, FALSE }, 1018 { MCHT_TITLE, FALSE }, 1019 { MCHT_NOWHERE, TRUE } 1020 }; 1021 1022 MCHITTESTINFO mchit; 1023 UINT res, old_res; 1024 SYSTEMTIME st; 1025 LONG x; 1026 UINT title_index; 1027 HWND hwnd; 1028 RECT r; 1029 char yearmonth[80], *locale_month, *locale_year; 1030 int month_count, year_count; 1031 BOOL in_the_middle; 1032 1033 memset(&mchit, 0, sizeof(MCHITTESTINFO)); 1034 1035 hwnd = create_monthcal_control(0); 1036 1037 /* test with invalid structure size */ 1038 mchit.cbSize = MCHITTESTINFO_V1_SIZE - 1; 1039 mchit.pt.x = 0; 1040 mchit.pt.y = 0; 1041 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1042 expect(0, mchit.pt.x); 1043 expect(0, mchit.pt.y); 1044 expect(~0u, res); 1045 expect(0, mchit.uHit); 1046 /* test with invalid pointer */ 1047 res = SendMessageA(hwnd, MCM_HITTEST, 0, 0); 1048 expect(~0u, res); 1049 1050 /* resize control to display single Calendar */ 1051 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r); 1052 if (res == 0) 1053 { 1054 win_skip("Message MCM_GETMINREQRECT unsupported. Skipping.\n"); 1055 DestroyWindow(hwnd); 1056 return; 1057 } 1058 MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE); 1059 1060 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1061 1062 st.wYear = 2007; 1063 st.wMonth = 4; 1064 st.wDay = 11; 1065 st.wHour = 1; 1066 st.wMinute = 0; 1067 st.wSecond = 0; 1068 st.wMilliseconds = 0; 1069 st.wDayOfWeek = 0; 1070 1071 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st); 1072 expect(1,res); 1073 1074 /* (0, 0) is the top left of the control - title */ 1075 mchit.cbSize = MCHITTESTINFO_V1_SIZE; 1076 mchit.pt.x = 0; 1077 mchit.pt.y = 0; 1078 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1079 expect(0, mchit.pt.x); 1080 expect(0, mchit.pt.y); 1081 expect(mchit.uHit, res); 1082 expect_hex(MCHT_TITLE, res); 1083 1084 /* bottom right of the control and should not be active */ 1085 mchit.pt.x = r.right; 1086 mchit.pt.y = r.bottom; 1087 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1088 expect(r.right, mchit.pt.x); 1089 expect(r.bottom, mchit.pt.y); 1090 expect(mchit.uHit, res); 1091 todo_wine expect_hex(MCHT_NOWHERE, res); 1092 1093 /* completely out of the control, should not be active */ 1094 mchit.pt.x = 2 * r.right; 1095 mchit.pt.y = 2 * r.bottom; 1096 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1097 expect(2 * r.right, mchit.pt.x); 1098 expect(2 * r.bottom, mchit.pt.y); 1099 expect(mchit.uHit, res); 1100 todo_wine expect_hex(MCHT_NOWHERE, res); 1101 1102 /* in active area - day of the week */ 1103 mchit.pt.x = r.right / 2; 1104 mchit.pt.y = r.bottom / 2; 1105 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1106 expect(r.right / 2, mchit.pt.x); 1107 expect(r.bottom / 2, mchit.pt.y); 1108 expect(mchit.uHit, res); 1109 expect_hex(MCHT_CALENDARDATE, res); 1110 1111 /* in active area - day of the week #2 */ 1112 mchit.pt.x = r.right / 14; /* half of first day rect */ 1113 mchit.pt.y = r.bottom / 2; 1114 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1115 expect(r.right / 14, mchit.pt.x); 1116 expect(r.bottom / 2, mchit.pt.y); 1117 expect(mchit.uHit, res); 1118 expect_hex(MCHT_CALENDARDATE, res); 1119 1120 /* in active area - date from prev month */ 1121 mchit.pt.x = r.right / 14; /* half of first day rect */ 1122 mchit.pt.y = 6 * r.bottom / 19; 1123 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1124 expect(r.right / 14, mchit.pt.x); 1125 expect(6 * r.bottom / 19, mchit.pt.y); 1126 expect(mchit.uHit, res); 1127 expect_hex(MCHT_CALENDARDATEPREV, res); 1128 1129 if (0) 1130 { 1131 /* (125, 115) is in active area - date from this month */ 1132 mchit.pt.x = 125; 1133 mchit.pt.y = 115; 1134 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1135 expect(125, mchit.pt.x); 1136 expect(115, mchit.pt.y); 1137 expect(mchit.uHit, res); 1138 expect(MCHT_CALENDARDATE, res); 1139 } 1140 1141 /* in active area - date from next month */ 1142 mchit.pt.x = 11 * r.right / 14; 1143 mchit.pt.y = 16 * r.bottom / 19; 1144 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1145 expect(11 * r.right / 14, mchit.pt.x); 1146 expect(16 * r.bottom / 19, mchit.pt.y); 1147 expect(mchit.uHit, res); 1148 expect_hex(MCHT_CALENDARDATENEXT, res); 1149 1150 /* in active area - today link */ 1151 mchit.pt.x = r.right / 14; 1152 mchit.pt.y = 18 * r.bottom / 19; 1153 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1154 expect(r.right / 14, mchit.pt.x); 1155 expect(18 * r.bottom / 19, mchit.pt.y); 1156 expect(mchit.uHit, res); 1157 expect_hex(MCHT_TODAYLINK, res); 1158 1159 /* in active area - today link */ 1160 mchit.pt.x = r.right / 2; 1161 mchit.pt.y = 18 * r.bottom / 19; 1162 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1163 expect(r.right / 2, mchit.pt.x); 1164 expect(18 * r.bottom / 19, mchit.pt.y); 1165 expect(mchit.uHit, res); 1166 expect_hex(MCHT_TODAYLINK, res); 1167 1168 /* in active area - today link */ 1169 mchit.pt.x = r.right / 10; 1170 mchit.pt.y = 18 * r.bottom / 19; 1171 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1172 expect(r.right / 10, mchit.pt.x); 1173 expect(18 * r.bottom / 19, mchit.pt.y); 1174 expect(mchit.uHit, res); 1175 expect_hex(MCHT_TODAYLINK, res); 1176 1177 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_hit_test_seq, "monthcal hit test", TRUE); 1178 1179 /* The horizontal position of title bar elements depends on locale (y pos 1180 is constant), so we sample across a horizontal line and make sure we 1181 find all elements. */ 1182 1183 /* Get the format of the title */ 1184 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SYEARMONTH, yearmonth, 80); 1185 /* Find out if we have a month and/or year */ 1186 locale_year = strstr(yearmonth, "y"); 1187 locale_month = strstr(yearmonth, "M"); 1188 1189 mchit.pt.x = 0; 1190 mchit.pt.y = (5/2) * r.bottom / 19; 1191 title_index = 0; 1192 old_res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1193 expect_hex(title_hits[title_index].ht, old_res); 1194 1195 in_the_middle = FALSE; 1196 month_count = year_count = 0; 1197 for (x = 0; x < r.right; x++){ 1198 mchit.pt.x = x; 1199 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1200 expect(x, mchit.pt.x); 1201 expect((5/2) * r.bottom / 19, mchit.pt.y); 1202 expect(mchit.uHit, res); 1203 if (res != old_res) { 1204 1205 if (old_res == MCHT_TITLEBTNPREV) 1206 in_the_middle = TRUE; 1207 1208 if (res == MCHT_TITLEBTNNEXT) 1209 in_the_middle = FALSE; 1210 1211 if (in_the_middle) { 1212 if (res == MCHT_TITLEMONTH) 1213 month_count++; 1214 else if (res == MCHT_TITLEYEAR) 1215 year_count++; 1216 } else { 1217 title_index++; 1218 1219 if (sizeof(title_hits) / sizeof(title_hits[0]) <= title_index) 1220 break; 1221 1222 todo_wine_if(title_hits[title_index].todo) 1223 ok(title_hits[title_index].ht == res, "Expected %x, got %x, pos %d\n", 1224 title_hits[title_index].ht, res, x); 1225 } 1226 old_res = res; 1227 } 1228 } 1229 1230 /* There are some limits, even if LOCALE_SYEARMONTH contains rubbish 1231 * or no month/year indicators at all */ 1232 if (locale_month) 1233 todo_wine ok(month_count == 1, "Expected 1 month item, got %d\n", month_count); 1234 else 1235 ok(month_count <= 1, "Too many month items: %d\n", month_count); 1236 1237 if (locale_year) 1238 todo_wine ok(year_count == 1, "Expected 1 year item, got %d\n", year_count); 1239 else 1240 ok(year_count <= 1, "Too many year items: %d\n", year_count); 1241 1242 todo_wine ok(month_count + year_count >= 1, "Not enough month and year items\n"); 1243 1244 ok(r.right <= x && title_index + 1 == sizeof(title_hits) / sizeof(title_hits[0]), 1245 "Wrong title layout\n"); 1246 1247 DestroyWindow(hwnd); 1248 } 1249 1250 static void test_todaylink(void) 1251 { 1252 MCHITTESTINFO mchit; 1253 SYSTEMTIME st_test, st_new; 1254 UINT res; 1255 HWND hwnd; 1256 RECT r; 1257 1258 memset(&mchit, 0, sizeof(MCHITTESTINFO)); 1259 1260 hwnd = create_monthcal_control(0); 1261 1262 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r); 1263 expect(1, res); 1264 MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE); 1265 1266 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1267 1268 /* hit active area - today link */ 1269 mchit.cbSize = MCHITTESTINFO_V1_SIZE; 1270 mchit.pt.x = r.right / 14; 1271 mchit.pt.y = 18 * r.bottom / 19; 1272 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1273 expect(r.right / 14, mchit.pt.x); 1274 expect(18 * r.bottom / 19, mchit.pt.y); 1275 expect(mchit.uHit, res); 1276 expect(MCHT_TODAYLINK, res); 1277 1278 st_test.wDay = 1; 1279 st_test.wMonth = 1; 1280 st_test.wYear = 2005; 1281 1282 res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test); 1283 expect(0, res); 1284 1285 memset(&st_new, 0, sizeof(st_new)); 1286 res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new); 1287 expect(1, res); 1288 expect(1, st_new.wDay); 1289 expect(1, st_new.wMonth); 1290 expect(2005, st_new.wYear); 1291 1292 res = SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(mchit.pt.x, mchit.pt.y)); 1293 expect(0, res); 1294 1295 memset(&st_new, 0, sizeof(st_new)); 1296 res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new); 1297 expect(1, res); 1298 expect(1, st_new.wDay); 1299 expect(1, st_new.wMonth); 1300 expect(2005, st_new.wYear); 1301 1302 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_todaylink_seq, "monthcal hit test", TRUE); 1303 1304 DestroyWindow(hwnd); 1305 } 1306 1307 static void test_today(void) 1308 { 1309 SYSTEMTIME st_test, st_new; 1310 int res; 1311 HWND hwnd; 1312 1313 hwnd = create_monthcal_control(0); 1314 1315 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1316 1317 /* Setter and Getters for "today" information */ 1318 1319 /* check for overflow, should be ok */ 1320 memset(&st_test, 0, sizeof(st_test)); 1321 st_test.wDay = 38; 1322 st_test.wMonth = 38; 1323 1324 st_new.wDay = 27; 1325 st_new.wMonth = 27; 1326 1327 res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test); 1328 expect(0, res); 1329 1330 res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new); 1331 expect(1, res); 1332 1333 /* st_test should not change */ 1334 expect(38, st_test.wDay); 1335 expect(38, st_test.wMonth); 1336 1337 /* st_new should change, overflow does not matter */ 1338 expect(38, st_new.wDay); 1339 expect(38, st_new.wMonth); 1340 1341 /* check for zero, should be ok*/ 1342 st_test.wDay = 0; 1343 st_test.wMonth = 0; 1344 1345 res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test); 1346 expect(0, res); 1347 1348 res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new); 1349 expect(1, res); 1350 1351 /* st_test should not change */ 1352 expect(0, st_test.wDay); 1353 expect(0, st_test.wMonth); 1354 1355 /* st_new should change to zero*/ 1356 expect(0, st_new.wDay); 1357 expect(0, st_new.wMonth); 1358 1359 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_today_seq, "monthcal today", TRUE); 1360 1361 DestroyWindow(hwnd); 1362 } 1363 1364 static void test_scroll(void) 1365 { 1366 int res; 1367 HWND hwnd; 1368 1369 hwnd = create_monthcal_control(0); 1370 1371 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0); 1372 expect(2, res); 1373 1374 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1375 1376 /* Setter and Getters for scroll rate */ 1377 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 2, 0); 1378 expect(0, res); 1379 1380 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 3, 0); 1381 expect(2, res); 1382 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0); 1383 expect(3, res); 1384 1385 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 12, 0); 1386 expect(3, res); 1387 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0); 1388 expect(12, res); 1389 1390 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 15, 0); 1391 expect(12, res); 1392 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0); 1393 expect(15, res); 1394 1395 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, -5, 0); 1396 expect(15, res); 1397 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0); 1398 expect(-5, res); 1399 1400 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_scroll_seq, "monthcal scroll", FALSE); 1401 1402 DestroyWindow(hwnd); 1403 } 1404 1405 static void test_monthrange(void) 1406 { 1407 int res; 1408 SYSTEMTIME st_visible[2], st_daystate[2], st; 1409 HWND hwnd; 1410 RECT r; 1411 1412 hwnd = create_monthcal_control(0); 1413 1414 memset(&st_visible, 0, sizeof(st_visible)); 1415 memset(&st_daystate, 0, sizeof(st_daystate)); 1416 1417 st.wYear = 2000; 1418 st.wMonth = 11; 1419 st.wDay = 28; 1420 st.wHour = 11; 1421 st.wMinute = 59; 1422 st.wSecond = 30; 1423 st.wMilliseconds = 0; 1424 st.wDayOfWeek = 0; 1425 1426 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st); 1427 expect(1,res); 1428 1429 /* to be locale independent */ 1430 SendMessageA(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, (LPARAM)6); 1431 1432 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r); 1433 expect(TRUE, res); 1434 /* resize control to display two Calendars */ 1435 MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE); 1436 1437 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1438 1439 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible); 1440 expect(2, res); 1441 expect(2000, st_visible[0].wYear); 1442 expect(11, st_visible[0].wMonth); 1443 expect(1, st_visible[0].wDay); 1444 expect(2000, st_visible[1].wYear); 1445 expect(12, st_visible[1].wMonth); 1446 expect(31, st_visible[1].wDay); 1447 1448 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, (LPARAM)st_daystate); 1449 expect(4, res); 1450 expect(2000, st_daystate[0].wYear); 1451 expect(10, st_daystate[0].wMonth); 1452 expect(29, st_daystate[0].wDay); 1453 expect(2001, st_daystate[1].wYear); 1454 expect(1, st_daystate[1].wMonth); 1455 expect(6, st_daystate[1].wDay); 1456 1457 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_monthrange_seq, "monthcal monthrange", FALSE); 1458 1459 /* with null date array parameter */ 1460 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, 0); 1461 expect(2, res); 1462 1463 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0); 1464 expect(4, res); 1465 1466 /* resize control to display single Calendar */ 1467 MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE); 1468 1469 memset(&st, 0, sizeof(st)); 1470 st.wMonth = 9; 1471 st.wYear = 1752; 1472 st.wDay = 14; 1473 1474 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st); 1475 expect(1, res); 1476 1477 /* September 1752 has 19 days */ 1478 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible); 1479 expect(1, res); 1480 1481 expect(1752, st_visible[0].wYear); 1482 expect(9, st_visible[0].wMonth); 1483 ok(14 == st_visible[0].wDay || 1484 broken(1 == st_visible[0].wDay), /* comctl32 <= 4.72 */ 1485 "Expected 14, got %d\n", st_visible[0].wDay); 1486 1487 expect(1752, st_visible[1].wYear); 1488 expect(9, st_visible[1].wMonth); 1489 expect(19, st_visible[1].wDay); 1490 1491 DestroyWindow(hwnd); 1492 } 1493 1494 static void test_maxselday(void) 1495 { 1496 int res; 1497 HWND hwnd; 1498 DWORD style; 1499 1500 hwnd = create_monthcal_control(0); 1501 /* if no style specified default to 1 */ 1502 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0); 1503 expect(1, res); 1504 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0); 1505 expect(0, res); 1506 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0); 1507 expect(1, res); 1508 1509 /* try to set style */ 1510 style = GetWindowLongA(hwnd, GWL_STYLE); 1511 SetWindowLongA(hwnd, GWL_STYLE, style | MCS_MULTISELECT); 1512 style = GetWindowLongA(hwnd, GWL_STYLE); 1513 ok(!(style & MCS_MULTISELECT), "Expected MCS_MULTISELECT not to be set\n"); 1514 DestroyWindow(hwnd); 1515 1516 hwnd = create_monthcal_control(MCS_MULTISELECT); 1517 /* try to remove style */ 1518 style = GetWindowLongA(hwnd, GWL_STYLE); 1519 SetWindowLongA(hwnd, GWL_STYLE, style & ~MCS_MULTISELECT); 1520 style = GetWindowLongA(hwnd, GWL_STYLE); 1521 ok(style & MCS_MULTISELECT, "Expected MCS_MULTISELECT to be set\n"); 1522 DestroyWindow(hwnd); 1523 1524 hwnd = create_monthcal_control(MCS_MULTISELECT); 1525 1526 /* default width is a week */ 1527 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0); 1528 expect(7, res); 1529 1530 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1531 1532 /* Setter and Getters for max selected days */ 1533 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0); 1534 expect(1, res); 1535 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0); 1536 expect(5, res); 1537 1538 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 15, 0); 1539 expect(1, res); 1540 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0); 1541 expect(15, res); 1542 1543 /* test invalid value */ 1544 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, -1, 0); 1545 expect(0, res); 1546 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0); 1547 expect(15, res); 1548 1549 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_max_sel_day_seq, "monthcal MaxSelDay", FALSE); 1550 1551 /* zero value is invalid too */ 1552 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 0, 0); 1553 expect(0, res); 1554 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0); 1555 expect(15, res); 1556 1557 DestroyWindow(hwnd); 1558 } 1559 1560 static void test_size(void) 1561 { 1562 int res; 1563 RECT r1, r2; 1564 HFONT hFont1, hFont2; 1565 LOGFONTA logfont; 1566 HWND hwnd; 1567 1568 hwnd = create_monthcal_control(0); 1569 1570 lstrcpyA(logfont.lfFaceName, "Arial"); 1571 memset(&logfont, 0, sizeof(logfont)); 1572 logfont.lfHeight = 12; 1573 hFont1 = CreateFontIndirectA(&logfont); 1574 1575 logfont.lfHeight = 24; 1576 hFont2 = CreateFontIndirectA(&logfont); 1577 1578 /* initialize to a font we can compare against */ 1579 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont1, 0); 1580 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r1); 1581 ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n"); 1582 1583 /* check that setting a larger font results in an larger rect */ 1584 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont2, 0); 1585 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2); 1586 ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n"); 1587 1588 OffsetRect(&r1, -r1.left, -r1.top); 1589 OffsetRect(&r2, -r2.left, -r2.top); 1590 1591 ok(r1.bottom < r2.bottom, "Failed to get larger rect with larger font\n"); 1592 1593 DestroyWindow(hwnd); 1594 } 1595 1596 static void test_create(void) 1597 { 1598 HWND hwnd; 1599 1600 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1601 1602 hwnd = create_monthcal_control(0); 1603 ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_control_seq, "create monthcal control", TRUE); 1604 1605 DestroyWindow(hwnd); 1606 1607 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1608 hwnd = create_monthcal_control(MCS_MULTISELECT); 1609 ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_multi_sel_style_seq, "create monthcal (multi sel style)", TRUE); 1610 DestroyWindow(hwnd); 1611 } 1612 1613 static void test_destroy(void) 1614 { 1615 HWND hwnd; 1616 1617 hwnd = create_monthcal_control(0); 1618 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1619 DestroyWindow(hwnd); 1620 ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_monthcal_parent_msgs_seq, "Destroy monthcal (parent msg)", FALSE); 1621 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_child_msgs_seq, "Destroy monthcal (child msg)", FALSE); 1622 1623 /* MCS_MULTISELECT */ 1624 hwnd = create_monthcal_control(MCS_MULTISELECT); 1625 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1626 DestroyWindow(hwnd); 1627 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_multi_sel_style_seq, "Destroy monthcal (multi sel style)", FALSE); 1628 } 1629 1630 static void test_selrange(void) 1631 { 1632 HWND hwnd; 1633 SYSTEMTIME st, range[2], range2[2]; 1634 BOOL ret, old_comctl32 = FALSE; 1635 1636 hwnd = create_monthcal_control(MCS_MULTISELECT); 1637 1638 /* just after creation selection should start and end today */ 1639 ret = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st); 1640 expect(TRUE, ret); 1641 1642 memset(range, 0xcc, sizeof(range)); 1643 ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range); 1644 expect(TRUE, ret); 1645 expect(st.wYear, range[0].wYear); 1646 expect(st.wMonth, range[0].wMonth); 1647 expect(st.wDay, range[0].wDay); 1648 if (range[0].wDayOfWeek != st.wDayOfWeek) 1649 { 1650 win_skip("comctl32 <= 4.70 doesn't set some values\n"); 1651 old_comctl32 = TRUE; 1652 } 1653 else 1654 { 1655 expect(st.wDayOfWeek, range[0].wDayOfWeek); 1656 expect(st.wHour, range[0].wHour); 1657 expect(st.wMinute, range[0].wMinute); 1658 expect(st.wSecond, range[0].wSecond); 1659 expect(st.wMilliseconds, range[0].wMilliseconds); 1660 } 1661 1662 expect(st.wYear, range[1].wYear); 1663 expect(st.wMonth, range[1].wMonth); 1664 expect(st.wDay, range[1].wDay); 1665 if (!old_comctl32) 1666 { 1667 expect(st.wDayOfWeek, range[1].wDayOfWeek); 1668 expect(st.wHour, range[1].wHour); 1669 expect(st.wMinute, range[1].wMinute); 1670 expect(st.wSecond, range[1].wSecond); 1671 expect(st.wMilliseconds, range[1].wMilliseconds); 1672 } 1673 1674 /* bounds are swapped if min > max */ 1675 memset(&range[0], 0, sizeof(range[0])); 1676 range[0].wYear = 2009; 1677 range[0].wMonth = 10; 1678 range[0].wDay = 5; 1679 range[1] = range[0]; 1680 range[1].wDay = 3; 1681 1682 ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range); 1683 expect(TRUE, ret); 1684 1685 ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2); 1686 expect(TRUE, ret); 1687 1688 expect(range[1].wYear, range2[0].wYear); 1689 expect(range[1].wMonth, range2[0].wMonth); 1690 expect(range[1].wDay, range2[0].wDay); 1691 expect(6, range2[0].wDayOfWeek); 1692 expect(range[1].wHour, range2[0].wHour); 1693 expect(range[1].wMinute, range2[0].wMinute); 1694 expect(range[1].wSecond, range2[0].wSecond); 1695 expect(range[1].wMilliseconds, range2[0].wMilliseconds); 1696 1697 expect(range[0].wYear, range2[1].wYear); 1698 expect(range[0].wMonth, range2[1].wMonth); 1699 expect(range[0].wDay, range2[1].wDay); 1700 expect(1, range2[1].wDayOfWeek); 1701 expect(range[0].wHour, range2[1].wHour); 1702 expect(range[0].wMinute, range2[1].wMinute); 1703 expect(range[0].wSecond, range2[1].wSecond); 1704 expect(range[0].wMilliseconds, range2[1].wMilliseconds); 1705 1706 /* try with range larger than maximum configured */ 1707 memset(&range[0], 0, sizeof(range[0])); 1708 range[0].wYear = 2009; 1709 range[0].wMonth = 10; 1710 range[0].wDay = 1; 1711 range[1] = range[0]; 1712 1713 ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range); 1714 expect(TRUE, ret); 1715 1716 range[1] = range[0]; 1717 /* default max. range is 7 days */ 1718 range[1].wDay = 8; 1719 1720 ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range); 1721 expect(FALSE, ret); 1722 1723 ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2); 1724 expect(TRUE, ret); 1725 1726 expect(range[0].wYear, range2[0].wYear); 1727 expect(range[0].wMonth, range2[0].wMonth); 1728 expect(range[0].wDay, range2[0].wDay); 1729 expect(range[0].wYear, range2[1].wYear); 1730 expect(range[0].wMonth, range2[1].wMonth); 1731 expect(range[0].wDay, range2[1].wDay); 1732 1733 DestroyWindow(hwnd); 1734 } 1735 1736 static void test_killfocus(void) 1737 { 1738 HWND hwnd; 1739 DWORD style; 1740 1741 hwnd = create_monthcal_control(0); 1742 1743 /* make parent invisible */ 1744 style = GetWindowLongA(parent_wnd, GWL_STYLE); 1745 SetWindowLongA(parent_wnd, GWL_STYLE, style & ~WS_VISIBLE); 1746 1747 SendMessageA(hwnd, WM_KILLFOCUS, (WPARAM)GetDesktopWindow(), 0); 1748 1749 style = GetWindowLongA(hwnd, GWL_STYLE); 1750 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n"); 1751 1752 style = GetWindowLongA(parent_wnd, GWL_STYLE); 1753 SetWindowLongA(parent_wnd, GWL_STYLE, style | WS_VISIBLE); 1754 1755 DestroyWindow(hwnd); 1756 } 1757 1758 static void test_hittest_v6(void) 1759 { 1760 MCHITTESTINFO mchit; 1761 DWORD ret; 1762 HWND hwnd; 1763 RECT r; 1764 1765 hwnd = create_monthcal_control(0); 1766 SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 0); 1767 1768 SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r); 1769 /* reserving some area around calendar */ 1770 MoveWindow(hwnd, 0, 0, r.right * 3 / 2, r.bottom * 3 / 2, FALSE); 1771 mchit.cbSize = sizeof(MCHITTESTINFO); 1772 mchit.pt.x = mchit.pt.y = 0; 1773 mchit.iOffset = -1; 1774 mchit.iRow = -1; 1775 mchit.iCol = -1; 1776 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1777 if (ret == ~0u) 1778 { 1779 win_skip("Only MCHITTESTINFO_V1 supported\n"); 1780 DestroyWindow(hwnd); 1781 return; 1782 } 1783 todo_wine expect_hex(MCHT_NOWHERE, ret); 1784 expect(-1, mchit.iOffset); 1785 expect(-1, mchit.iRow); 1786 expect(-1, mchit.iCol); 1787 1788 MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE); 1789 mchit.pt.x = r.right / 2; 1790 mchit.pt.y = r.bottom / 2; 1791 mchit.iOffset = -1; 1792 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1793 expect_hex(MCHT_CALENDARDATE, ret); 1794 expect(0, mchit.iOffset); 1795 1796 /* over day area */ 1797 mchit.pt.x = r.right / (7*2); 1798 mchit.pt.y = r.bottom / 2; 1799 mchit.iOffset = -1; 1800 mchit.iCol = mchit.iRow = -1; 1801 mchit.uHit = 0; 1802 mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1; 1803 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1804 expect_hex(MCHT_CALENDARDATE, ret); 1805 expect_hex(MCHT_CALENDARDATE, mchit.uHit); 1806 expect(0, mchit.iOffset); 1807 expect(2, mchit.iRow); 1808 expect(0, mchit.iCol); 1809 /* returned a one day rectangle */ 1810 expect_d(r.right / 7, mchit.rc.right - mchit.rc.left); 1811 expect_d(r.bottom / 10, mchit.rc.bottom - mchit.rc.top); 1812 1813 /* title */ 1814 mchit.pt.x = 1; 1815 mchit.pt.y = 1; 1816 mchit.iOffset = -1; 1817 mchit.iCol = mchit.iRow = -1; 1818 mchit.uHit = 0; 1819 mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1; 1820 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1821 expect_hex(MCHT_TITLE, ret); 1822 expect_hex(MCHT_TITLE, mchit.uHit); 1823 expect(0, mchit.iOffset); 1824 expect(-1, mchit.iRow); 1825 expect(-1, mchit.iCol); 1826 expect(0, mchit.rc.left); 1827 expect(0, mchit.rc.top); 1828 expect_d(r.right, mchit.rc.right); 1829 ok(mchit.rc.bottom > 0, "got %d\n", mchit.rc.bottom); 1830 1831 /* between two calendars */ 1832 MoveWindow(hwnd, 0, 0, r.right * 5/2, r.bottom, FALSE); 1833 mchit.pt.x = r.right / (5*4); 1834 mchit.pt.y = r.bottom / 2; 1835 mchit.iOffset = -2; 1836 mchit.iCol = mchit.iRow = -2; 1837 mchit.uHit = ~0; 1838 mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1; 1839 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 1840 todo_wine expect_hex(MCHT_NOWHERE, ret); 1841 todo_wine expect_hex(MCHT_NOWHERE, mchit.uHit); 1842 expect(-2, mchit.iOffset); 1843 expect(-2, mchit.iRow); 1844 expect(-2, mchit.iCol); 1845 todo_wine expect(0, mchit.rc.left); 1846 todo_wine expect(0, mchit.rc.top); 1847 todo_wine expect_d(r.right * 5/2, mchit.rc.right); 1848 todo_wine expect_d(r.bottom, mchit.rc.bottom); 1849 1850 DestroyWindow(hwnd); 1851 } 1852 1853 static void test_get_set_border(void) 1854 { 1855 HWND hwnd; 1856 DWORD ret; 1857 1858 hwnd = create_monthcal_control(0); 1859 1860 /* a non-default value */ 1861 ret = SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 10); 1862 expect(0, ret); 1863 1864 ret = SendMessageA(hwnd, MCM_GETCALENDARBORDER, 0, 0); 1865 1866 if (ret != 10) 1867 { 1868 skip("MCM_GET/SETCALENDARBORDER not supported\n"); 1869 DestroyWindow(hwnd); 1870 return; 1871 } 1872 1873 expect(10, ret); 1874 1875 DestroyWindow(hwnd); 1876 } 1877 1878 static void test_MCM_SIZERECTTOMIN(void) 1879 { 1880 HWND hwnd; 1881 DWORD ret; 1882 RECT r, r2; 1883 1884 hwnd = create_monthcal_control(0); 1885 1886 ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2); 1887 if (ret == 0) 1888 { 1889 win_skip("Message MCM_GETMINREQRECT unsupported. Skipping.\n"); 1890 DestroyWindow(hwnd); 1891 return; 1892 } 1893 1894 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, 0); 1895 ok(ret == 0, "got %d\n", ret); 1896 1897 SetRectEmpty(&r); 1898 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r); 1899 if (ret == 0) 1900 { 1901 skip("Message MCM_SIZERECTTOMIN unsupported. Skipping.\n"); 1902 DestroyWindow(hwnd); 1903 return; 1904 } 1905 ok(ret == 1, "got %d\n", ret); 1906 ok(r.left == 0 && r.right > 0, "got %d, %d\n", r.left, r.right); 1907 1908 r = r2; 1909 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r); 1910 ok(ret == 1, "got %d\n", ret); 1911 1912 r2.right = (r2.right - r2.left) * 3; 1913 r2.bottom = (r2.bottom - r2.top) * 3; 1914 r2.left = r2.top = 0; 1915 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r2); 1916 ok(ret == 1, "got %d\n", ret); 1917 1918 DestroyWindow(hwnd); 1919 } 1920 1921 static void test_MCM_GETCALENDARCOUNT(void) 1922 { 1923 HWND hwnd; 1924 DWORD ret; 1925 1926 hwnd = create_monthcal_control(0); 1927 1928 ret = SendMessageA(hwnd, MCM_GETCALENDARCOUNT, 0, 0); 1929 if (ret == 0) 1930 { 1931 win_skip("Message MCM_GETCALENDARCOUNT unsupported. Skipping.\n"); 1932 DestroyWindow(hwnd); 1933 return; 1934 } 1935 1936 expect(2, ret); 1937 1938 DestroyWindow(hwnd); 1939 } 1940 1941 static void test_daystate(void) 1942 { 1943 MONTHDAYSTATE state[4]; 1944 DWORD ret, style; 1945 HWND hwnd; 1946 RECT r; 1947 1948 /* without MCS_DAYSTATE */ 1949 hwnd = create_monthcal_control(0); 1950 1951 ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r); 1952 expect(TRUE, ret); 1953 1954 /* resize control to display two Calendars */ 1955 MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE); 1956 1957 ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0); 1958 expect(4, ret); 1959 1960 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state); 1961 expect(0, ret); 1962 1963 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state); 1964 expect(0, ret); 1965 1966 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0); 1967 expect(0, ret); 1968 1969 /* try to switch on */ 1970 SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | MCS_DAYSTATE); 1971 style = GetWindowLongA(hwnd, GWL_STYLE); 1972 ok((style & MCS_DAYSTATE) == 0, "got 0x%08x\n", style); 1973 1974 DestroyWindow(hwnd); 1975 1976 /* with MCS_DAYSTATE */ 1977 hwnd = create_monthcal_control(MCS_DAYSTATE); 1978 1979 ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0); 1980 expect(4, ret); 1981 1982 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state); 1983 expect(1, ret); 1984 1985 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state); 1986 expect(0, ret); 1987 1988 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0); 1989 expect(0, ret); 1990 1991 /* try to switch off */ 1992 SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~MCS_DAYSTATE); 1993 style = GetWindowLongA(hwnd, GWL_STYLE); 1994 ok((style & MCS_DAYSTATE) == MCS_DAYSTATE, "got 0x%08x\n", style); 1995 1996 DestroyWindow(hwnd); 1997 } 1998 1999 static void test_sel_notify(void) 2000 { 2001 typedef struct 2002 { 2003 DWORD val; 2004 const char* name; 2005 } Monthcal_style; 2006 2007 HWND hwnd; 2008 RECT rc; 2009 MCHITTESTINFO mchit = {sizeof(MCHITTESTINFO)}; 2010 SYSTEMTIME st; 2011 Monthcal_style styles[] = { 2012 {MCS_NOTODAY, "MCS_NOTODAY"}, 2013 {MCS_NOTODAY | MCS_MULTISELECT, "MCS_NOTODAY | MCS_MULTISELECT"}, 2014 {MCS_DAYSTATE, "MCS_DAYSTATE"}, 2015 {MCS_DAYSTATE | MCS_MULTISELECT, "MCS_DAYSTATE | MCS_MULTISELECT"} 2016 }; 2017 int i; 2018 2019 for(i = 0; i < sizeof styles / sizeof styles[0]; i++) 2020 { 2021 hwnd = create_monthcal_control(styles[i].val); 2022 SetWindowLongPtrA(hwnd, GWLP_ID, SEL_NOTIFY_TEST_ID); 2023 SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&rc); 2024 MoveWindow(hwnd, 0, 0, rc.right, rc.bottom, FALSE); 2025 /* Simulate mouse click on some unselected day to generate 2026 MCN_SELECT and MCN_SELCHANGE notifications */ 2027 mchit.pt.x = rc.right / 2; 2028 mchit.pt.y = rc.bottom / 2; 2029 SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 2030 SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st); 2031 while(st.wDay == mchit.st.wDay) /* Ensure that mchit.pt points to unselected day */ 2032 { 2033 mchit.pt.y++; 2034 SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit); 2035 } 2036 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y)); 2037 SendMessageA(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y)); 2038 DestroyWindow(hwnd); 2039 } 2040 } 2041 2042 static void init_functions(void) 2043 { 2044 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll"); 2045 2046 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f); 2047 X(InitCommonControlsEx); 2048 #undef X 2049 } 2050 2051 START_TEST(monthcal) 2052 { 2053 INITCOMMONCONTROLSEX iccex; 2054 ULONG_PTR ctx_cookie; 2055 HANDLE hCtx; 2056 2057 init_functions(); 2058 2059 iccex.dwSize = sizeof(iccex); 2060 iccex.dwICC = ICC_DATE_CLASSES; 2061 pInitCommonControlsEx(&iccex); 2062 2063 test_monthcal(); 2064 2065 init_msg_sequences(sequences, NUM_MSG_SEQUENCES); 2066 2067 parent_wnd = create_parent_window(); 2068 2069 test_create(); 2070 test_destroy(); 2071 test_color(); 2072 test_currdate(); 2073 test_firstDay(); 2074 test_unicode(); 2075 test_today(); 2076 test_scroll(); 2077 test_monthrange(); 2078 test_hittest(); 2079 test_todaylink(); 2080 test_size(); 2081 test_maxselday(); 2082 test_selrange(); 2083 test_killfocus(); 2084 test_daystate(); 2085 test_sel_notify(); 2086 2087 if (!load_v6_module(&ctx_cookie, &hCtx)) 2088 { 2089 DestroyWindow(parent_wnd); 2090 return; 2091 } 2092 2093 test_hittest_v6(); 2094 test_get_set_border(); 2095 test_MCM_SIZERECTTOMIN(); 2096 test_MCM_GETCALENDARCOUNT(); 2097 2098 unload_v6_module(ctx_cookie, hCtx); 2099 2100 DestroyWindow(parent_wnd); 2101 } 2102