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 <assert.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
37 #define NUM_MSG_SEQUENCES 2
38 #define PARENT_SEQ_INDEX 0
39 #define MONTHCAL_SEQ_INDEX 1
40
41 struct subclass_info
42 {
43 WNDPROC oldproc;
44 };
45
46 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
47
48 static const struct message create_parent_window_seq[] = {
49 { WM_GETMINMAXINFO, sent },
50 { WM_NCCREATE, sent },
51 { WM_NCCALCSIZE, sent|wparam, 0 },
52 { WM_CREATE, sent },
53 { WM_SHOWWINDOW, sent|wparam, 1 },
54 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
55 { WM_QUERYNEWPALETTE, sent|optional },
56 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
57 { WM_ACTIVATEAPP, sent|wparam, 1 },
58 { WM_NCACTIVATE, sent|wparam, 1 },
59 { WM_ACTIVATE, sent|wparam, 1 },
60 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
61 { WM_IME_NOTIFY, sent|defwinproc|optional },
62 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
63 /* Win9x adds SWP_NOZORDER below */
64 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
65 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
66 { WM_SIZE, sent },
67 { WM_MOVE, sent },
68 { 0 }
69 };
70
71 static const struct message create_monthcal_control_seq[] = {
72 { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
73 { WM_QUERYUISTATE, sent|optional },
74 { WM_GETFONT, sent },
75 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE},
76 { 0 }
77 };
78
79 static const struct message create_monthcal_multi_sel_style_seq[] = {
80 { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
81 { WM_QUERYUISTATE, sent|optional },
82 { WM_GETFONT, sent },
83 { 0 }
84 };
85
86 static const struct message monthcal_color_seq[] = {
87 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
88 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(0,0,0)},
89 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
90 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(255,255,255)},
91 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
92
93 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
94 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(0,0,0)},
95 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
96 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(255,255,255)},
97 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
98
99 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
100 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(0,0,0)},
101 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
102 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(255,255,255)},
103 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
104
105 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
106 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(0,0,0)},
107 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
108 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(255,255,255)},
109 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
110
111 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
112 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(0,0,0)},
113 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
114 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(255,255,255)},
115 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
116
117 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
118 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(0,0,0)},
119 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
120 { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(255,255,255)},
121 { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
122 { 0 }
123 };
124
125 static const struct message monthcal_curr_date_seq[] = {
126 { MCM_SETCURSEL, sent|wparam, 0},
127 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
128 { WM_ERASEBKGND, sent|lparam|defwinproc, 0},
129 { MCM_SETCURSEL, sent|wparam, 0},
130 { MCM_SETCURSEL, sent|wparam, 0},
131 { MCM_GETCURSEL, sent|wparam, 0},
132 { MCM_GETCURSEL, sent|wparam|lparam, 0, 0},
133 { 0 }
134 };
135
136 static const struct message monthcal_first_day_seq[] = {
137 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
138
139 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -5},
140 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
141
142 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -4},
143 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
144
145 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -3},
146 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
147
148 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -2},
149 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
150
151 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -1},
152 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
153
154 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
155 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
156
157 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 1},
158 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
159
160 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 2},
161 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
162
163 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 3},
164 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
165
166 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 4},
167 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
168
169 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 5},
170 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
171
172 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 6},
173 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
174
175 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 7},
176 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
177
178 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 8},
179 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
180
181 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 9},
182 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
183
184 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 10},
185 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
186
187 { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 11},
188 { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
189 { 0 }
190 };
191
192 static const struct message monthcal_unicode_seq[] = {
193 { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
194 { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
195 { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
196 { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
197 { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
198 { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
199 { 0 }
200 };
201
202 static const struct message monthcal_hit_test_seq[] = {
203 { MCM_SETCURSEL, sent|wparam, 0},
204 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
205 { MCM_HITTEST, sent|wparam, 0},
206 { MCM_HITTEST, sent|wparam, 0},
207 { MCM_HITTEST, sent|wparam, 0},
208 { MCM_HITTEST, sent|wparam, 0},
209 { MCM_HITTEST, sent|wparam, 0},
210 { MCM_HITTEST, sent|wparam, 0},
211 { MCM_HITTEST, sent|wparam, 0},
212 { MCM_HITTEST, sent|wparam, 0},
213 { MCM_HITTEST, sent|wparam, 0},
214 { MCM_HITTEST, sent|wparam, 0},
215 { MCM_HITTEST, sent|wparam, 0},
216 { MCM_HITTEST, sent|wparam, 0},
217 { MCM_HITTEST, sent|wparam, 0},
218 { MCM_HITTEST, sent|wparam, 0},
219 { MCM_HITTEST, sent|wparam, 0},
220 { MCM_HITTEST, sent|wparam, 0},
221 { MCM_HITTEST, sent|wparam, 0},
222 { 0 }
223 };
224
225 static const struct message monthcal_todaylink_seq[] = {
226 { MCM_HITTEST, sent|wparam, 0},
227 { MCM_SETTODAY, sent|wparam, 0},
228 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
229 { MCM_GETTODAY, sent|wparam, 0},
230 { WM_LBUTTONDOWN, sent|wparam|lparam, MK_LBUTTON, MAKELONG(70, 370)},
231 { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0},
232 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
233 { MCM_GETCURSEL, sent|wparam, 0},
234 { 0 }
235 };
236
237 static const struct message monthcal_today_seq[] = {
238 { MCM_SETTODAY, sent|wparam, 0},
239 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
240 { MCM_GETTODAY, sent|wparam, 0},
241 { MCM_SETTODAY, sent|wparam, 0},
242 { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
243 { MCM_GETTODAY, sent|wparam, 0},
244 { 0 }
245 };
246
247 static const struct message monthcal_scroll_seq[] = {
248 { MCM_SETMONTHDELTA, sent|wparam|lparam, 2, 0},
249 { MCM_SETMONTHDELTA, sent|wparam|lparam, 3, 0},
250 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
251 { MCM_SETMONTHDELTA, sent|wparam|lparam, 12, 0},
252 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
253 { MCM_SETMONTHDELTA, sent|wparam|lparam, 15, 0},
254 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
255 { MCM_SETMONTHDELTA, sent|wparam|lparam, -5, 0},
256 { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
257 { 0 }
258 };
259
260 static const struct message monthcal_monthrange_seq[] = {
261 { MCM_GETMONTHRANGE, sent|wparam, GMR_VISIBLE},
262 { MCM_GETMONTHRANGE, sent|wparam, GMR_DAYSTATE},
263 { 0 }
264 };
265
266 static const struct message monthcal_max_sel_day_seq[] = {
267 { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 5, 0},
268 { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
269 { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 15, 0},
270 { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
271 { MCM_SETMAXSELCOUNT, sent|wparam|lparam, -1, 0},
272 { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
273 { 0 }
274 };
275
276 /* expected message sequence for parent*/
277 static const struct message destroy_monthcal_parent_msgs_seq[] = {
278 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY},
279 { 0 }
280 };
281
282 /* expected message sequence for child*/
283 static const struct message destroy_monthcal_child_msgs_seq[] = {
284 { 0x0090, sent|optional }, /* Vista */
285 { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0},
286 { WM_WINDOWPOSCHANGING, sent|wparam, 0},
287 { WM_WINDOWPOSCHANGED, sent|wparam, 0},
288 { WM_DESTROY, sent|wparam|lparam, 0, 0},
289 { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
290 { 0 }
291 };
292
293 static const struct message destroy_monthcal_multi_sel_style_seq[] = {
294 { 0x0090, sent|optional }, /* Vista */
295 { WM_DESTROY, sent|wparam|lparam, 0, 0},
296 { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
297 { 0 }
298 };
299
300 /* expected message sequence for parent window*/
301 static const struct message destroy_parent_seq[] = {
302 { 0x0090, sent|optional }, /* Vista */
303 { WM_WINDOWPOSCHANGING, sent|wparam, 0},
304 { WM_WINDOWPOSCHANGED, sent|wparam, 0},
305 { WM_NCACTIVATE, sent|wparam, 0},
306 { WM_ACTIVATE, sent|wparam, 0},
307 { WM_NCACTIVATE, sent|wparam|lparam|optional, 0, 0},
308 { WM_ACTIVATE, sent|wparam|lparam|optional, 0, 0},
309 { WM_ACTIVATEAPP, sent|wparam, 0},
310 { WM_KILLFOCUS, sent|wparam|lparam, 0, 0},
311 { WM_IME_SETCONTEXT, sent|wparam|optional, 0},
312 { WM_IME_NOTIFY, sent|wparam|lparam|defwinproc|optional, 1, 0},
313 { WM_DESTROY, sent|wparam|lparam, 0, 0},
314 { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
315 { 0 }
316 };
317
318 static void test_monthcal(void)
319 {
320 HWND hwnd;
321 SYSTEMTIME st[2], st1[2];
322 int res, month_range;
323
324 hwnd = CreateWindowA(MONTHCAL_CLASSA, "MonthCal", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT,
325 0, 300, 300, 0, 0, NULL, NULL);
326 ok(hwnd != NULL, "Failed to create MonthCal\n");
327 GetSystemTime(&st[0]);
328 st[1] = st[0];
329
330 /* Invalid date/time */
331 st[0].wYear = 2000;
332 /* Time should not matter */
333 st[1].wHour = st[1].wMinute = st[1].wSecond = 70;
334 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n");
335 ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
336 ok(st1[0].wYear != 2000, "Lover limit changed\n");
337
338 st[1].wMonth = 0;
339 ok(!SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Should have failed to set limits\n");
340 ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
341 ok(st1[0].wYear != 2000, "Lover limit changed\n");
342 ok(!SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Should have failed to set MAX limit\n");
343 ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
344 ok(st1[0].wYear != 2000, "Lover limit changed\n");
345
346 GetSystemTime(&st[0]);
347 st[0].wDay = 20;
348 st[0].wMonth = 5;
349 st[1] = st[0];
350
351 month_range = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
352 st[1].wMonth--;
353 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
354 res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
355 ok(res == month_range, "Invalid month range (%d)\n", res);
356 ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX), "Limits should be set\n");
357
358 st[1].wMonth += 2;
359 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
360 res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
361 ok(res == month_range, "Invalid month range (%d)\n", res);
362
363 st[1].wYear --;
364 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
365 st[1].wYear += 1;
366 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
367
368 st[1].wMonth -= 3;
369 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
370 ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "Only MAX limit should be set\n");
371 st[1].wMonth += 4;
372 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
373 st[1].wYear -= 3;
374 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
375 st[1].wYear += 4;
376 ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
377 ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "Only MAX limit should be set\n");
378
379 DestroyWindow(hwnd);
380 }
381
382 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
383 {
384 static long defwndproc_counter = 0;
385 LRESULT ret;
386 struct message msg;
387
388 /* log system messages, except for painting */
389 if (message < WM_USER &&
390 message != WM_PAINT &&
391 message != WM_ERASEBKGND &&
392 message != WM_NCPAINT &&
393 message != WM_NCHITTEST &&
394 message != WM_GETTEXT &&
395 message != WM_GETICON &&
396 message != WM_DEVICECHANGE)
397 {
398 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
399
400 msg.message = message;
401 msg.flags = sent|wparam|lparam;
402 if (defwndproc_counter) msg.flags |= defwinproc;
403 msg.wParam = wParam;
404 msg.lParam = lParam;
405 add_message(sequences, PARENT_SEQ_INDEX, &msg);
406 }
407
408 defwndproc_counter++;
409 ret = DefWindowProcA(hwnd, message, wParam, lParam);
410 defwndproc_counter--;
411
412 return ret;
413 }
414
415 static BOOL register_parent_wnd_class(void)
416 {
417 WNDCLASSA cls;
418
419 cls.style = 0;
420 cls.lpfnWndProc = parent_wnd_proc;
421 cls.cbClsExtra = 0;
422 cls.cbWndExtra = 0;
423 cls.hInstance = GetModuleHandleA(NULL);
424 cls.hIcon = 0;
425 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
426 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
427 cls.lpszMenuName = NULL;
428 cls.lpszClassName = "Month-Cal test parent class";
429 return RegisterClassA(&cls);
430 }
431
432 static HWND create_parent_window(void)
433 {
434 HWND hwnd;
435
436 InitCommonControls();
437
438 /* flush message sequences, so we can check the new sequence by the end of function */
439 flush_sequences(sequences, NUM_MSG_SEQUENCES);
440
441 if (!register_parent_wnd_class())
442 return NULL;
443
444 hwnd = CreateWindowEx(0, "Month-Cal test parent class",
445 "Month-Cal test parent window",
446 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
447 WS_MAXIMIZEBOX | WS_VISIBLE,
448 0, 0, 500, 500,
449 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
450
451 assert(hwnd);
452
453 /* check for message sequences */
454 ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_window_seq, "create parent window", TRUE);
455
456 return hwnd;
457 }
458
459 static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
460 {
461 struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
462 static long defwndproc_counter = 0;
463 LRESULT ret;
464 struct message msg;
465
466 trace("monthcal: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
467
468 msg.message = message;
469 msg.flags = sent|wparam|lparam;
470 if (defwndproc_counter) msg.flags |= defwinproc;
471 msg.wParam = wParam;
472 msg.lParam = lParam;
473 add_message(sequences, MONTHCAL_SEQ_INDEX, &msg);
474
475 defwndproc_counter++;
476 ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
477 defwndproc_counter--;
478
479 return ret;
480 }
481
482 static HWND create_monthcal_control(DWORD style, HWND parent_window)
483 {
484 struct subclass_info *info;
485 HWND hwnd;
486
487 info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
488 if (!info)
489 return NULL;
490
491 hwnd = CreateWindowEx(0,
492 MONTHCAL_CLASS,
493 "",
494 style,
495 0, 0, 300, 400,
496 parent_window, NULL, GetModuleHandleA(NULL), NULL);
497
498 if (!hwnd)
499 {
500 HeapFree(GetProcessHeap(), 0, info);
501 return NULL;
502 }
503
504 info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
505 (LONG_PTR)monthcal_subclass_proc);
506 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
507
508 return hwnd;
509 }
510
511
512 /* Setter and Getters Tests */
513
514 static void test_monthcal_color(HWND hwnd)
515 {
516 int res, temp;
517
518 flush_sequences(sequences, NUM_MSG_SEQUENCES);
519
520 /* Setter and Getters for color*/
521 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
522 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(0,0,0));
523 expect(temp, res);
524 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
525 expect(RGB(0,0,0), temp);
526 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(255,255,255));
527 expect(temp, res);
528 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
529 expect(RGB(255,255,255), temp);
530
531 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
532 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(0,0,0));
533 expect(temp, res);
534 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
535 expect(RGB(0,0,0), temp);
536 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(255,255,255));
537 expect(temp, res);
538 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
539 expect(RGB(255,255,255), temp);
540
541 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
542 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(0,0,0));
543 expect(temp, res);
544 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
545 expect(RGB(0,0,0), temp);
546 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(255,255,255));
547 expect(temp, res);
548 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
549 expect(RGB(255,255,255), temp);
550
551 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
552 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(0,0,0));
553 expect(temp, res);
554 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
555 expect(RGB(0,0,0), temp);
556 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(255,255,255));
557 expect(temp, res);
558 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
559 expect(RGB(255,255,255), temp);
560
561 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
562 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(0,0,0));
563 expect(temp, res);
564 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
565 expect(RGB(0,0,0), temp);
566 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(255,255,255));
567 expect(temp, res);
568 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
569 expect(RGB(255,255,255), temp);
570
571 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
572 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(0,0,0));
573 expect(temp, res);
574 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
575 expect(RGB(0,0,0), temp);
576 res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(255,255,255));
577 expect(temp, res);
578 temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
579 expect(RGB(255,255,255), temp);
580
581 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_color_seq, "monthcal color", FALSE);
582 }
583
584 static void test_monthcal_currDate(HWND hwnd)
585 {
586 SYSTEMTIME st_original, st_new, st_test;
587 int res;
588
589 flush_sequences(sequences, NUM_MSG_SEQUENCES);
590
591 /* Setter and Getters for current date selected */
592 st_original.wYear = 2000;
593 st_original.wMonth = 11;
594 st_original.wDay = 28;
595 st_original.wHour = 11;
596 st_original.wMinute = 59;
597 st_original.wSecond = 30;
598 st_original.wMilliseconds = 0;
599 st_original.wDayOfWeek = 0;
600
601 st_new = st_test = st_original;
602
603 /* Should not validate the time */
604 res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
605 expect(1,res);
606
607 /* Overflow matters, check for wDay */
608 st_test.wDay += 4;
609 res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
610 expect(0,res);
611
612 /* correct wDay before checking for wMonth */
613 st_test.wDay -= 4;
614 expect(st_original.wDay, st_test.wDay);
615
616 /* Overflow matters, check for wMonth */
617 st_test.wMonth += 4;
618 res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
619 expect(0,res);
620
621 /* checking if gets the information right, modify st_new */
622 st_new.wYear += 4;
623 st_new.wMonth += 4;
624 st_new.wDay += 4;
625 st_new.wHour += 4;
626 st_new.wMinute += 4;
627 st_new.wSecond += 4;
628
629 res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
630 expect(1, res);
631
632 /* st_new change to st_origin, above settings with overflow */
633 /* should not change the current settings */
634 expect(st_original.wYear, st_new.wYear);
635 expect(st_original.wMonth, st_new.wMonth);
636 expect(st_original.wDay, st_new.wDay);
637 expect(st_original.wHour, st_new.wHour);
638 expect(st_original.wMinute, st_new.wMinute);
639 expect(st_original.wSecond, st_new.wSecond);
640
641 /* lparam cannot be NULL */
642 res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM) NULL);
643 expect(0, res);
644
645 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_curr_date_seq, "monthcal currDate", TRUE);
646 }
647
648 static void test_monthcal_firstDay(HWND hwnd)
649 {
650 int res, fday, i, prev;
651 TCHAR b[128];
652 LCID lcid = LOCALE_USER_DEFAULT;
653
654 flush_sequences(sequences, NUM_MSG_SEQUENCES);
655
656 /* Setter and Getters for first day of week */
657 /* check for locale first day */
658 if(GetLocaleInfo(lcid, LOCALE_IFIRSTDAYOFWEEK, b, 128)){
659 fday = atoi(b);
660 trace("fday: %d\n", fday);
661 res = SendMessage(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
662 expect(fday, res);
663 prev = fday;
664
665 /* checking for the values that actually will be stored as */
666 /* current first day when we set a new value */
667 for (i = -5; i < 12; i++){
668 res = SendMessage(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, (LPARAM) i);
669 expect(prev, res);
670 res = SendMessage(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
671 prev = res;
672
673 if (i == -1){
674 expect(MAKELONG(fday, FALSE), res);
675 }else if (i >= 7){
676 /* out of range sets max first day of week, locale is ignored */
677 expect(MAKELONG(6, TRUE), res);
678 }else{
679 expect(MAKELONG(i, TRUE), res);
680 }
681 }
682
683 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_first_day_seq, "monthcal firstDay", FALSE);
684
685 }else{
686 skip("Cannot retrieve first day of the week\n");
687 }
688
689 }
690
691 static void test_monthcal_unicode(HWND hwnd)
692 {
693 int res, temp;
694
695 flush_sequences(sequences, NUM_MSG_SEQUENCES);
696
697 /* Setter and Getters for Unicode format */
698
699 /* getting the current settings */
700 temp = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
701
702 /* setting to 1, should return previous settings */
703 res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
704 expect(temp, res);
705
706 /* current setting is 1, so, should return 1 */
707 res = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
708 todo_wine {expect(1, res);}
709
710 /* setting to 0, should return previous settings */
711 res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 0, 0);
712 todo_wine {expect(1, res);}
713
714 /* current setting is 0, so, it should return 0 */
715 res = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
716 expect(0, res);
717
718 /* should return previous settings */
719 res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
720 expect(0, res);
721
722 ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_unicode_seq, "monthcal unicode", FALSE);
723 }
724
725 static void test_monthcal_HitTest(HWND hwnd)
726 {
727 MCHITTESTINFO mchit;
728 UINT res;
729 SYSTEMTIME st;
730
731 memset(&mchit, 0, sizeof(MCHITTESTINFO));
732
733 flush_sequences(sequences, NUM_MSG_SEQUENCES);
734
735 st.wYear = 2007;
736 st.wMonth = 4;
737 st.wDay = 11;
738 st.wHour = 1;
739 st.wMinute = 0;
740 st.wSecond = 0;
741 st.wMilliseconds = 0;
742 st.wDayOfWeek = 0;
743
744 res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
745 expect(1,res);
746
747 /* (0, 0) is the top left of the control and should not be active */
748 mchit.cbSize = sizeof(MCHITTESTINFO);
749 mchit.pt.x = 0;
750 mchit.pt.y = 0;
751 res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
752 expect(0, mchit.pt.x);
753 expect(0, mchit.pt.y);
754 expect(mchit.uHit, res);
755 todo_wine {expect(MCHT_NOWHERE, res);}
756
757 /* (300, 400) is the bottom right of the control and should not be active */
758 mchit.pt.x = 300;
759 mchit.pt.y = 400;
760 res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
761 expect(300, mchit.pt.x);
762 expect(400, mchit.pt.y);