2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004 Dmitry Timoshkov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define _WIN32_WINNT 0x0500 /* For WM_CHANGEUISTATE */
33 #include "wine/test.h"
35 #define MDI_FIRST_CHILD_ID 2004
38 FIXME: add tests for these
39 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
40 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
41 WS_THICKFRAME: thick border
42 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
43 WS_BORDER (default for overlapped windows): single black border
44 none (default for child (and popup?) windows): no border
48 sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10,
49 defwinproc=0x20, optional=0x40, hook=0x80
53 UINT message; /* the WM_* code */
54 msg_flags_t flags; /* message props */
55 WPARAM wParam; /* expected value of wParam */
56 LPARAM lParam; /* expected value of lParam */
59 /* Empty message sequence */
60 static const struct message WmEmptySeq[] =
64 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
65 static const struct message WmCreateOverlappedSeq[] = {
66 { HCBT_CREATEWND, hook },
67 { WM_GETMINMAXINFO, sent },
68 { WM_NCCREATE, sent },
69 { WM_NCCALCSIZE, sent|wparam, 0 },
73 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
74 * for a not visible overlapped window.
76 static const struct message WmSWP_ShowOverlappedSeq[] = {
77 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
78 { WM_NCPAINT, sent|wparam|optional, 1 },
79 { WM_GETTEXT, sent|defwinproc|optional },
80 { WM_ERASEBKGND, sent|optional },
81 { HCBT_ACTIVATE, hook },
82 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
83 { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, /* Win9x: SWP_NOSENDCHANGING */
84 { WM_ACTIVATEAPP, sent|wparam, 1 },
85 { WM_NCACTIVATE, sent|wparam, 1 },
86 { WM_GETTEXT, sent|defwinproc|optional },
87 { WM_ACTIVATE, sent|wparam, 1 },
88 { HCBT_SETFOCUS, hook },
89 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
90 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
91 { WM_NCPAINT, sent|wparam|optional, 1 },
92 { WM_GETTEXT, sent|defwinproc|optional },
93 { WM_ERASEBKGND, sent|optional },
94 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
95 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
96 { WM_NCPAINT, sent|wparam|optional, 1 },
97 { WM_ERASEBKGND, sent|optional },
100 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
101 * for a visible overlapped window.
103 static const struct message WmSWP_HideOverlappedSeq[] = {
104 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
105 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
108 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
109 static const struct message WmShowOverlappedSeq[] = {
110 { WM_SHOWWINDOW, sent|wparam, 1 },
111 { WM_NCPAINT, sent|wparam|optional, 1 },
112 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
113 { WM_NCPAINT, sent|wparam|optional, 1 },
114 { WM_GETTEXT, sent|defwinproc|optional },
115 { WM_ERASEBKGND, sent|optional },
116 { HCBT_ACTIVATE, hook },
117 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
118 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
119 { WM_ACTIVATEAPP, sent|wparam, 1 },
120 { WM_NCACTIVATE, sent|wparam, 1 },
121 { WM_GETTEXT, sent|defwinproc|optional },
122 { WM_ACTIVATE, sent|wparam, 1 },
123 { HCBT_SETFOCUS, hook },
124 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
125 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
126 { WM_NCPAINT, sent|wparam|optional, 1 },
127 { WM_GETTEXT, sent|defwinproc|optional },
128 { WM_ERASEBKGND, sent|optional },
129 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
130 { WM_NCCALCSIZE, sent|optional },
131 { WM_NCPAINT, sent|optional },
132 { WM_ERASEBKGND, sent|optional },
133 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
134 * messages. Does that mean that CreateWindow doesn't set initial
135 * window dimensions for overlapped windows?
142 /* ShowWindow(SW_HIDE) for a visible overlapped window */
143 static const struct message WmHideOverlappedSeq[] = {
144 { WM_SHOWWINDOW, sent|wparam, 0 },
145 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
146 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
149 { WM_NCACTIVATE, sent|wparam, 0 },
150 { WM_ACTIVATE, sent|wparam, 0 },
151 { WM_ACTIVATEAPP, sent|wparam, 0 },
152 { WM_KILLFOCUS, sent|wparam, 0 },
153 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
156 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
157 static const struct message WmHideInvisibleOverlappedSeq[] = {
160 /* DestroyWindow for a visible overlapped window */
161 static const struct message WmDestroyOverlappedSeq[] = {
162 { HCBT_DESTROYWND, hook },
163 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
164 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
165 { WM_NCACTIVATE, sent|wparam, 0 },
166 { WM_ACTIVATE, sent|wparam, 0 },
167 { WM_ACTIVATEAPP, sent|wparam, 0 },
168 { WM_KILLFOCUS, sent|wparam, 0 },
169 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
170 { WM_DESTROY, sent },
171 { WM_NCDESTROY, sent },
174 /* CreateWindow (for a child popup window, not initially visible) */
175 static const struct message WmCreateChildPopupSeq[] = {
176 { HCBT_CREATEWND, hook },
177 { WM_NCCREATE, sent },
178 { WM_NCCALCSIZE, sent|wparam, 0 },
184 /* CreateWindow (for a popup window, not initially visible,
185 * which sets WS_VISIBLE in WM_CREATE handler)
187 static const struct message WmCreateInvisiblePopupSeq[] = {
188 { HCBT_CREATEWND, hook },
189 { WM_NCCREATE, sent },
190 { WM_NCCALCSIZE, sent|wparam, 0 },
192 { WM_STYLECHANGING, sent },
193 { WM_STYLECHANGED, sent },
198 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
199 * for a popup window with WS_VISIBLE style set
201 static const struct message WmShowVisiblePopupSeq_2[] = {
202 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
205 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
206 * for a popup window with WS_VISIBLE style set
208 static const struct message WmShowVisiblePopupSeq_3[] = {
209 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
210 { HCBT_ACTIVATE, hook },
211 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
212 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
213 { WM_NCACTIVATE, sent|wparam, 1 },
214 { WM_ACTIVATE, sent|wparam, 1 },
215 { HCBT_SETFOCUS, hook },
216 { WM_KILLFOCUS, sent|parent },
217 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
218 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
219 { WM_SETFOCUS, sent|defwinproc },
222 /* CreateWindow (for child window, not initially visible) */
223 static const struct message WmCreateChildSeq[] = {
224 { HCBT_CREATEWND, hook },
225 { WM_NCCREATE, sent },
226 /* child is inserted into parent's child list after WM_NCCREATE returns */
227 { WM_NCCALCSIZE, sent|wparam, 0 },
231 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
234 /* CreateWindow (for maximized child window, not initially visible) */
235 static const struct message WmCreateMaximizedChildSeq[] = {
236 { HCBT_CREATEWND, hook },
237 { WM_NCCREATE, sent },
238 { WM_NCCALCSIZE, sent|wparam, 0 },
242 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
243 { WM_GETMINMAXINFO, sent },
244 { WM_WINDOWPOSCHANGING, sent },
245 { WM_NCCALCSIZE, sent|wparam, 1 },
246 { WM_WINDOWPOSCHANGED, sent },
247 { WM_SIZE, sent|defwinproc },
248 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
251 /* CreateWindow (for a child window, initially visible) */
252 static const struct message WmCreateVisibleChildSeq[] = {
253 { HCBT_CREATEWND, hook },
254 { WM_NCCREATE, sent },
255 /* child is inserted into parent's child list after WM_NCCREATE returns */
256 { WM_NCCALCSIZE, sent|wparam, 0 },
260 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
261 { WM_SHOWWINDOW, sent|wparam, 1 },
262 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
263 { WM_ERASEBKGND, sent|parent|optional },
264 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
267 /* ShowWindow(SW_SHOW) for a not visible child window */
268 static const struct message WmShowChildSeq[] = {
269 { WM_SHOWWINDOW, sent|wparam, 1 },
270 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
271 { WM_ERASEBKGND, sent|parent|optional },
272 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
275 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
276 * for a not visible child window
278 static const struct message WmShowChildSeq_2[] = {
279 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
280 { WM_CHILDACTIVATE, sent },
281 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
284 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
285 * for a not visible child window
287 static const struct message WmShowChildSeq_3[] = {
288 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
289 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
292 /* DestroyWindow for a visible child window */
293 static const struct message WmDestroyChildSeq[] = {
294 { HCBT_DESTROYWND, hook },
295 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
296 { WM_SHOWWINDOW, sent|wparam, 0 },
297 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
298 { WM_ERASEBKGND, sent|parent|optional },
299 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
300 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
301 { WM_KILLFOCUS, sent },
302 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
303 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
304 { WM_SETFOCUS, sent|parent },
305 { WM_DESTROY, sent },
306 { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
307 { WM_NCDESTROY, sent },
308 { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
311 /* Moving the mouse in nonclient area */
312 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
313 { WM_NCHITTEST, sent },
314 { WM_SETCURSOR, sent },
315 { WM_NCMOUSEMOVE, posted },
318 /* Moving the mouse in client area */
319 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
320 { WM_NCHITTEST, sent },
321 { WM_SETCURSOR, sent },
322 { WM_MOUSEMOVE, posted },
325 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
326 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
327 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
328 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
329 { WM_GETMINMAXINFO, sent|defwinproc },
330 { WM_ENTERSIZEMOVE, sent|defwinproc },
331 { WM_WINDOWPOSCHANGING, sent|defwinproc },
332 { WM_WINDOWPOSCHANGED, sent|defwinproc },
333 { WM_MOVE, sent|defwinproc },
334 { WM_EXITSIZEMOVE, sent|defwinproc },
337 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
338 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
339 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
340 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
341 { WM_GETMINMAXINFO, sent|defwinproc },
342 { WM_ENTERSIZEMOVE, sent|defwinproc },
343 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
344 { WM_WINDOWPOSCHANGING, sent|defwinproc },
345 { WM_GETMINMAXINFO, sent|defwinproc },
346 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
347 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
348 { WM_GETTEXT, sent|defwinproc },
349 { WM_ERASEBKGND, sent|defwinproc },
350 { WM_WINDOWPOSCHANGED, sent|defwinproc },
351 { WM_MOVE, sent|defwinproc },
352 { WM_SIZE, sent|defwinproc },
353 { WM_EXITSIZEMOVE, sent|defwinproc },
356 /* Resizing child window with MoveWindow (32) */
357 static const struct message WmResizingChildWithMoveWindowSeq[] = {
358 { WM_WINDOWPOSCHANGING, sent },
359 { WM_NCCALCSIZE, sent|wparam, 1 },
360 { WM_ERASEBKGND, sent|optional },
361 { WM_WINDOWPOSCHANGED, sent },
362 { WM_MOVE, sent|defwinproc },
363 { WM_SIZE, sent|defwinproc },
366 /* Clicking on inactive button */
367 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
368 { WM_NCHITTEST, sent },
369 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
370 { WM_MOUSEACTIVATE, sent },
371 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
372 { WM_SETCURSOR, sent },
373 { WM_SETCURSOR, sent|parent|defwinproc },
374 { WM_LBUTTONDOWN, posted },
375 { WM_KILLFOCUS, posted|parent },
376 { WM_SETFOCUS, posted },
377 { WM_CTLCOLORBTN, posted|parent },
378 { BM_SETSTATE, posted },
379 { WM_CTLCOLORBTN, posted|parent },
380 { WM_LBUTTONUP, posted },
381 { BM_SETSTATE, posted },
382 { WM_CTLCOLORBTN, posted|parent },
383 { WM_COMMAND, posted|parent },
386 /* Reparenting a button (16/32) */
387 /* The last child (button) reparented gets topmost for its new parent. */
388 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
389 { WM_SHOWWINDOW, sent|wparam, 0 },
390 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
391 { WM_ERASEBKGND, sent|parent },
392 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
393 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
394 { WM_CHILDACTIVATE, sent },
395 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
396 { WM_MOVE, sent|defwinproc },
397 { WM_SHOWWINDOW, sent|wparam, 1 },
400 /* Creation of a custom dialog (32) */
401 static const struct message WmCreateCustomDialogSeq[] = {
402 { HCBT_CREATEWND, hook },
403 { WM_GETMINMAXINFO, sent },
404 { WM_NCCREATE, sent },
405 { WM_NCCALCSIZE, sent|wparam, 0 },
407 { WM_SHOWWINDOW, sent|wparam, 1 },
408 { HCBT_ACTIVATE, hook },
409 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
410 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
411 { WM_NCACTIVATE, sent|wparam, 1 },
412 { WM_GETTEXT, sent|optional|defwinproc },
413 { WM_GETICON, sent|optional|defwinproc },
414 { WM_GETICON, sent|optional|defwinproc },
415 { WM_GETICON, sent|optional|defwinproc },
416 { WM_GETTEXT, sent|optional|defwinproc },
417 { WM_ACTIVATE, sent|wparam, 1 },
418 { WM_KILLFOCUS, sent|parent },
419 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
420 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
421 { WM_SETFOCUS, sent },
422 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
423 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
424 { WM_NCPAINT, sent|wparam, 1 },
425 { WM_GETTEXT, sent|optional|defwinproc },
426 { WM_GETICON, sent|optional|defwinproc },
427 { WM_GETICON, sent|optional|defwinproc },
428 { WM_GETICON, sent|optional|defwinproc },
429 { WM_GETTEXT, sent|optional|defwinproc },
430 { WM_ERASEBKGND, sent },
431 { WM_CTLCOLORDLG, sent|defwinproc },
432 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
433 { WM_GETTEXT, sent|optional },
434 { WM_GETICON, sent|optional },
435 { WM_GETICON, sent|optional },
436 { WM_GETICON, sent|optional },
437 { WM_GETTEXT, sent|optional },
438 { WM_NCCALCSIZE, sent|optional },
439 { WM_NCPAINT, sent|optional },
440 { WM_GETTEXT, sent|optional|defwinproc },
441 { WM_GETICON, sent|optional|defwinproc },
442 { WM_GETICON, sent|optional|defwinproc },
443 { WM_GETICON, sent|optional|defwinproc },
444 { WM_GETTEXT, sent|optional|defwinproc },
445 { WM_ERASEBKGND, sent|optional },
446 { WM_CTLCOLORDLG, sent|optional|defwinproc },
451 /* Calling EndDialog for a custom dialog (32) */
452 static const struct message WmEndCustomDialogSeq[] = {
453 { WM_WINDOWPOSCHANGING, sent },
454 { WM_WINDOWPOSCHANGED, sent },
455 { WM_GETTEXT, sent|optional },
456 { WM_GETICON, sent|optional },
457 { WM_GETICON, sent|optional },
458 { WM_GETICON, sent|optional },
459 { HCBT_ACTIVATE, hook },
460 { WM_NCACTIVATE, sent|wparam, 0 },
461 { WM_GETTEXT, sent|optional|defwinproc },
462 { WM_GETICON, sent|optional|defwinproc },
463 { WM_GETICON, sent|optional|defwinproc },
464 { WM_GETICON, sent|optional|defwinproc },
465 { WM_GETTEXT, sent|optional|defwinproc },
466 { WM_ACTIVATE, sent|wparam, 0 },
467 { WM_WINDOWPOSCHANGING, sent|optional },
468 { HCBT_SETFOCUS, hook },
469 { WM_KILLFOCUS, sent },
470 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
471 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
472 { WM_SETFOCUS, sent|parent|defwinproc },
475 /* Creation and destruction of a modal dialog (32) */
476 static const struct message WmModalDialogSeq[] = {
477 { WM_CANCELMODE, sent|parent },
478 { HCBT_SETFOCUS, hook },
479 { WM_KILLFOCUS, sent|parent },
480 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
481 { WM_ENABLE, sent|parent|wparam, 0 },
482 { HCBT_CREATEWND, hook },
483 { WM_SETFONT, sent },
484 { WM_INITDIALOG, sent },
485 { WM_CHANGEUISTATE, sent|optional },
486 { WM_SHOWWINDOW, sent },
487 { HCBT_ACTIVATE, hook },
488 { WM_WINDOWPOSCHANGING, sent },
489 { WM_NCACTIVATE, sent|wparam, 1 },
490 { WM_GETICON, sent|optional },
491 { WM_GETICON, sent|optional },
492 { WM_GETICON, sent|optional },
493 { WM_GETTEXT, sent|optional },
494 { WM_ACTIVATE, sent|wparam, 1 },
495 { WM_WINDOWPOSCHANGING, sent },
496 { WM_NCPAINT, sent },
497 { WM_GETICON, sent|optional },
498 { WM_GETICON, sent|optional },
499 { WM_GETICON, sent|optional },
500 { WM_GETTEXT, sent|optional },
501 { WM_ERASEBKGND, sent },
502 { WM_CTLCOLORDLG, sent },
503 { WM_WINDOWPOSCHANGED, sent },
504 { WM_GETICON, sent|optional },
505 { WM_GETICON, sent|optional },
506 { WM_GETICON, sent|optional },
507 { WM_GETTEXT, sent|optional },
508 { WM_NCCALCSIZE, sent|optional },
509 { WM_NCPAINT, sent|optional },
510 { WM_GETICON, sent|optional },
511 { WM_GETICON, sent|optional },
512 { WM_GETICON, sent|optional },
513 { WM_GETTEXT, sent|optional },
514 { WM_ERASEBKGND, sent|optional },
515 { WM_CTLCOLORDLG, sent|optional },
516 { WM_PAINT, sent|optional },
517 { WM_CTLCOLORBTN, sent },
518 { WM_ENTERIDLE, sent|parent },
520 { WM_ENABLE, sent|parent|wparam, 1 },
521 { WM_WINDOWPOSCHANGING, sent },
522 { WM_WINDOWPOSCHANGED, sent },
523 { WM_GETICON, sent|optional },
524 { WM_GETICON, sent|optional },
525 { WM_GETICON, sent|optional },
526 { WM_GETTEXT, sent|optional },
527 { HCBT_ACTIVATE, hook },
528 { WM_NCACTIVATE, sent|wparam, 0 },
529 { WM_GETICON, sent|optional },
530 { WM_GETICON, sent|optional },
531 { WM_GETICON, sent|optional },
532 { WM_GETTEXT, sent|optional },
533 { WM_ACTIVATE, sent|wparam, 0 },
534 { WM_WINDOWPOSCHANGING, sent|optional },
535 { HCBT_SETFOCUS, hook },
536 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
537 { WM_SETFOCUS, sent|parent|defwinproc },
538 { HCBT_DESTROYWND, hook },
539 { WM_DESTROY, sent },
540 { WM_NCDESTROY, sent },
543 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
544 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
545 /* (inside dialog proc, handling WM_INITDIALOG) */
546 { WM_WINDOWPOSCHANGING, sent },
547 { WM_NCCALCSIZE, sent },
548 { WM_NCACTIVATE, sent|parent|wparam, 0 },
549 { WM_GETTEXT, sent|defwinproc },
550 { WM_ACTIVATE, sent|parent|wparam, 0 },
551 { WM_WINDOWPOSCHANGING, sent },
552 { WM_WINDOWPOSCHANGING, sent|parent },
553 { WM_NCACTIVATE, sent|wparam, 1 },
554 { WM_ACTIVATE, sent|wparam, 1 },
555 { WM_WINDOWPOSCHANGED, sent },
556 { WM_SIZE, sent|defwinproc },
557 /* (setting focus) */
558 { WM_SHOWWINDOW, sent|wparam, 1 },
559 { WM_WINDOWPOSCHANGING, sent },
560 { WM_NCPAINT, sent },
561 { WM_GETTEXT, sent|defwinproc },
562 { WM_ERASEBKGND, sent },
563 { WM_CTLCOLORDLG, sent|defwinproc },
564 { WM_WINDOWPOSCHANGED, sent },
566 /* (bunch of WM_CTLCOLOR* for each control) */
567 { WM_PAINT, sent|parent },
568 { WM_ENTERIDLE, sent|parent|wparam, 0 },
569 { WM_SETCURSOR, sent|parent },
572 /* SetMenu for NonVisible windows with size change*/
573 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
574 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
575 { WM_NCCALCSIZE, sent|wparam, 1 },
576 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
577 { WM_MOVE, sent|defwinproc },
578 { WM_SIZE, sent|defwinproc },
579 { WM_GETICON, sent|optional },
580 { WM_GETICON, sent|optional },
581 { WM_GETICON, sent|optional },
582 { WM_GETTEXT, sent|optional },
583 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
586 /* SetMenu for NonVisible windows with no size change */
587 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
588 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
589 { WM_NCCALCSIZE, sent|wparam, 1 },
590 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
593 /* SetMenu for Visible windows with size change */
594 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
595 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
596 { WM_NCCALCSIZE, sent|wparam, 1 },
597 { WM_NCPAINT, sent|wparam, 1 },
598 { WM_GETTEXT, sent|defwinproc|optional },
599 { WM_ERASEBKGND, sent|optional },
600 { WM_ACTIVATE, sent|optional },
601 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
602 { WM_MOVE, sent|defwinproc },
603 { WM_SIZE, sent|defwinproc },
604 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
605 { WM_NCPAINT, sent|wparam|optional, 1 },
606 { WM_ERASEBKGND, sent|optional },
609 /* SetMenu for Visible windows with no size change */
610 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
611 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
612 { WM_NCCALCSIZE, sent|wparam, 1 },
613 { WM_NCPAINT, sent|wparam, 1 },
614 { WM_GETTEXT, sent|defwinproc|optional },
615 { WM_ERASEBKGND, sent|optional },
616 { WM_ACTIVATE, sent|optional },
617 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
620 /* DrawMenuBar for a visible window */
621 static const struct message WmDrawMenuBarSeq[] =
623 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
624 { WM_NCCALCSIZE, sent|wparam, 1 },
625 { WM_NCPAINT, sent|wparam, 1 },
626 { WM_GETTEXT, sent|defwinproc|optional },
627 { WM_ERASEBKGND, sent|optional },
628 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
632 static const struct message WmSetRedrawFalseSeq[] =
634 { WM_SETREDRAW, sent|wparam, 0 },
638 static const struct message WmSetRedrawTrueSeq[] =
640 { WM_SETREDRAW, sent|wparam, 1 },
644 static const struct message WmEnableWindowSeq[] =
646 { WM_CANCELMODE, sent },
651 static const struct message WmGetScrollRangeSeq[] =
653 { SBM_GETRANGE, sent },
656 static const struct message WmGetScrollInfoSeq[] =
658 { SBM_GETSCROLLINFO, sent },
661 static const struct message WmSetScrollRangeSeq[] =
663 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
664 sends SBM_SETSCROLLINFO.
666 { SBM_SETSCROLLINFO, sent },
669 /* SetScrollRange for a window without a non-client area */
670 static const struct message WmSetScrollRangeHVSeq[] =
672 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
673 { WM_NCCALCSIZE, sent|wparam, 1 },
674 { WM_GETTEXT, sent|defwinproc|optional },
675 { WM_ERASEBKGND, sent|optional },
676 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
679 /* SetScrollRange for a window with a non-client area */
680 static const struct message WmSetScrollRangeHV_NC_Seq[] =
682 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
683 { WM_NCCALCSIZE, sent|wparam, 1 },
684 { WM_NCPAINT, sent|optional },
685 { WM_GETTEXT, sent|defwinproc|optional },
686 { WM_ERASEBKGND, sent|optional },
687 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
688 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
689 { WM_SIZE, sent|defwinproc },
693 static int after_end_dialog;
694 static int sequence_cnt, sequence_size;
695 static struct message* sequence;
697 static void add_message(const struct message *msg)
702 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
704 if (sequence_cnt == sequence_size)
707 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
711 sequence[sequence_cnt].message = msg->message;
712 sequence[sequence_cnt].flags = msg->flags;
713 sequence[sequence_cnt].wParam = msg->wParam;
714 sequence[sequence_cnt].lParam = msg->lParam;
719 static void flush_sequence()
721 HeapFree(GetProcessHeap(), 0, sequence);
723 sequence_cnt = sequence_size = 0;
726 static void ok_sequence(const struct message *expected, const char *context)
728 static const struct message end_of_sequence = { 0, 0, 0, 0 };
729 const struct message *actual;
731 add_message(&end_of_sequence);
735 while (expected->message && actual->message)
737 trace("expected %04x - actual %04x\n", expected->message, actual->message);
739 if (expected->message == actual->message)
741 if (expected->flags & wparam)
742 ok (expected->wParam == actual->wParam,
743 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
744 context, expected->message, expected->wParam, actual->wParam);
745 if (expected->flags & lparam)
746 ok (expected->lParam == actual->lParam,
747 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
748 context, expected->message, expected->lParam, actual->lParam);
749 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
750 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
751 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
752 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
753 "%s: the msg 0x%04x should have been %s\n",
754 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
755 ok ((expected->flags & parent) == (actual->flags & parent),
756 "%s: the msg 0x%04x was expected in %s\n",
757 context, expected->message, (expected->flags & parent) ? "parent" : "child");
758 ok ((expected->flags & hook) == (actual->flags & hook),
759 "%s: the msg 0x%04x should have been sent by a hook\n",
760 context, expected->message);
764 else if (expected->flags & optional)
769 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
770 context, expected->message, actual->message);
777 /* skip all optional trailing messages */
778 while (expected->message && (expected->flags & optional))
782 if (expected->message || actual->message)
783 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
784 context, expected->message, actual->message);
790 /******************************** MDI test **********************************/
792 /* CreateWindow for MDI frame window, initially visible */
793 static const struct message WmCreateMDIframeSeq[] = {
794 { HCBT_CREATEWND, hook },
795 { WM_GETMINMAXINFO, sent },
796 { WM_NCCREATE, sent },
797 { WM_NCCALCSIZE, sent|wparam, 0 },
799 { WM_SHOWWINDOW, sent|wparam, 1 },
800 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
801 { HCBT_ACTIVATE, hook },
802 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
803 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
804 { WM_WINDOWPOSCHANGED, sent|wparam|optional, 0 }, /* Win9x */
805 { WM_ACTIVATEAPP, sent|wparam, 1 },
806 { WM_NCACTIVATE, sent|wparam, 1 },
807 { WM_ACTIVATE, sent|wparam, 1 },
808 { HCBT_SETFOCUS, hook },
809 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
810 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
811 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
816 /* DestroyWindow for MDI frame window, initially visible */
817 static const struct message WmDestroyMDIframeSeq[] = {
818 { HCBT_DESTROYWND, hook },
819 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
820 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
821 { WM_NCACTIVATE, sent|wparam, 0 },
822 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
823 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
824 { WM_DESTROY, sent },
825 { WM_NCDESTROY, sent },
828 /* CreateWindow for MDI client window, initially visible */
829 static const struct message WmCreateMDIclientSeq[] = {
830 { HCBT_CREATEWND, hook },
831 { WM_NCCREATE, sent },
832 { WM_NCCALCSIZE, sent|wparam, 0 },
836 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
837 { WM_SHOWWINDOW, sent|wparam, 1 },
838 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
839 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
842 /* DestroyWindow for MDI client window, initially visible */
843 static const struct message WmDestroyMDIclientSeq[] = {
844 { HCBT_DESTROYWND, hook },
845 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
846 { WM_SHOWWINDOW, sent|wparam, 0 },
847 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
848 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
849 { WM_DESTROY, sent },
850 { WM_NCDESTROY, sent },
853 /* CreateWindow for MDI child window, initially visible */
854 static const struct message WmCreateMDIchildVisibleSeq[] = {
855 { HCBT_CREATEWND, hook },
856 { WM_NCCREATE, sent },
857 { WM_NCCALCSIZE, sent|wparam, 0 },
861 /* Win2k sends wparam set to
862 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
863 * while Win9x doesn't bother to set child window id according to
864 * CLIENTCREATESTRUCT.idFirstChild
866 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
867 { WM_SHOWWINDOW, sent|wparam, 1 },
868 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
869 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
870 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
871 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE*/
872 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
873 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 }, /*SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/
875 /* Win9x: message sequence terminates here. */
877 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
878 { HCBT_SETFOCUS, hook }, /* in MDI client */
879 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
880 { WM_SETFOCUS, sent }, /* in MDI client */
881 { HCBT_SETFOCUS, hook },
882 { WM_KILLFOCUS, sent }, /* in MDI client */
883 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
884 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
885 { WM_SETFOCUS, sent|defwinproc },
886 { WM_MDIACTIVATE, sent|defwinproc },
889 /* DestroyWindow for MDI child window, initially visible */
890 static const struct message WmDestroyMDIchildVisibleSeq[] = {
891 { HCBT_DESTROYWND, hook },
892 /* Win2k sends wparam set to
893 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
894 * while Win9x doesn't bother to set child window id according to
895 * CLIENTCREATESTRUCT.idFirstChild
897 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
898 { WM_SHOWWINDOW, sent|wparam, 0 },
899 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
900 { WM_ERASEBKGND, sent|parent|optional },
901 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
903 /* { WM_DESTROY, sent }
904 * Win9x: message sequence terminates here.
907 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
908 { WM_KILLFOCUS, sent },
909 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
910 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
911 { WM_SETFOCUS, sent }, /* in MDI client */
913 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
914 { WM_KILLFOCUS, sent }, /* in MDI client */
915 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
916 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
917 { WM_SETFOCUS, sent }, /* in MDI client */
919 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
920 { WM_KILLFOCUS, sent },
921 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
922 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
923 { WM_SETFOCUS, sent }, /* in MDI client */
925 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
926 { WM_KILLFOCUS, sent }, /* in MDI client */
927 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
928 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
929 { WM_SETFOCUS, sent }, /* in MDI client */
931 { WM_DESTROY, sent },
933 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
934 { WM_KILLFOCUS, sent },
935 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
936 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
937 { WM_SETFOCUS, sent }, /* in MDI client */
939 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
940 { WM_KILLFOCUS, sent }, /* in MDI client */
941 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
942 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
943 { WM_SETFOCUS, sent }, /* in MDI client */
945 { WM_NCDESTROY, sent },
948 /* CreateWindow for MDI child window, initially invisible */
949 static const struct message WmCreateMDIchildInvisibleSeq[] = {
950 { HCBT_CREATEWND, hook },
951 { WM_NCCREATE, sent },
952 { WM_NCCALCSIZE, sent|wparam, 0 },
956 /* Win2k sends wparam set to
957 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
958 * while Win9x doesn't bother to set child window id according to
959 * CLIENTCREATESTRUCT.idFirstChild
961 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
964 /* DestroyWindow for MDI child window, initially invisible */
965 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
966 { HCBT_DESTROYWND, hook },
967 /* Win2k sends wparam set to
968 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
969 * while Win9x doesn't bother to set child window id according to
970 * CLIENTCREATESTRUCT.idFirstChild
972 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
973 { WM_DESTROY, sent },
974 { WM_NCDESTROY, sent },
978 static HWND mdi_client;
979 static WNDPROC old_mdi_client_proc;
981 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
985 /* do not log painting messages */
986 if (message != WM_PAINT &&
987 message != WM_ERASEBKGND &&
988 message != WM_NCPAINT &&
989 message != WM_GETTEXT)
991 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
993 msg.message = message;
994 msg.flags = sent|wparam|lparam;
1000 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1003 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1005 static long defwndproc_counter = 0;
1009 /* do not log painting messages */
1010 if (message != WM_PAINT &&
1011 message != WM_ERASEBKGND &&
1012 message != WM_NCPAINT &&
1013 message != WM_GETTEXT)
1015 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1019 case WM_WINDOWPOSCHANGING:
1020 case WM_WINDOWPOSCHANGED:
1022 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1024 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1025 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1026 winpos->hwnd, winpos->hwndInsertAfter,
1027 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1032 msg.message = message;
1033 msg.flags = sent|wparam|lparam;
1034 if (defwndproc_counter) msg.flags |= defwinproc;
1035 msg.wParam = wParam;
1036 msg.lParam = lParam;
1040 defwndproc_counter++;
1041 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1042 defwndproc_counter--;
1047 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1049 static long defwndproc_counter = 0;
1053 /* do not log painting messages */
1054 if (message != WM_PAINT &&
1055 message != WM_ERASEBKGND &&
1056 message != WM_NCPAINT &&
1057 message != WM_GETTEXT)
1059 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1061 msg.message = message;
1062 msg.flags = sent|wparam|lparam;
1063 if (defwndproc_counter) msg.flags |= defwinproc;
1064 msg.wParam = wParam;
1065 msg.lParam = lParam;
1069 defwndproc_counter++;
1070 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
1071 defwndproc_counter--;
1076 static BOOL mdi_RegisterWindowClasses(void)
1081 cls.lpfnWndProc = mdi_frame_wnd_proc;
1084 cls.hInstance = GetModuleHandleA(0);
1086 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1087 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1088 cls.lpszMenuName = NULL;
1089 cls.lpszClassName = "MDI_frame_class";
1090 if (!RegisterClassA(&cls)) return FALSE;
1092 cls.lpfnWndProc = mdi_child_wnd_proc;
1093 cls.lpszClassName = "MDI_child_class";
1094 if (!RegisterClassA(&cls)) return FALSE;
1096 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
1097 old_mdi_client_proc = cls.lpfnWndProc;
1098 cls.hInstance = GetModuleHandleA(0);
1099 cls.lpfnWndProc = mdi_client_hook_proc;
1100 cls.lpszClassName = "MDI_client_class";
1101 if (!RegisterClassA(&cls)) assert(0);
1106 static void test_mdi_messages(void)
1108 CLIENTCREATESTRUCT client_cs;
1109 HWND mdi_frame, mdi_child;
1111 assert(mdi_RegisterWindowClasses());
1115 trace("creating MDI frame window\n");
1116 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1117 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1118 WS_MAXIMIZEBOX | WS_VISIBLE,
1119 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1120 GetDesktopWindow(), 0,
1121 GetModuleHandleA(0), NULL);
1123 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window");
1125 trace("creating MDI client window\n");
1126 client_cs.hWindowMenu = 0;
1127 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
1128 mdi_client = CreateWindowExA(0, "MDI_client_class",
1130 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
1132 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
1134 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window");
1136 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
1141 trace("creating visible MDI child window\n");
1142 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1143 WS_CHILD | WS_VISIBLE,
1144 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1145 mdi_client, 0, GetModuleHandleA(0), NULL);
1147 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window");
1149 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1150 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1152 DestroyWindow(mdi_child);
1153 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window");
1158 trace("creating invisible MDI child window\n");
1159 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1161 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1162 mdi_client, 0, GetModuleHandleA(0), NULL);
1164 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window");
1166 ok(!(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
1167 ok(!IsWindowVisible(mdi_child), "MDI child should not be visible\n");
1169 DestroyWindow(mdi_child);
1170 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window");
1172 DestroyWindow(mdi_client);
1173 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window");
1175 DestroyWindow(mdi_frame);
1176 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window");
1178 /************************* End of MDI test **********************************/
1180 static void test_WM_SETREDRAW(HWND hwnd)
1182 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
1186 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
1187 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE");
1189 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
1190 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
1193 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
1194 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE");
1196 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1197 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
1199 /* restore original WS_VISIBLE state */
1200 SetWindowLongA(hwnd, GWL_STYLE, style);
1205 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1209 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1211 msg.message = message;
1212 msg.flags = sent|wparam|lparam;
1213 msg.wParam = wParam;
1214 msg.lParam = lParam;
1217 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
1218 if (message == WM_TIMER) EndDialog( hwnd, 0 );
1222 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1224 DWORD style, exstyle;
1227 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1228 style = GetWindowLongA(hwnd, GWL_STYLE);
1229 /* do not be confused by WS_DLGFRAME set */
1230 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1232 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1233 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1235 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1236 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1237 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC");
1239 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)");
1241 style = GetWindowLongA(hwnd, GWL_STYLE);
1242 if (set) ok(style & set, "style %08lx should be set\n", set);
1243 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1245 /* a subsequent call should do nothing */
1246 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1247 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT)");
1251 trace("Ignore GetScrollRange error below if you are on Win9x\n");
1252 ok(GetScrollRange(hwnd, ctl, &xmin, &xmax), "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
1253 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)");
1254 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
1255 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
1258 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1260 DWORD style, exstyle;
1263 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1264 style = GetWindowLongA(hwnd, GWL_STYLE);
1265 /* do not be confused by WS_DLGFRAME set */
1266 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1268 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1269 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1271 si.cbSize = sizeof(si);
1272 si.fMask = SIF_RANGE;
1275 SetScrollInfo(hwnd, ctl, &si, TRUE);
1276 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1277 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC");
1279 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1281 style = GetWindowLongA(hwnd, GWL_STYLE);
1282 if (set) ok(style & set, "style %08lx should be set\n", set);
1283 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1285 /* a subsequent call should do nothing */
1286 SetScrollInfo(hwnd, ctl, &si, TRUE);
1287 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1289 si.fMask = SIF_PAGE;
1291 SetScrollInfo(hwnd, ctl, &si, FALSE);
1292 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1296 SetScrollInfo(hwnd, ctl, &si, FALSE);
1297 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1299 si.fMask = SIF_RANGE;
1300 si.nMin = 0xdeadbeef;
1301 si.nMax = 0xdeadbeef;
1302 ok(GetScrollInfo(hwnd, ctl, &si), "GetScrollInfo error %ld\n", GetLastError());
1303 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)");
1304 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
1305 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
1308 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
1309 static void test_scroll_messages(HWND hwnd)
1316 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1317 if (sequence->message != WmGetScrollRangeSeq[0].message)
1318 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1319 /* values of min and max are undefined */
1322 ok(SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE), "SetScrollRange error %ld\n", GetLastError());
1323 if (sequence->message != WmSetScrollRangeSeq[0].message)
1324 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1329 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1330 if (sequence->message != WmGetScrollRangeSeq[0].message)
1331 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1332 /* values of min and max are undefined */
1335 si.cbSize = sizeof(si);
1336 si.fMask = SIF_RANGE;
1339 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1340 if (sequence->message != WmSetScrollRangeSeq[0].message)
1341 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1344 si.fMask = SIF_PAGE;
1346 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1347 if (sequence->message != WmSetScrollRangeSeq[0].message)
1348 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1353 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1354 if (sequence->message != WmSetScrollRangeSeq[0].message)
1355 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1358 si.fMask = SIF_RANGE;
1359 si.nMin = 0xdeadbeef;
1360 si.nMax = 0xdeadbeef;
1361 ok(GetScrollInfo(hwnd, SB_CTL, &si), "GetScrollInfo error %ld\n", GetLastError());
1362 if (sequence->message != WmGetScrollInfoSeq[0].message)
1363 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1364 /* values of min and max are undefined */
1367 /* set WS_HSCROLL */
1368 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1369 /* clear WS_HSCROLL */
1370 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1372 /* set WS_HSCROLL */
1373 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1374 /* clear WS_HSCROLL */
1375 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1377 /* set WS_VSCROLL */
1378 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1379 /* clear WS_VSCROLL */
1380 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1382 /* set WS_VSCROLL */
1383 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1384 /* clear WS_VSCROLL */
1385 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1388 /* test if we receive the right sequence of messages */
1389 static void test_messages(void)
1391 HWND hwnd, hparent, hchild;
1392 HWND hchild2, hbutton;
1395 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1396 100, 100, 200, 200, 0, 0, 0, NULL);
1397 ok (hwnd != 0, "Failed to create overlapped window\n");
1398 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
1400 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
1401 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
1402 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible");
1404 /* test WM_SETREDRAW on a not visible top level window */
1405 test_WM_SETREDRAW(hwnd);
1407 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1408 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped");
1409 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
1411 ok(GetActiveWindow() == hwnd, "window should be active\n");
1412 ok(GetFocus() == hwnd, "window should have input focus\n");
1413 ShowWindow(hwnd, SW_HIDE);
1414 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped");
1416 ShowWindow(hwnd, SW_SHOW);
1417 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped");
1419 ok(GetActiveWindow() == hwnd, "window should be active\n");
1420 ok(GetFocus() == hwnd, "window should have input focus\n");
1421 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1422 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped");
1423 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
1425 /* test WM_SETREDRAW on a visible top level window */
1426 ShowWindow(hwnd, SW_SHOW);
1427 test_WM_SETREDRAW(hwnd);
1429 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
1430 test_scroll_messages(hwnd);
1432 DestroyWindow(hwnd);
1433 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
1435 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1436 100, 100, 200, 200, 0, 0, 0, NULL);
1437 ok (hparent != 0, "Failed to create parent window\n");
1440 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
1441 0, 0, 10, 10, hparent, 0, 0, NULL);
1442 ok (hchild != 0, "Failed to create child window\n");
1443 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child");
1444 DestroyWindow(hchild);
1447 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1448 0, 0, 10, 10, hparent, 0, 0, NULL);
1449 ok (hchild != 0, "Failed to create child window\n");
1450 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child");
1452 trace("testing scroll APIs on a visible child window %p\n", hchild);
1453 test_scroll_messages(hchild);
1455 DestroyWindow(hchild);
1458 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
1459 0, 0, 10, 10, hparent, 0, 0, NULL);
1460 ok (hchild != 0, "Failed to create child window\n");
1461 ok_sequence(WmCreateChildSeq, "CreateWindow:child");
1463 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
1464 100, 100, 50, 50, hparent, 0, 0, NULL);
1465 ok (hchild2 != 0, "Failed to create child2 window\n");
1468 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
1469 0, 100, 50, 50, hchild, 0, 0, NULL);
1470 ok (hbutton != 0, "Failed to create button window\n");
1472 /* test WM_SETREDRAW on a not visible child window */
1473 test_WM_SETREDRAW(hchild);
1475 ShowWindow(hchild, SW_SHOW);
1476 ok_sequence(WmShowChildSeq, "ShowWindow:child");
1478 /* test WM_SETREDRAW on a visible child window */
1479 test_WM_SETREDRAW(hchild);
1481 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
1482 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
1484 ShowWindow(hchild, SW_HIDE);
1486 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1487 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2");
1489 ShowWindow(hchild, SW_HIDE);
1491 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
1492 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3");
1494 /* DestroyWindow sequence below expects that a child has focus */
1498 DestroyWindow(hchild);
1499 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
1500 DestroyWindow(hchild2);
1501 DestroyWindow(hbutton);
1504 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
1505 0, 0, 100, 100, hparent, 0, 0, NULL);
1506 ok (hchild != 0, "Failed to create child popup window\n");
1507 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup");
1508 DestroyWindow(hchild);
1510 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
1512 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
1513 0, 0, 100, 100, hparent, 0, 0, NULL);
1514 ok (hchild != 0, "Failed to create popup window\n");
1515 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
1516 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1517 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1519 ShowWindow(hchild, SW_SHOW);
1520 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup");
1522 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1523 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2");
1525 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1526 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3");
1527 DestroyWindow(hchild);
1529 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
1530 * changes nothing in message sequences.
1533 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
1534 0, 0, 100, 100, hparent, 0, 0, NULL);
1535 ok (hchild != 0, "Failed to create popup window\n");
1536 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
1537 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1538 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1540 ShowWindow(hchild, SW_SHOW);
1541 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup");
1543 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1544 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2");
1545 DestroyWindow(hchild);
1548 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
1549 0, 0, 100, 100, hparent, 0, 0, NULL);
1550 ok(hwnd != 0, "Failed to create custom dialog window\n");
1551 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog");
1553 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
1554 test_scroll_messages(hwnd);
1557 after_end_dialog = 1;
1558 EndDialog( hwnd, 0 );
1559 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog");
1561 DestroyWindow(hwnd);
1562 after_end_dialog = 0;
1565 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
1566 ok_sequence(WmModalDialogSeq, "ModalDialog");
1568 DestroyWindow(hparent);
1571 /* Message sequence for SetMenu */
1572 hmenu = CreateMenu();
1573 ok (hmenu != 0, "Failed to create menu\n");
1574 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
1575 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1576 100, 100, 200, 200, 0, hmenu, 0, NULL);
1577 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
1578 ok (SetMenu(hwnd, 0), "SetMenu\n");
1579 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");
1580 ok (SetMenu(hwnd, 0), "SetMenu\n");
1581 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");
1582 ShowWindow(hwnd, SW_SHOW);
1584 ok (SetMenu(hwnd, 0), "SetMenu\n");
1585 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");
1586 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
1587 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");
1589 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
1590 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar");
1592 DestroyWindow(hwnd);
1595 /* Message sequence for EnableWindow */
1596 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1597 100, 100, 200, 200, 0, 0, 0, NULL);
1598 ok (hparent != 0, "Failed to create parent window\n");
1599 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1600 0, 0, 10, 10, hparent, 0, 0, NULL);
1601 ok (hchild != 0, "Failed to create child window\n");
1606 EnableWindow(hparent, FALSE);
1607 ok_sequence(WmEnableWindowSeq, "EnableWindow");
1609 DestroyWindow(hparent);
1613 /****************** button message test *************************/
1614 static const struct message WmSetFocusButtonSeq[] =
1616 { HCBT_SETFOCUS, hook },
1617 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1618 { WM_SETFOCUS, sent|wparam, 0 },
1619 { WM_CTLCOLORBTN, sent|defwinproc },
1622 static const struct message WmKillFocusButtonSeq[] =
1624 { HCBT_SETFOCUS, hook },
1625 { WM_KILLFOCUS, sent|wparam, 0 },
1626 { WM_CTLCOLORBTN, sent|defwinproc },
1627 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1630 static const struct message WmSetFocusStaticSeq[] =
1632 { HCBT_SETFOCUS, hook },
1633 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1634 { WM_SETFOCUS, sent|wparam, 0 },
1635 { WM_CTLCOLORSTATIC, sent|defwinproc },
1638 static const struct message WmKillFocusStaticSeq[] =
1640 { HCBT_SETFOCUS, hook },
1641 { WM_KILLFOCUS, sent|wparam, 0 },
1642 { WM_CTLCOLORSTATIC, sent|defwinproc },
1643 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1647 static WNDPROC old_button_proc;
1649 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1651 static long defwndproc_counter = 0;
1655 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1657 msg.message = message;
1658 msg.flags = sent|wparam|lparam;
1659 if (defwndproc_counter) msg.flags |= defwinproc;
1660 msg.wParam = wParam;
1661 msg.lParam = lParam;
1664 defwndproc_counter++;
1665 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
1666 defwndproc_counter--;
1671 static void subclass_button(void)
1675 if (!GetClassInfoA(0, "button", &cls)) assert(0);
1677 old_button_proc = cls.lpfnWndProc;
1679 cls.hInstance = GetModuleHandle(0);
1680 cls.lpfnWndProc = button_hook_proc;
1681 cls.lpszClassName = "my_button_class";
1682 if (!RegisterClassA(&cls)) assert(0);
1685 static void test_button_messages(void)
1690 const struct message *setfocus;
1691 const struct message *killfocus;
1693 { BS_PUSHBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq },
1694 { BS_DEFPUSHBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq },
1695 { BS_CHECKBOX, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1696 { BS_AUTOCHECKBOX, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1697 { BS_RADIOBUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1698 { BS_3STATE, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1699 { BS_AUTO3STATE, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1700 { BS_GROUPBOX, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1701 { BS_USERBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq },
1702 { BS_AUTORADIOBUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1703 { BS_OWNERDRAW, WmSetFocusButtonSeq, WmKillFocusButtonSeq }
1710 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
1712 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
1713 0, 0, 50, 14, 0, 0, 0, NULL);
1714 ok(hwnd != 0, "Failed to create button window\n");
1716 ShowWindow(hwnd, SW_SHOW);
1721 trace("button style %08lx\n", button[i].style);
1723 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button");
1726 ok_sequence(button[i].killfocus, "SetFocus(0) on a button");
1728 DestroyWindow(hwnd);
1731 /************* end of button message test ********************/
1733 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1735 static long defwndproc_counter = 0;
1739 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1741 msg.message = message;
1742 msg.flags = sent|wparam|lparam;
1743 if (defwndproc_counter) msg.flags |= defwinproc;
1744 msg.wParam = wParam;
1745 msg.lParam = lParam;
1748 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
1750 HWND parent = GetParent(hwnd);
1752 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
1754 GetClientRect(parent, &rc);
1755 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
1757 trace("ptReserved = (%ld,%ld)\n"
1758 "ptMaxSize = (%ld,%ld)\n"
1759 "ptMaxPosition = (%ld,%ld)\n"
1760 "ptMinTrackSize = (%ld,%ld)\n"
1761 "ptMaxTrackSize = (%ld,%ld)\n",
1762 minmax->ptReserved.x, minmax->ptReserved.y,
1763 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
1764 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
1765 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
1766 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
1768 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
1769 minmax->ptMaxSize.x, rc.right);
1770 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
1771 minmax->ptMaxSize.y, rc.bottom);
1774 defwndproc_counter++;
1775 ret = DefWindowProcA(hwnd, message, wParam, lParam);
1776 defwndproc_counter--;
1781 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1783 static long defwndproc_counter = 0;
1787 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1789 msg.message = message;
1790 msg.flags = sent|wparam|lparam;
1791 if (defwndproc_counter) msg.flags |= defwinproc;
1792 msg.wParam = wParam;
1793 msg.lParam = lParam;
1796 if (message == WM_CREATE)
1798 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
1799 SetWindowLongA(hwnd, GWL_STYLE, style);
1802 defwndproc_counter++;
1803 ret = DefWindowProcA(hwnd, message, wParam, lParam);
1804 defwndproc_counter--;
1809 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1811 static long defwndproc_counter = 0;
1815 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1817 if (message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
1818 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
1819 message == WM_ENABLE || message == WM_ENTERIDLE ||
1820 message == WM_IME_SETCONTEXT)
1822 msg.message = message;
1823 msg.flags = sent|parent|wparam|lparam;
1824 if (defwndproc_counter) msg.flags |= defwinproc;
1825 msg.wParam = wParam;
1826 msg.lParam = lParam;
1830 defwndproc_counter++;
1831 ret = DefWindowProcA(hwnd, message, wParam, lParam);
1832 defwndproc_counter--;
1837 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1839 static long defwndproc_counter = 0;
1843 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1845 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
1846 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
1847 if (after_end_dialog)
1848 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
1850 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
1852 msg.message = message;
1853 msg.flags = sent|wparam|lparam;
1854 if (defwndproc_counter) msg.flags |= defwinproc;
1855 msg.wParam = wParam;
1856 msg.lParam = lParam;
1859 defwndproc_counter++;
1860 ret = DefDlgProcA(hwnd, message, wParam, lParam);
1861 defwndproc_counter--;
1866 static BOOL RegisterWindowClasses(void)
1871 cls.lpfnWndProc = MsgCheckProcA;
1874 cls.hInstance = GetModuleHandleA(0);
1876 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1877 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1878 cls.lpszMenuName = NULL;
1879 cls.lpszClassName = "TestWindowClass";
1880 if(!RegisterClassA(&cls)) return FALSE;
1882 cls.lpfnWndProc = PopupMsgCheckProcA;
1883 cls.lpszClassName = "TestPopupClass";
1884 if(!RegisterClassA(&cls)) return FALSE;
1886 cls.lpfnWndProc = ParentMsgCheckProcA;
1887 cls.lpszClassName = "TestParentClass";
1888 if(!RegisterClassA(&cls)) return FALSE;
1890 cls.lpfnWndProc = DefWindowProcA;
1891 cls.lpszClassName = "SimpleWindowClass";
1892 if(!RegisterClassA(&cls)) return FALSE;
1894 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
1895 cls.lpfnWndProc = TestDlgProcA;
1896 cls.lpszClassName = "TestDialogClass";
1897 if(!RegisterClassA(&cls)) return FALSE;
1902 static HHOOK hCBT_hook;
1904 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
1908 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
1910 /* Log also SetFocus(0) calls */
1911 if (!wParam) wParam = lParam;
1913 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
1915 if (!strcmp(buf, "TestWindowClass") ||
1916 !strcmp(buf, "TestParentClass") ||
1917 !strcmp(buf, "TestPopupClass") ||
1918 !strcmp(buf, "SimpleWindowClass") ||
1919 !strcmp(buf, "TestDialogClass") ||
1920 !strcmp(buf, "MDI_frame_class") ||
1921 !strcmp(buf, "MDI_client_class") ||
1922 !strcmp(buf, "MDI_child_class") ||
1923 !strcmp(buf, "my_button_class") ||
1924 !strcmp(buf, "#32770"))
1928 msg.message = nCode;
1930 msg.wParam = wParam;
1931 msg.lParam = lParam;
1935 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
1940 if (!RegisterWindowClasses()) assert(0);
1942 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
1946 test_mdi_messages();
1947 test_button_messages();
1949 UnhookWindowsHookEx(hCBT_hook);