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
test_monthcal(void)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
parent_wnd_proc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)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
register_parent_wnd_class(void)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
create_parent_window(void)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
monthcal_subclass_proc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)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
create_monthcal_control(DWORD style)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
test_color(void)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
test_currdate(void)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
test_firstDay(void)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
test_unicode(void)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
test_hittest(void)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 (ARRAY_SIZE(title_hits) <= 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 == ARRAY_SIZE(title_hits), "Wrong title layout\n");
1245
1246 DestroyWindow(hwnd);
1247 }
1248
test_todaylink(void)1249 static void test_todaylink(void)
1250 {
1251 MCHITTESTINFO mchit;
1252 SYSTEMTIME st_test, st_new;
1253 UINT res;
1254 HWND hwnd;
1255 RECT r;
1256
1257 memset(&mchit, 0, sizeof(MCHITTESTINFO));
1258
1259 hwnd = create_monthcal_control(0);
1260
1261 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1262 expect(1, res);
1263 MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1264
1265 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1266
1267 /* hit active area - today link */
1268 mchit.cbSize = MCHITTESTINFO_V1_SIZE;
1269 mchit.pt.x = r.right / 14;
1270 mchit.pt.y = 18 * r.bottom / 19;
1271 res = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1272 expect(r.right / 14, mchit.pt.x);
1273 expect(18 * r.bottom / 19, mchit.pt.y);
1274 expect(mchit.uHit, res);
1275 expect(MCHT_TODAYLINK, res);
1276
1277 st_test.wDay = 1;
1278 st_test.wMonth = 1;
1279 st_test.wYear = 2005;
1280
1281 res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1282 expect(0, res);
1283
1284 memset(&st_new, 0, sizeof(st_new));
1285 res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1286 expect(1, res);
1287 expect(1, st_new.wDay);
1288 expect(1, st_new.wMonth);
1289 expect(2005, st_new.wYear);
1290
1291 res = SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(mchit.pt.x, mchit.pt.y));
1292 expect(0, res);
1293
1294 memset(&st_new, 0, sizeof(st_new));
1295 res = SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
1296 expect(1, res);
1297 expect(1, st_new.wDay);
1298 expect(1, st_new.wMonth);
1299 expect(2005, st_new.wYear);
1300
1301 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_todaylink_seq, "monthcal hit test", TRUE);
1302
1303 DestroyWindow(hwnd);
1304 }
1305
test_today(void)1306 static void test_today(void)
1307 {
1308 SYSTEMTIME st_test, st_new;
1309 int res;
1310 HWND hwnd;
1311
1312 hwnd = create_monthcal_control(0);
1313
1314 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1315
1316 /* Setter and Getters for "today" information */
1317
1318 /* check for overflow, should be ok */
1319 memset(&st_test, 0, sizeof(st_test));
1320 st_test.wDay = 38;
1321 st_test.wMonth = 38;
1322
1323 st_new.wDay = 27;
1324 st_new.wMonth = 27;
1325
1326 res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1327 expect(0, res);
1328
1329 res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1330 expect(1, res);
1331
1332 /* st_test should not change */
1333 expect(38, st_test.wDay);
1334 expect(38, st_test.wMonth);
1335
1336 /* st_new should change, overflow does not matter */
1337 expect(38, st_new.wDay);
1338 expect(38, st_new.wMonth);
1339
1340 /* check for zero, should be ok*/
1341 st_test.wDay = 0;
1342 st_test.wMonth = 0;
1343
1344 res = SendMessageA(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1345 expect(0, res);
1346
1347 res = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1348 expect(1, res);
1349
1350 /* st_test should not change */
1351 expect(0, st_test.wDay);
1352 expect(0, st_test.wMonth);
1353
1354 /* st_new should change to zero*/
1355 expect(0, st_new.wDay);
1356 expect(0, st_new.wMonth);
1357
1358 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_today_seq, "monthcal today", TRUE);
1359
1360 DestroyWindow(hwnd);
1361 }
1362
test_scroll(void)1363 static void test_scroll(void)
1364 {
1365 int res;
1366 HWND hwnd;
1367
1368 hwnd = create_monthcal_control(0);
1369
1370 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1371 expect(2, res);
1372
1373 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1374
1375 /* Setter and Getters for scroll rate */
1376 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 2, 0);
1377 expect(0, res);
1378
1379 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 3, 0);
1380 expect(2, res);
1381 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1382 expect(3, res);
1383
1384 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 12, 0);
1385 expect(3, res);
1386 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1387 expect(12, res);
1388
1389 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, 15, 0);
1390 expect(12, res);
1391 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1392 expect(15, res);
1393
1394 res = SendMessageA(hwnd, MCM_SETMONTHDELTA, -5, 0);
1395 expect(15, res);
1396 res = SendMessageA(hwnd, MCM_GETMONTHDELTA, 0, 0);
1397 expect(-5, res);
1398
1399 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_scroll_seq, "monthcal scroll", FALSE);
1400
1401 DestroyWindow(hwnd);
1402 }
1403
test_monthrange(void)1404 static void test_monthrange(void)
1405 {
1406 int res;
1407 SYSTEMTIME st_visible[2], st_daystate[2], st;
1408 HWND hwnd;
1409 RECT r;
1410
1411 hwnd = create_monthcal_control(0);
1412
1413 memset(&st_visible, 0, sizeof(st_visible));
1414 memset(&st_daystate, 0, sizeof(st_daystate));
1415
1416 st.wYear = 2000;
1417 st.wMonth = 11;
1418 st.wDay = 28;
1419 st.wHour = 11;
1420 st.wMinute = 59;
1421 st.wSecond = 30;
1422 st.wMilliseconds = 0;
1423 st.wDayOfWeek = 0;
1424
1425 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
1426 expect(1,res);
1427
1428 /* to be locale independent */
1429 SendMessageA(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, (LPARAM)6);
1430
1431 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1432 expect(TRUE, res);
1433 /* resize control to display two Calendars */
1434 MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE);
1435
1436 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1437
1438 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
1439 expect(2, res);
1440 expect(2000, st_visible[0].wYear);
1441 expect(11, st_visible[0].wMonth);
1442 expect(1, st_visible[0].wDay);
1443 expect(2000, st_visible[1].wYear);
1444 expect(12, st_visible[1].wMonth);
1445 expect(31, st_visible[1].wDay);
1446
1447 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, (LPARAM)st_daystate);
1448 expect(4, res);
1449 expect(2000, st_daystate[0].wYear);
1450 expect(10, st_daystate[0].wMonth);
1451 expect(29, st_daystate[0].wDay);
1452 expect(2001, st_daystate[1].wYear);
1453 expect(1, st_daystate[1].wMonth);
1454 expect(6, st_daystate[1].wDay);
1455
1456 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_monthrange_seq, "monthcal monthrange", FALSE);
1457
1458 /* with null date array parameter */
1459 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, 0);
1460 expect(2, res);
1461
1462 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1463 expect(4, res);
1464
1465 /* resize control to display single Calendar */
1466 MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1467
1468 memset(&st, 0, sizeof(st));
1469 st.wMonth = 9;
1470 st.wYear = 1752;
1471 st.wDay = 14;
1472
1473 res = SendMessageA(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
1474 expect(1, res);
1475
1476 /* September 1752 has 19 days */
1477 res = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
1478 expect(1, res);
1479
1480 expect(1752, st_visible[0].wYear);
1481 expect(9, st_visible[0].wMonth);
1482 ok(14 == st_visible[0].wDay ||
1483 broken(1 == st_visible[0].wDay), /* comctl32 <= 4.72 */
1484 "Expected 14, got %d\n", st_visible[0].wDay);
1485
1486 expect(1752, st_visible[1].wYear);
1487 expect(9, st_visible[1].wMonth);
1488 expect(19, st_visible[1].wDay);
1489
1490 DestroyWindow(hwnd);
1491 }
1492
test_maxselday(void)1493 static void test_maxselday(void)
1494 {
1495 int res;
1496 HWND hwnd;
1497 DWORD style;
1498
1499 hwnd = create_monthcal_control(0);
1500 /* if no style specified default to 1 */
1501 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1502 expect(1, res);
1503 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
1504 expect(0, res);
1505 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1506 expect(1, res);
1507
1508 /* try to set style */
1509 style = GetWindowLongA(hwnd, GWL_STYLE);
1510 SetWindowLongA(hwnd, GWL_STYLE, style | MCS_MULTISELECT);
1511 style = GetWindowLongA(hwnd, GWL_STYLE);
1512 ok(!(style & MCS_MULTISELECT), "Expected MCS_MULTISELECT not to be set\n");
1513 DestroyWindow(hwnd);
1514
1515 hwnd = create_monthcal_control(MCS_MULTISELECT);
1516 /* try to remove style */
1517 style = GetWindowLongA(hwnd, GWL_STYLE);
1518 SetWindowLongA(hwnd, GWL_STYLE, style & ~MCS_MULTISELECT);
1519 style = GetWindowLongA(hwnd, GWL_STYLE);
1520 ok(style & MCS_MULTISELECT, "Expected MCS_MULTISELECT to be set\n");
1521 DestroyWindow(hwnd);
1522
1523 hwnd = create_monthcal_control(MCS_MULTISELECT);
1524
1525 /* default width is a week */
1526 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1527 expect(7, res);
1528
1529 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1530
1531 /* Setter and Getters for max selected days */
1532 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
1533 expect(1, res);
1534 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1535 expect(5, res);
1536
1537 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 15, 0);
1538 expect(1, res);
1539 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1540 expect(15, res);
1541
1542 /* test invalid value */
1543 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, -1, 0);
1544 expect(0, res);
1545 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1546 expect(15, res);
1547
1548 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_max_sel_day_seq, "monthcal MaxSelDay", FALSE);
1549
1550 /* zero value is invalid too */
1551 res = SendMessageA(hwnd, MCM_SETMAXSELCOUNT, 0, 0);
1552 expect(0, res);
1553 res = SendMessageA(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1554 expect(15, res);
1555
1556 DestroyWindow(hwnd);
1557 }
1558
test_size(void)1559 static void test_size(void)
1560 {
1561 int res;
1562 RECT r1, r2;
1563 HFONT hFont1, hFont2;
1564 LOGFONTA logfont;
1565 HWND hwnd;
1566
1567 hwnd = create_monthcal_control(0);
1568
1569 lstrcpyA(logfont.lfFaceName, "Arial");
1570 memset(&logfont, 0, sizeof(logfont));
1571 logfont.lfHeight = 12;
1572 hFont1 = CreateFontIndirectA(&logfont);
1573
1574 logfont.lfHeight = 24;
1575 hFont2 = CreateFontIndirectA(&logfont);
1576
1577 /* initialize to a font we can compare against */
1578 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont1, 0);
1579 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r1);
1580 ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n");
1581
1582 /* check that setting a larger font results in an larger rect */
1583 SendMessageA(hwnd, WM_SETFONT, (WPARAM)hFont2, 0);
1584 res = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2);
1585 ok(res, "SendMessageA(MCM_GETMINREQRECT) failed\n");
1586
1587 OffsetRect(&r1, -r1.left, -r1.top);
1588 OffsetRect(&r2, -r2.left, -r2.top);
1589
1590 ok(r1.bottom < r2.bottom, "Failed to get larger rect with larger font\n");
1591
1592 DestroyWindow(hwnd);
1593 }
1594
test_create(void)1595 static void test_create(void)
1596 {
1597 HWND hwnd;
1598
1599 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1600
1601 hwnd = create_monthcal_control(0);
1602 ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_control_seq, "create monthcal control", TRUE);
1603
1604 DestroyWindow(hwnd);
1605
1606 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1607 hwnd = create_monthcal_control(MCS_MULTISELECT);
1608 ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_multi_sel_style_seq, "create monthcal (multi sel style)", TRUE);
1609 DestroyWindow(hwnd);
1610 }
1611
test_destroy(void)1612 static void test_destroy(void)
1613 {
1614 HWND hwnd;
1615
1616 hwnd = create_monthcal_control(0);
1617 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1618 DestroyWindow(hwnd);
1619 ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_monthcal_parent_msgs_seq, "Destroy monthcal (parent msg)", FALSE);
1620 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_child_msgs_seq, "Destroy monthcal (child msg)", FALSE);
1621
1622 /* MCS_MULTISELECT */
1623 hwnd = create_monthcal_control(MCS_MULTISELECT);
1624 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1625 DestroyWindow(hwnd);
1626 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_multi_sel_style_seq, "Destroy monthcal (multi sel style)", FALSE);
1627 }
1628
test_selrange(void)1629 static void test_selrange(void)
1630 {
1631 HWND hwnd;
1632 SYSTEMTIME st, range[2], range2[2];
1633 BOOL ret, old_comctl32 = FALSE;
1634
1635 hwnd = create_monthcal_control(MCS_MULTISELECT);
1636
1637 /* just after creation selection should start and end today */
1638 ret = SendMessageA(hwnd, MCM_GETTODAY, 0, (LPARAM)&st);
1639 expect(TRUE, ret);
1640
1641 memset(range, 0xcc, sizeof(range));
1642 ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range);
1643 expect(TRUE, ret);
1644 expect(st.wYear, range[0].wYear);
1645 expect(st.wMonth, range[0].wMonth);
1646 expect(st.wDay, range[0].wDay);
1647 if (range[0].wDayOfWeek != st.wDayOfWeek)
1648 {
1649 win_skip("comctl32 <= 4.70 doesn't set some values\n");
1650 old_comctl32 = TRUE;
1651 }
1652 else
1653 {
1654 expect(st.wDayOfWeek, range[0].wDayOfWeek);
1655 expect(st.wHour, range[0].wHour);
1656 expect(st.wMinute, range[0].wMinute);
1657 expect(st.wSecond, range[0].wSecond);
1658 expect(st.wMilliseconds, range[0].wMilliseconds);
1659 }
1660
1661 expect(st.wYear, range[1].wYear);
1662 expect(st.wMonth, range[1].wMonth);
1663 expect(st.wDay, range[1].wDay);
1664 if (!old_comctl32)
1665 {
1666 expect(st.wDayOfWeek, range[1].wDayOfWeek);
1667 expect(st.wHour, range[1].wHour);
1668 expect(st.wMinute, range[1].wMinute);
1669 expect(st.wSecond, range[1].wSecond);
1670 expect(st.wMilliseconds, range[1].wMilliseconds);
1671 }
1672
1673 /* bounds are swapped if min > max */
1674 memset(&range[0], 0, sizeof(range[0]));
1675 range[0].wYear = 2009;
1676 range[0].wMonth = 10;
1677 range[0].wDay = 5;
1678 range[1] = range[0];
1679 range[1].wDay = 3;
1680
1681 ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1682 expect(TRUE, ret);
1683
1684 ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2);
1685 expect(TRUE, ret);
1686
1687 expect(range[1].wYear, range2[0].wYear);
1688 expect(range[1].wMonth, range2[0].wMonth);
1689 expect(range[1].wDay, range2[0].wDay);
1690 expect(6, range2[0].wDayOfWeek);
1691 expect(range[1].wHour, range2[0].wHour);
1692 expect(range[1].wMinute, range2[0].wMinute);
1693 expect(range[1].wSecond, range2[0].wSecond);
1694 expect(range[1].wMilliseconds, range2[0].wMilliseconds);
1695
1696 expect(range[0].wYear, range2[1].wYear);
1697 expect(range[0].wMonth, range2[1].wMonth);
1698 expect(range[0].wDay, range2[1].wDay);
1699 expect(1, range2[1].wDayOfWeek);
1700 expect(range[0].wHour, range2[1].wHour);
1701 expect(range[0].wMinute, range2[1].wMinute);
1702 expect(range[0].wSecond, range2[1].wSecond);
1703 expect(range[0].wMilliseconds, range2[1].wMilliseconds);
1704
1705 /* try with range larger than maximum configured */
1706 memset(&range[0], 0, sizeof(range[0]));
1707 range[0].wYear = 2009;
1708 range[0].wMonth = 10;
1709 range[0].wDay = 1;
1710 range[1] = range[0];
1711
1712 ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1713 expect(TRUE, ret);
1714
1715 range[1] = range[0];
1716 /* default max. range is 7 days */
1717 range[1].wDay = 8;
1718
1719 ret = SendMessageA(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
1720 expect(FALSE, ret);
1721
1722 ret = SendMessageA(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2);
1723 expect(TRUE, ret);
1724
1725 expect(range[0].wYear, range2[0].wYear);
1726 expect(range[0].wMonth, range2[0].wMonth);
1727 expect(range[0].wDay, range2[0].wDay);
1728 expect(range[0].wYear, range2[1].wYear);
1729 expect(range[0].wMonth, range2[1].wMonth);
1730 expect(range[0].wDay, range2[1].wDay);
1731
1732 DestroyWindow(hwnd);
1733 }
1734
test_killfocus(void)1735 static void test_killfocus(void)
1736 {
1737 HWND hwnd;
1738 DWORD style;
1739
1740 hwnd = create_monthcal_control(0);
1741
1742 /* make parent invisible */
1743 style = GetWindowLongA(parent_wnd, GWL_STYLE);
1744 SetWindowLongA(parent_wnd, GWL_STYLE, style & ~WS_VISIBLE);
1745
1746 SendMessageA(hwnd, WM_KILLFOCUS, (WPARAM)GetDesktopWindow(), 0);
1747
1748 style = GetWindowLongA(hwnd, GWL_STYLE);
1749 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
1750
1751 style = GetWindowLongA(parent_wnd, GWL_STYLE);
1752 SetWindowLongA(parent_wnd, GWL_STYLE, style | WS_VISIBLE);
1753
1754 DestroyWindow(hwnd);
1755 }
1756
test_hittest_v6(void)1757 static void test_hittest_v6(void)
1758 {
1759 MCHITTESTINFO mchit;
1760 DWORD ret;
1761 HWND hwnd;
1762 RECT r;
1763
1764 hwnd = create_monthcal_control(0);
1765 SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 0);
1766
1767 SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1768 /* reserving some area around calendar */
1769 MoveWindow(hwnd, 0, 0, r.right * 3 / 2, r.bottom * 3 / 2, FALSE);
1770 mchit.cbSize = sizeof(MCHITTESTINFO);
1771 mchit.pt.x = mchit.pt.y = 0;
1772 mchit.iOffset = -1;
1773 mchit.iRow = -1;
1774 mchit.iCol = -1;
1775 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1776 if (ret == ~0u)
1777 {
1778 win_skip("Only MCHITTESTINFO_V1 supported\n");
1779 DestroyWindow(hwnd);
1780 return;
1781 }
1782 todo_wine expect_hex(MCHT_NOWHERE, ret);
1783 expect(-1, mchit.iOffset);
1784 expect(-1, mchit.iRow);
1785 expect(-1, mchit.iCol);
1786
1787 MoveWindow(hwnd, 0, 0, r.right, r.bottom, FALSE);
1788 mchit.pt.x = r.right / 2;
1789 mchit.pt.y = r.bottom / 2;
1790 mchit.iOffset = -1;
1791 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1792 expect_hex(MCHT_CALENDARDATE, ret);
1793 expect(0, mchit.iOffset);
1794
1795 /* over day area */
1796 mchit.pt.x = r.right / (7*2);
1797 mchit.pt.y = r.bottom / 2;
1798 mchit.iOffset = -1;
1799 mchit.iCol = mchit.iRow = -1;
1800 mchit.uHit = 0;
1801 SetRect(&mchit.rc, -1, -1, -1, -1);
1802 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1803 expect_hex(MCHT_CALENDARDATE, ret);
1804 expect_hex(MCHT_CALENDARDATE, mchit.uHit);
1805 expect(0, mchit.iOffset);
1806 expect(2, mchit.iRow);
1807 expect(0, mchit.iCol);
1808 /* returned a one day rectangle */
1809 expect_d(r.right / 7, mchit.rc.right - mchit.rc.left);
1810 expect_d(r.bottom / 10, mchit.rc.bottom - mchit.rc.top);
1811
1812 /* title */
1813 mchit.pt.x = 1;
1814 mchit.pt.y = 1;
1815 mchit.iOffset = -1;
1816 mchit.iCol = mchit.iRow = -1;
1817 mchit.uHit = 0;
1818 SetRect(&mchit.rc, -1, -1, -1, -1);
1819 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1820 expect_hex(MCHT_TITLE, ret);
1821 expect_hex(MCHT_TITLE, mchit.uHit);
1822 expect(0, mchit.iOffset);
1823 expect(-1, mchit.iRow);
1824 expect(-1, mchit.iCol);
1825 expect(0, mchit.rc.left);
1826 expect(0, mchit.rc.top);
1827 expect_d(r.right, mchit.rc.right);
1828 ok(mchit.rc.bottom > 0, "got %d\n", mchit.rc.bottom);
1829
1830 /* between two calendars */
1831 MoveWindow(hwnd, 0, 0, r.right * 5/2, r.bottom, FALSE);
1832 mchit.pt.x = r.right / (5*4);
1833 mchit.pt.y = r.bottom / 2;
1834 mchit.iOffset = -2;
1835 mchit.iCol = mchit.iRow = -2;
1836 mchit.uHit = ~0;
1837 SetRect(&mchit.rc, -1, -1, -1, -1);
1838 ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
1839 todo_wine expect_hex(MCHT_NOWHERE, ret);
1840 todo_wine expect_hex(MCHT_NOWHERE, mchit.uHit);
1841 expect(-2, mchit.iOffset);
1842 expect(-2, mchit.iRow);
1843 expect(-2, mchit.iCol);
1844 todo_wine expect(0, mchit.rc.left);
1845 todo_wine expect(0, mchit.rc.top);
1846 todo_wine expect_d(r.right * 5/2, mchit.rc.right);
1847 todo_wine expect_d(r.bottom, mchit.rc.bottom);
1848
1849 DestroyWindow(hwnd);
1850 }
1851
test_get_set_border(void)1852 static void test_get_set_border(void)
1853 {
1854 HWND hwnd;
1855 DWORD ret;
1856
1857 hwnd = create_monthcal_control(0);
1858
1859 /* a non-default value */
1860 ret = SendMessageA(hwnd, MCM_SETCALENDARBORDER, TRUE, 10);
1861 expect(0, ret);
1862
1863 ret = SendMessageA(hwnd, MCM_GETCALENDARBORDER, 0, 0);
1864
1865 if (ret != 10)
1866 {
1867 skip("MCM_GET/SETCALENDARBORDER not supported\n");
1868 DestroyWindow(hwnd);
1869 return;
1870 }
1871
1872 expect(10, ret);
1873
1874 DestroyWindow(hwnd);
1875 }
1876
test_MCM_SIZERECTTOMIN(void)1877 static void test_MCM_SIZERECTTOMIN(void)
1878 {
1879 HWND hwnd;
1880 DWORD ret;
1881 RECT r, r2;
1882
1883 hwnd = create_monthcal_control(0);
1884
1885 ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r2);
1886 if (ret == 0)
1887 {
1888 win_skip("Message MCM_GETMINREQRECT unsupported. Skipping.\n");
1889 DestroyWindow(hwnd);
1890 return;
1891 }
1892
1893 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, 0);
1894 ok(ret == 0, "got %d\n", ret);
1895
1896 SetRectEmpty(&r);
1897 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r);
1898 if (ret == 0)
1899 {
1900 skip("Message MCM_SIZERECTTOMIN unsupported. Skipping.\n");
1901 DestroyWindow(hwnd);
1902 return;
1903 }
1904 ok(ret == 1, "got %d\n", ret);
1905 ok(r.left == 0 && r.right > 0, "got %d, %d\n", r.left, r.right);
1906
1907 r = r2;
1908 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r);
1909 ok(ret == 1, "got %d\n", ret);
1910
1911 r2.right = (r2.right - r2.left) * 3;
1912 r2.bottom = (r2.bottom - r2.top) * 3;
1913 r2.left = r2.top = 0;
1914 ret = SendMessageA(hwnd, MCM_SIZERECTTOMIN, 0, (LPARAM)&r2);
1915 ok(ret == 1, "got %d\n", ret);
1916
1917 DestroyWindow(hwnd);
1918 }
1919
test_MCM_GETCALENDARCOUNT(void)1920 static void test_MCM_GETCALENDARCOUNT(void)
1921 {
1922 HWND hwnd;
1923 DWORD ret;
1924
1925 hwnd = create_monthcal_control(0);
1926
1927 ret = SendMessageA(hwnd, MCM_GETCALENDARCOUNT, 0, 0);
1928 if (ret == 0)
1929 {
1930 win_skip("Message MCM_GETCALENDARCOUNT unsupported. Skipping.\n");
1931 DestroyWindow(hwnd);
1932 return;
1933 }
1934
1935 expect(2, ret);
1936
1937 DestroyWindow(hwnd);
1938 }
1939
test_daystate(void)1940 static void test_daystate(void)
1941 {
1942 MONTHDAYSTATE state[4];
1943 DWORD ret, style;
1944 HWND hwnd;
1945 RECT r;
1946
1947 /* without MCS_DAYSTATE */
1948 hwnd = create_monthcal_control(0);
1949
1950 ret = SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&r);
1951 expect(TRUE, ret);
1952
1953 /* resize control to display two Calendars */
1954 MoveWindow(hwnd, 0, 0, r.right, (5/2)*r.bottom, FALSE);
1955
1956 ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1957 expect(4, ret);
1958
1959 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state);
1960 expect(0, ret);
1961
1962 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state);
1963 expect(0, ret);
1964
1965 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0);
1966 expect(0, ret);
1967
1968 /* try to switch on */
1969 SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | MCS_DAYSTATE);
1970 style = GetWindowLongA(hwnd, GWL_STYLE);
1971 ok((style & MCS_DAYSTATE) == 0, "got 0x%08x\n", style);
1972
1973 DestroyWindow(hwnd);
1974
1975 /* with MCS_DAYSTATE */
1976 hwnd = create_monthcal_control(MCS_DAYSTATE);
1977
1978 ret = SendMessageA(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, 0);
1979 expect(4, ret);
1980
1981 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 4, (LPARAM)&state);
1982 expect(1, ret);
1983
1984 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 2, (LPARAM)&state);
1985 expect(0, ret);
1986
1987 ret = SendMessageA(hwnd, MCM_SETDAYSTATE, 0, 0);
1988 expect(0, ret);
1989
1990 /* try to switch off */
1991 SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~MCS_DAYSTATE);
1992 style = GetWindowLongA(hwnd, GWL_STYLE);
1993 ok((style & MCS_DAYSTATE) == MCS_DAYSTATE, "got 0x%08x\n", style);
1994
1995 DestroyWindow(hwnd);
1996 }
1997
test_sel_notify(void)1998 static void test_sel_notify(void)
1999 {
2000 typedef struct
2001 {
2002 DWORD val;
2003 const char* name;
2004 } Monthcal_style;
2005
2006 HWND hwnd;
2007 RECT rc;
2008 MCHITTESTINFO mchit = {sizeof(MCHITTESTINFO)};
2009 SYSTEMTIME st;
2010 Monthcal_style styles[] = {
2011 {MCS_NOTODAY, "MCS_NOTODAY"},
2012 {MCS_NOTODAY | MCS_MULTISELECT, "MCS_NOTODAY | MCS_MULTISELECT"},
2013 {MCS_DAYSTATE, "MCS_DAYSTATE"},
2014 {MCS_DAYSTATE | MCS_MULTISELECT, "MCS_DAYSTATE | MCS_MULTISELECT"}
2015 };
2016 int i;
2017
2018 for(i = 0; i < ARRAY_SIZE(styles); i++)
2019 {
2020 hwnd = create_monthcal_control(styles[i].val);
2021 SetWindowLongPtrA(hwnd, GWLP_ID, SEL_NOTIFY_TEST_ID);
2022 SendMessageA(hwnd, MCM_GETMINREQRECT, 0, (LPARAM)&rc);
2023 MoveWindow(hwnd, 0, 0, rc.right, rc.bottom, FALSE);
2024 /* Simulate mouse click on some unselected day to generate
2025 MCN_SELECT and MCN_SELCHANGE notifications */
2026 mchit.pt.x = rc.right / 2;
2027 mchit.pt.y = rc.bottom / 2;
2028 SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
2029 SendMessageA(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st);
2030 while(st.wDay == mchit.st.wDay) /* Ensure that mchit.pt points to unselected day */
2031 {
2032 mchit.pt.y++;
2033 SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
2034 }
2035 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y));
2036 SendMessageA(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(mchit.pt.x, mchit.pt.y));
2037 DestroyWindow(hwnd);
2038 }
2039 }
2040
init_functions(void)2041 static void init_functions(void)
2042 {
2043 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2044
2045 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2046 X(InitCommonControlsEx);
2047 #undef X
2048 }
2049
START_TEST(monthcal)2050 START_TEST(monthcal)
2051 {
2052 INITCOMMONCONTROLSEX iccex;
2053 ULONG_PTR ctx_cookie;
2054 HANDLE hCtx;
2055
2056 init_functions();
2057
2058 iccex.dwSize = sizeof(iccex);
2059 iccex.dwICC = ICC_DATE_CLASSES;
2060 pInitCommonControlsEx(&iccex);
2061
2062 test_monthcal();
2063
2064 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2065
2066 parent_wnd = create_parent_window();
2067
2068 test_create();
2069 test_destroy();
2070 test_color();
2071 test_currdate();
2072 test_firstDay();
2073 test_unicode();
2074 test_today();
2075 test_scroll();
2076 test_monthrange();
2077 test_hittest();
2078 test_todaylink();
2079 test_size();
2080 test_maxselday();
2081 test_selrange();
2082 test_killfocus();
2083 test_daystate();
2084 test_sel_notify();
2085
2086 if (!load_v6_module(&ctx_cookie, &hCtx))
2087 {
2088 DestroyWindow(parent_wnd);
2089 return;
2090 }
2091
2092 test_hittest_v6();
2093 test_get_set_border();
2094 test_MCM_SIZERECTTOMIN();
2095 test_MCM_GETCALENDARCOUNT();
2096
2097 unload_v6_module(ctx_cookie, hCtx);
2098
2099 DestroyWindow(parent_wnd);
2100 }
2101