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
27 #define _WIN32_WINNT 0x0500 /* For WM_CHANGEUISTATE */
34 #include "wine/test.h"
36 #define MDI_FIRST_CHILD_ID 2004
39 FIXME: add tests for these
40 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
41 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
42 WS_THICKFRAME: thick border
43 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
44 WS_BORDER (default for overlapped windows): single black border
45 none (default for child (and popup?) windows): no border
61 UINT message; /* the WM_* code */
62 msg_flags_t flags; /* message props */
63 WPARAM wParam; /* expected value of wParam */
64 LPARAM lParam; /* expected value of lParam */
67 /* Empty message sequence */
68 static const struct message WmEmptySeq[] =
72 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
73 static const struct message WmCreateOverlappedSeq[] = {
74 { HCBT_CREATEWND, hook },
75 { WM_GETMINMAXINFO, sent },
76 { WM_NCCREATE, sent },
77 { WM_NCCALCSIZE, sent|wparam, 0 },
81 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
82 * for a not visible overlapped window.
84 static const struct message WmSWP_ShowOverlappedSeq[] = {
85 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
86 { WM_NCPAINT, sent|wparam|optional, 1 },
87 { WM_GETTEXT, sent|defwinproc|optional },
88 { WM_ERASEBKGND, sent|optional },
89 { HCBT_ACTIVATE, hook },
90 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
91 { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, /* Win9x: SWP_NOSENDCHANGING */
92 { WM_ACTIVATEAPP, sent|wparam, 1 },
93 { WM_NCACTIVATE, sent|wparam, 1 },
94 { WM_GETTEXT, sent|defwinproc|optional },
95 { WM_ACTIVATE, sent|wparam, 1 },
96 { HCBT_SETFOCUS, hook },
97 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
98 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
99 { WM_NCPAINT, sent|wparam|optional, 1 },
100 { WM_GETTEXT, sent|defwinproc|optional },
101 { WM_ERASEBKGND, sent|optional },
102 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
103 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
104 { WM_NCPAINT, sent|wparam|optional, 1 },
105 { WM_ERASEBKGND, sent|optional },
108 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
109 * for a visible overlapped window.
111 static const struct message WmSWP_HideOverlappedSeq[] = {
112 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
113 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
116 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
117 static const struct message WmShowOverlappedSeq[] = {
118 { WM_SHOWWINDOW, sent|wparam, 1 },
119 { WM_NCPAINT, sent|wparam|optional, 1 },
120 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
121 { WM_NCPAINT, sent|wparam|optional, 1 },
122 { WM_GETTEXT, sent|defwinproc|optional },
123 { WM_ERASEBKGND, sent|optional },
124 { HCBT_ACTIVATE, hook },
125 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
126 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
127 { WM_ACTIVATEAPP, sent|wparam, 1 },
128 { WM_NCACTIVATE, sent|wparam, 1 },
129 { WM_GETTEXT, sent|defwinproc|optional },
130 { WM_ACTIVATE, sent|wparam, 1 },
131 { HCBT_SETFOCUS, hook },
132 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
133 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
134 { WM_NCPAINT, sent|wparam|optional, 1 },
135 { WM_GETTEXT, sent|defwinproc|optional },
136 { WM_ERASEBKGND, sent|optional },
137 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
138 { WM_NCCALCSIZE, sent|optional },
139 { WM_NCPAINT, sent|optional },
140 { WM_ERASEBKGND, sent|optional },
141 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
142 * messages. Does that mean that CreateWindow doesn't set initial
143 * window dimensions for overlapped windows?
150 /* ShowWindow(SW_HIDE) for a visible overlapped window */
151 static const struct message WmHideOverlappedSeq[] = {
152 { WM_SHOWWINDOW, sent|wparam, 0 },
153 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
154 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
157 { WM_NCACTIVATE, sent|wparam, 0 },
158 { WM_ACTIVATE, sent|wparam, 0 },
159 { WM_ACTIVATEAPP, sent|wparam, 0 },
160 { WM_KILLFOCUS, sent|wparam, 0 },
161 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
164 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
165 static const struct message WmHideInvisibleOverlappedSeq[] = {
168 /* DestroyWindow for a visible overlapped window */
169 static const struct message WmDestroyOverlappedSeq[] = {
170 { HCBT_DESTROYWND, hook },
171 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
172 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
173 { WM_NCACTIVATE, sent|wparam, 0 },
174 { WM_ACTIVATE, sent|wparam, 0 },
175 { WM_ACTIVATEAPP, sent|wparam, 0 },
176 { WM_KILLFOCUS, sent|wparam, 0 },
177 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
178 { WM_DESTROY, sent },
179 { WM_NCDESTROY, sent },
182 /* CreateWindow (for a child popup window, not initially visible) */
183 static const struct message WmCreateChildPopupSeq[] = {
184 { HCBT_CREATEWND, hook },
185 { WM_NCCREATE, sent },
186 { WM_NCCALCSIZE, sent|wparam, 0 },
192 /* CreateWindow (for a popup window, not initially visible,
193 * which sets WS_VISIBLE in WM_CREATE handler)
195 static const struct message WmCreateInvisiblePopupSeq[] = {
196 { HCBT_CREATEWND, hook },
197 { WM_NCCREATE, sent },
198 { WM_NCCALCSIZE, sent|wparam, 0 },
200 { WM_STYLECHANGING, sent },
201 { WM_STYLECHANGED, sent },
206 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
207 * for a popup window with WS_VISIBLE style set
209 static const struct message WmShowVisiblePopupSeq_2[] = {
210 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
213 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
214 * for a popup window with WS_VISIBLE style set
216 static const struct message WmShowVisiblePopupSeq_3[] = {
217 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
218 { HCBT_ACTIVATE, hook },
219 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
220 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
221 { WM_NCACTIVATE, sent|wparam, 1 },
222 { WM_ACTIVATE, sent|wparam, 1 },
223 { HCBT_SETFOCUS, hook },
224 { WM_KILLFOCUS, sent|parent },
225 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
226 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
227 { WM_SETFOCUS, sent|defwinproc },
230 /* CreateWindow (for child window, not initially visible) */
231 static const struct message WmCreateChildSeq[] = {
232 { HCBT_CREATEWND, hook },
233 { WM_NCCREATE, sent },
234 /* child is inserted into parent's child list after WM_NCCREATE returns */
235 { WM_NCCALCSIZE, sent|wparam, 0 },
239 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
242 /* CreateWindow (for maximized child window, not initially visible) */
243 static const struct message WmCreateMaximizedChildSeq[] = {
244 { HCBT_CREATEWND, hook },
245 { WM_NCCREATE, sent },
246 { WM_NCCALCSIZE, sent|wparam, 0 },
250 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
251 { WM_GETMINMAXINFO, sent },
252 { WM_WINDOWPOSCHANGING, sent },
253 { WM_NCCALCSIZE, sent|wparam, 1 },
254 { WM_WINDOWPOSCHANGED, sent },
255 { WM_SIZE, sent|defwinproc },
256 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
259 /* CreateWindow (for a child window, initially visible) */
260 static const struct message WmCreateVisibleChildSeq[] = {
261 { HCBT_CREATEWND, hook },
262 { WM_NCCREATE, sent },
263 /* child is inserted into parent's child list after WM_NCCREATE returns */
264 { WM_NCCALCSIZE, sent|wparam, 0 },
268 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
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 /* ShowWindow(SW_SHOW) for a not visible child window */
276 static const struct message WmShowChildSeq[] = {
277 { WM_SHOWWINDOW, sent|wparam, 1 },
278 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
279 { WM_ERASEBKGND, sent|parent|optional },
280 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
283 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
284 * for a not visible child window
286 static const struct message WmShowChildSeq_2[] = {
287 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
288 { WM_CHILDACTIVATE, sent },
289 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
292 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
293 * for a not visible child window
295 static const struct message WmShowChildSeq_3[] = {
296 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
297 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
300 /* DestroyWindow for a visible child window */
301 static const struct message WmDestroyChildSeq[] = {
302 { HCBT_DESTROYWND, hook },
303 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
304 { WM_SHOWWINDOW, sent|wparam, 0 },
305 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
306 { WM_ERASEBKGND, sent|parent|optional },
307 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
308 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
309 { WM_KILLFOCUS, sent },
310 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
311 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
312 { WM_SETFOCUS, sent|parent },
313 { WM_DESTROY, sent },
314 { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
315 { WM_NCDESTROY, sent },
316 { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
319 /* Moving the mouse in nonclient area */
320 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
321 { WM_NCHITTEST, sent },
322 { WM_SETCURSOR, sent },
323 { WM_NCMOUSEMOVE, posted },
326 /* Moving the mouse in client area */
327 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
328 { WM_NCHITTEST, sent },
329 { WM_SETCURSOR, sent },
330 { WM_MOUSEMOVE, posted },
333 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
334 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
335 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
336 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
337 { WM_GETMINMAXINFO, sent|defwinproc },
338 { WM_ENTERSIZEMOVE, sent|defwinproc },
339 { WM_WINDOWPOSCHANGING, sent|defwinproc },
340 { WM_WINDOWPOSCHANGED, sent|defwinproc },
341 { WM_MOVE, sent|defwinproc },
342 { WM_EXITSIZEMOVE, sent|defwinproc },
345 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
346 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
347 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
348 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
349 { WM_GETMINMAXINFO, sent|defwinproc },
350 { WM_ENTERSIZEMOVE, sent|defwinproc },
351 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
352 { WM_WINDOWPOSCHANGING, sent|defwinproc },
353 { WM_GETMINMAXINFO, sent|defwinproc },
354 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
355 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
356 { WM_GETTEXT, sent|defwinproc },
357 { WM_ERASEBKGND, sent|defwinproc },
358 { WM_WINDOWPOSCHANGED, sent|defwinproc },
359 { WM_MOVE, sent|defwinproc },
360 { WM_SIZE, sent|defwinproc },
361 { WM_EXITSIZEMOVE, sent|defwinproc },
364 /* Resizing child window with MoveWindow (32) */
365 static const struct message WmResizingChildWithMoveWindowSeq[] = {
366 { WM_WINDOWPOSCHANGING, sent },
367 { WM_NCCALCSIZE, sent|wparam, 1 },
368 { WM_ERASEBKGND, sent|optional },
369 { WM_WINDOWPOSCHANGED, sent },
370 { WM_MOVE, sent|defwinproc },
371 { WM_SIZE, sent|defwinproc },
374 /* Clicking on inactive button */
375 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
376 { WM_NCHITTEST, sent },
377 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
378 { WM_MOUSEACTIVATE, sent },
379 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
380 { WM_SETCURSOR, sent },
381 { WM_SETCURSOR, sent|parent|defwinproc },
382 { WM_LBUTTONDOWN, posted },
383 { WM_KILLFOCUS, posted|parent },
384 { WM_SETFOCUS, posted },
385 { WM_CTLCOLORBTN, posted|parent },
386 { BM_SETSTATE, posted },
387 { WM_CTLCOLORBTN, posted|parent },
388 { WM_LBUTTONUP, posted },
389 { BM_SETSTATE, posted },
390 { WM_CTLCOLORBTN, posted|parent },
391 { WM_COMMAND, posted|parent },
394 /* Reparenting a button (16/32) */
395 /* The last child (button) reparented gets topmost for its new parent. */
396 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
397 { WM_SHOWWINDOW, sent|wparam, 0 },
398 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
399 { WM_ERASEBKGND, sent|parent },
400 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
401 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
402 { WM_CHILDACTIVATE, sent },
403 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
404 { WM_MOVE, sent|defwinproc },
405 { WM_SHOWWINDOW, sent|wparam, 1 },
408 /* Creation of a custom dialog (32) */
409 static const struct message WmCreateCustomDialogSeq[] = {
410 { HCBT_CREATEWND, hook },
411 { WM_GETMINMAXINFO, sent },
412 { WM_NCCREATE, sent },
413 { WM_NCCALCSIZE, sent|wparam, 0 },
415 { WM_SHOWWINDOW, sent|wparam, 1 },
416 { HCBT_ACTIVATE, hook },
417 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
418 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
419 { WM_NCACTIVATE, sent|wparam, 1 },
420 { WM_GETTEXT, sent|optional|defwinproc },
421 { WM_GETICON, sent|optional|defwinproc },
422 { WM_GETICON, sent|optional|defwinproc },
423 { WM_GETICON, sent|optional|defwinproc },
424 { WM_GETTEXT, sent|optional|defwinproc },
425 { WM_ACTIVATE, sent|wparam, 1 },
426 { WM_KILLFOCUS, sent|parent },
427 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
428 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
429 { WM_SETFOCUS, sent },
430 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
431 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
432 { WM_NCPAINT, sent|wparam, 1 },
433 { WM_GETTEXT, sent|optional|defwinproc },
434 { WM_GETICON, sent|optional|defwinproc },
435 { WM_GETICON, sent|optional|defwinproc },
436 { WM_GETICON, sent|optional|defwinproc },
437 { WM_GETTEXT, sent|optional|defwinproc },
438 { WM_ERASEBKGND, sent },
439 { WM_CTLCOLORDLG, sent|defwinproc },
440 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
441 { WM_GETTEXT, sent|optional },
442 { WM_GETICON, sent|optional },
443 { WM_GETICON, sent|optional },
444 { WM_GETICON, sent|optional },
445 { WM_GETTEXT, sent|optional },
446 { WM_NCCALCSIZE, sent|optional },
447 { WM_NCPAINT, sent|optional },
448 { WM_GETTEXT, sent|optional|defwinproc },
449 { WM_GETICON, sent|optional|defwinproc },
450 { WM_GETICON, sent|optional|defwinproc },
451 { WM_GETICON, sent|optional|defwinproc },
452 { WM_GETTEXT, sent|optional|defwinproc },
453 { WM_ERASEBKGND, sent|optional },
454 { WM_CTLCOLORDLG, sent|optional|defwinproc },
459 /* Calling EndDialog for a custom dialog (32) */
460 static const struct message WmEndCustomDialogSeq[] = {
461 { WM_WINDOWPOSCHANGING, sent },
462 { WM_WINDOWPOSCHANGED, sent },
463 { WM_GETTEXT, sent|optional },
464 { WM_GETICON, sent|optional },
465 { WM_GETICON, sent|optional },
466 { WM_GETICON, sent|optional },
467 { HCBT_ACTIVATE, hook },
468 { WM_NCACTIVATE, sent|wparam, 0 },
469 { WM_GETTEXT, sent|optional|defwinproc },
470 { WM_GETICON, sent|optional|defwinproc },
471 { WM_GETICON, sent|optional|defwinproc },
472 { WM_GETICON, sent|optional|defwinproc },
473 { WM_GETTEXT, sent|optional|defwinproc },
474 { WM_ACTIVATE, sent|wparam, 0 },
475 { WM_WINDOWPOSCHANGING, sent|optional },
476 { HCBT_SETFOCUS, hook },
477 { WM_KILLFOCUS, sent },
478 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
479 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
480 { WM_SETFOCUS, sent|parent|defwinproc },
483 /* Creation and destruction of a modal dialog (32) */
484 static const struct message WmModalDialogSeq[] = {
485 { WM_CANCELMODE, sent|parent },
486 { HCBT_SETFOCUS, hook },
487 { WM_KILLFOCUS, sent|parent },
488 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
489 { WM_ENABLE, sent|parent|wparam, 0 },
490 { HCBT_CREATEWND, hook },
491 { WM_SETFONT, sent },
492 { WM_INITDIALOG, sent },
493 { WM_CHANGEUISTATE, sent|optional },
494 { WM_SHOWWINDOW, sent },
495 { HCBT_ACTIVATE, hook },
496 { WM_WINDOWPOSCHANGING, sent },
497 { WM_NCACTIVATE, sent|wparam, 1 },
498 { WM_GETICON, sent|optional },
499 { WM_GETICON, sent|optional },
500 { WM_GETICON, sent|optional },
501 { WM_GETTEXT, sent|optional },
502 { WM_ACTIVATE, sent|wparam, 1 },
503 { WM_WINDOWPOSCHANGING, sent },
504 { WM_NCPAINT, sent },
505 { WM_GETICON, sent|optional },
506 { WM_GETICON, sent|optional },
507 { WM_GETICON, sent|optional },
508 { WM_GETTEXT, sent|optional },
509 { WM_ERASEBKGND, sent },
510 { WM_CTLCOLORDLG, sent },
511 { WM_WINDOWPOSCHANGED, sent },
512 { WM_GETICON, sent|optional },
513 { WM_GETICON, sent|optional },
514 { WM_GETICON, sent|optional },
515 { WM_GETTEXT, sent|optional },
516 { WM_NCCALCSIZE, sent|optional },
517 { WM_NCPAINT, sent|optional },
518 { WM_GETICON, sent|optional },
519 { WM_GETICON, sent|optional },
520 { WM_GETICON, sent|optional },
521 { WM_GETTEXT, sent|optional },
522 { WM_ERASEBKGND, sent|optional },
523 { WM_CTLCOLORDLG, sent|optional },
524 { WM_PAINT, sent|optional },
525 { WM_CTLCOLORBTN, sent },
526 { WM_ENTERIDLE, sent|parent },
528 { WM_ENABLE, sent|parent|wparam, 1 },
529 { WM_WINDOWPOSCHANGING, sent },
530 { WM_WINDOWPOSCHANGED, sent },
531 { WM_GETICON, sent|optional },
532 { WM_GETICON, sent|optional },
533 { WM_GETICON, sent|optional },
534 { WM_GETTEXT, sent|optional },
535 { HCBT_ACTIVATE, hook },
536 { WM_NCACTIVATE, sent|wparam, 0 },
537 { WM_GETICON, sent|optional },
538 { WM_GETICON, sent|optional },
539 { WM_GETICON, sent|optional },
540 { WM_GETTEXT, sent|optional },
541 { WM_ACTIVATE, sent|wparam, 0 },
542 { WM_WINDOWPOSCHANGING, sent|optional },
543 { HCBT_SETFOCUS, hook },
544 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
545 { WM_SETFOCUS, sent|parent|defwinproc },
546 { HCBT_DESTROYWND, hook },
547 { WM_DESTROY, sent },
548 { WM_NCDESTROY, sent },
551 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
552 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
553 /* (inside dialog proc, handling WM_INITDIALOG) */
554 { WM_WINDOWPOSCHANGING, sent },
555 { WM_NCCALCSIZE, sent },
556 { WM_NCACTIVATE, sent|parent|wparam, 0 },
557 { WM_GETTEXT, sent|defwinproc },
558 { WM_ACTIVATE, sent|parent|wparam, 0 },
559 { WM_WINDOWPOSCHANGING, sent },
560 { WM_WINDOWPOSCHANGING, sent|parent },
561 { WM_NCACTIVATE, sent|wparam, 1 },
562 { WM_ACTIVATE, sent|wparam, 1 },
563 { WM_WINDOWPOSCHANGED, sent },
564 { WM_SIZE, sent|defwinproc },
565 /* (setting focus) */
566 { WM_SHOWWINDOW, sent|wparam, 1 },
567 { WM_WINDOWPOSCHANGING, sent },
568 { WM_NCPAINT, sent },
569 { WM_GETTEXT, sent|defwinproc },
570 { WM_ERASEBKGND, sent },
571 { WM_CTLCOLORDLG, sent|defwinproc },
572 { WM_WINDOWPOSCHANGED, sent },
574 /* (bunch of WM_CTLCOLOR* for each control) */
575 { WM_PAINT, sent|parent },
576 { WM_ENTERIDLE, sent|parent|wparam, 0 },
577 { WM_SETCURSOR, sent|parent },
580 /* SetMenu for NonVisible windows with size change*/
581 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
582 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
583 { WM_NCCALCSIZE, sent|wparam, 1 },
584 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
585 { WM_MOVE, sent|defwinproc },
586 { WM_SIZE, sent|defwinproc },
587 { WM_GETICON, sent|optional },
588 { WM_GETICON, sent|optional },
589 { WM_GETICON, sent|optional },
590 { WM_GETTEXT, sent|optional },
591 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
594 /* SetMenu for NonVisible windows with no size change */
595 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
596 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
597 { WM_NCCALCSIZE, sent|wparam, 1 },
598 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
601 /* SetMenu for Visible windows with size change */
602 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
603 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
604 { WM_NCCALCSIZE, sent|wparam, 1 },
605 { WM_NCPAINT, sent|wparam, 1 },
606 { WM_GETTEXT, sent|defwinproc|optional },
607 { WM_ERASEBKGND, sent|optional },
608 { WM_ACTIVATE, sent|optional },
609 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
610 { WM_MOVE, sent|defwinproc },
611 { WM_SIZE, sent|defwinproc },
612 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
613 { WM_NCPAINT, sent|wparam|optional, 1 },
614 { WM_ERASEBKGND, sent|optional },
617 /* SetMenu for Visible windows with no size change */
618 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
619 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
620 { WM_NCCALCSIZE, sent|wparam, 1 },
621 { WM_NCPAINT, sent|wparam, 1 },
622 { WM_GETTEXT, sent|defwinproc|optional },
623 { WM_ERASEBKGND, sent|optional },
624 { WM_ACTIVATE, sent|optional },
625 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
628 /* DrawMenuBar for a visible window */
629 static const struct message WmDrawMenuBarSeq[] =
631 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
632 { WM_NCCALCSIZE, sent|wparam, 1 },
633 { WM_NCPAINT, sent|wparam, 1 },
634 { WM_GETTEXT, sent|defwinproc|optional },
635 { WM_ERASEBKGND, sent|optional },
636 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
640 static const struct message WmSetRedrawFalseSeq[] =
642 { WM_SETREDRAW, sent|wparam, 0 },
646 static const struct message WmSetRedrawTrueSeq[] =
648 { WM_SETREDRAW, sent|wparam, 1 },
652 static const struct message WmEnableWindowSeq[] =
654 { WM_CANCELMODE, sent },
659 static const struct message WmGetScrollRangeSeq[] =
661 { SBM_GETRANGE, sent },
664 static const struct message WmGetScrollInfoSeq[] =
666 { SBM_GETSCROLLINFO, sent },
669 static const struct message WmSetScrollRangeSeq[] =
671 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
672 sends SBM_SETSCROLLINFO.
674 { SBM_SETSCROLLINFO, sent },
677 /* SetScrollRange for a window without a non-client area */
678 static const struct message WmSetScrollRangeHVSeq[] =
680 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
681 { WM_NCCALCSIZE, sent|wparam, 1 },
682 { WM_GETTEXT, sent|defwinproc|optional },
683 { WM_ERASEBKGND, sent|optional },
684 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
687 /* SetScrollRange for a window with a non-client area */
688 static const struct message WmSetScrollRangeHV_NC_Seq[] =
690 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
691 { WM_NCCALCSIZE, sent|wparam, 1 },
692 { WM_NCPAINT, sent|optional },
693 { WM_GETTEXT, sent|defwinproc|optional },
694 { WM_ERASEBKGND, sent|optional },
695 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
696 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
697 { WM_SIZE, sent|defwinproc },
701 static int after_end_dialog;
702 static int sequence_cnt, sequence_size;
703 static struct message* sequence;
705 static void add_message(const struct message *msg)
710 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
712 if (sequence_cnt == sequence_size)
715 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
719 sequence[sequence_cnt].message = msg->message;
720 sequence[sequence_cnt].flags = msg->flags;
721 sequence[sequence_cnt].wParam = msg->wParam;
722 sequence[sequence_cnt].lParam = msg->lParam;
727 static void flush_sequence()
729 HeapFree(GetProcessHeap(), 0, sequence);
731 sequence_cnt = sequence_size = 0;
734 static void ok_sequence(const struct message *expected, const char *context, int todo)
736 static const struct message end_of_sequence = { 0, 0, 0, 0 };
737 const struct message *actual;
739 add_message(&end_of_sequence);
743 while (expected->message && actual->message)
745 trace("expected %04x - actual %04x\n", expected->message, actual->message);
747 if (expected->message == actual->message)
749 if (expected->flags & wparam)
750 ok (expected->wParam == actual->wParam,
751 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
752 context, expected->message, expected->wParam, actual->wParam);
753 if (expected->flags & lparam)
754 ok (expected->lParam == actual->lParam,
755 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
756 context, expected->message, expected->lParam, actual->lParam);
757 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
758 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
759 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
760 ok ((expected->flags & beginpaint) == (actual->flags & beginpaint),
761 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
762 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
763 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
764 "%s: the msg 0x%04x should have been %s\n",
765 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
766 ok ((expected->flags & parent) == (actual->flags & parent),
767 "%s: the msg 0x%04x was expected in %s\n",
768 context, expected->message, (expected->flags & parent) ? "parent" : "child");
769 ok ((expected->flags & hook) == (actual->flags & hook),
770 "%s: the msg 0x%04x should have been sent by a hook\n",
771 context, expected->message);
775 else if (expected->flags & optional)
780 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
781 context, expected->message, actual->message);
788 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
789 context, expected->message, actual->message);
795 /* skip all optional trailing messages */
796 while (expected->message && (expected->flags & optional))
802 if (expected->message || actual->message)
803 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
804 context, expected->message, actual->message);
809 if (expected->message || actual->message)
810 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
811 context, expected->message, actual->message);
817 /******************************** MDI test **********************************/
819 /* CreateWindow for MDI frame window, initially visible */
820 static const struct message WmCreateMDIframeSeq[] = {
821 { HCBT_CREATEWND, hook },
822 { WM_GETMINMAXINFO, sent },
823 { WM_NCCREATE, sent },
824 { WM_NCCALCSIZE, sent|wparam, 0 },
826 { WM_SHOWWINDOW, sent|wparam, 1 },
827 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
828 { HCBT_ACTIVATE, hook },
829 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
830 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
831 { WM_WINDOWPOSCHANGED, sent|wparam|optional, 0 }, /* Win9x */
832 { WM_ACTIVATEAPP, sent|wparam, 1 },
833 { WM_NCACTIVATE, sent|wparam, 1 },
834 { WM_ACTIVATE, sent|wparam, 1 },
835 { HCBT_SETFOCUS, hook },
836 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
837 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
838 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
843 /* DestroyWindow for MDI frame window, initially visible */
844 static const struct message WmDestroyMDIframeSeq[] = {
845 { HCBT_DESTROYWND, hook },
846 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
847 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
848 { WM_NCACTIVATE, sent|wparam, 0 },
849 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
850 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
851 { WM_DESTROY, sent },
852 { WM_NCDESTROY, sent },
855 /* CreateWindow for MDI client window, initially visible */
856 static const struct message WmCreateMDIclientSeq[] = {
857 { HCBT_CREATEWND, hook },
858 { WM_NCCREATE, sent },
859 { WM_NCCALCSIZE, sent|wparam, 0 },
863 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
864 { WM_SHOWWINDOW, sent|wparam, 1 },
865 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
866 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
869 /* DestroyWindow for MDI client window, initially visible */
870 static const struct message WmDestroyMDIclientSeq[] = {
871 { HCBT_DESTROYWND, hook },
872 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
873 { WM_SHOWWINDOW, sent|wparam, 0 },
874 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
875 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
876 { WM_DESTROY, sent },
877 { WM_NCDESTROY, sent },
880 /* CreateWindow for MDI child window, initially visible */
881 static const struct message WmCreateMDIchildVisibleSeq[] = {
882 { HCBT_CREATEWND, hook },
883 { WM_NCCREATE, sent },
884 { WM_NCCALCSIZE, sent|wparam, 0 },
888 /* Win2k sends wparam set to
889 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
890 * while Win9x doesn't bother to set child window id according to
891 * CLIENTCREATESTRUCT.idFirstChild
893 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
894 { WM_SHOWWINDOW, sent|wparam, 1 },
895 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
896 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
897 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
898 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE*/
899 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
900 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 }, /*SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/
902 /* Win9x: message sequence terminates here. */
904 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
905 { HCBT_SETFOCUS, hook }, /* in MDI client */
906 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
907 { WM_SETFOCUS, sent }, /* in MDI client */
908 { HCBT_SETFOCUS, hook },
909 { WM_KILLFOCUS, sent }, /* in MDI client */
910 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
911 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
912 { WM_SETFOCUS, sent|defwinproc },
913 { WM_MDIACTIVATE, sent|defwinproc },
916 /* DestroyWindow for MDI child window, initially visible */
917 static const struct message WmDestroyMDIchildVisibleSeq[] = {
918 { HCBT_DESTROYWND, hook },
919 /* Win2k sends wparam set to
920 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
921 * while Win9x doesn't bother to set child window id according to
922 * CLIENTCREATESTRUCT.idFirstChild
924 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
925 { WM_SHOWWINDOW, sent|wparam, 0 },
926 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
927 { WM_ERASEBKGND, sent|parent|optional },
928 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
930 /* { WM_DESTROY, sent }
931 * Win9x: message sequence terminates here.
934 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
935 { WM_KILLFOCUS, sent },
936 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
937 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
938 { WM_SETFOCUS, sent }, /* in MDI client */
940 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
941 { WM_KILLFOCUS, sent }, /* in MDI client */
942 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
943 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
944 { WM_SETFOCUS, sent }, /* in MDI client */
946 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
947 { WM_KILLFOCUS, sent },
948 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
949 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
950 { WM_SETFOCUS, sent }, /* in MDI client */
952 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
953 { WM_KILLFOCUS, sent }, /* in MDI client */
954 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
955 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
956 { WM_SETFOCUS, sent }, /* in MDI client */
958 { WM_DESTROY, sent },
960 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
961 { WM_KILLFOCUS, sent },
962 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
963 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
964 { WM_SETFOCUS, sent }, /* in MDI client */
966 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
967 { WM_KILLFOCUS, sent }, /* in MDI client */
968 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
969 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
970 { WM_SETFOCUS, sent }, /* in MDI client */
972 { WM_NCDESTROY, sent },
975 /* CreateWindow for MDI child window, initially invisible */
976 static const struct message WmCreateMDIchildInvisibleSeq[] = {
977 { HCBT_CREATEWND, hook },
978 { WM_NCCREATE, sent },
979 { WM_NCCALCSIZE, sent|wparam, 0 },
983 /* Win2k sends wparam set to
984 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
985 * while Win9x doesn't bother to set child window id according to
986 * CLIENTCREATESTRUCT.idFirstChild
988 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
991 /* DestroyWindow for MDI child window, initially invisible */
992 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
993 { HCBT_DESTROYWND, hook },
994 /* Win2k sends wparam set to
995 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
996 * while Win9x doesn't bother to set child window id according to
997 * CLIENTCREATESTRUCT.idFirstChild
999 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1000 { WM_DESTROY, sent },
1001 { WM_NCDESTROY, sent },
1005 static HWND mdi_client;
1006 static WNDPROC old_mdi_client_proc;
1008 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1012 /* do not log painting messages */
1013 if (message != WM_PAINT &&
1014 message != WM_ERASEBKGND &&
1015 message != WM_NCPAINT &&
1016 message != WM_GETTEXT)
1018 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1020 msg.message = message;
1021 msg.flags = sent|wparam|lparam;
1022 msg.wParam = wParam;
1023 msg.lParam = lParam;
1027 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1030 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1032 static long defwndproc_counter = 0;
1036 /* do not log painting messages */
1037 if (message != WM_PAINT &&
1038 message != WM_ERASEBKGND &&
1039 message != WM_NCPAINT &&
1040 message != WM_GETTEXT)
1042 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1046 case WM_WINDOWPOSCHANGING:
1047 case WM_WINDOWPOSCHANGED:
1049 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1051 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1052 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1053 winpos->hwnd, winpos->hwndInsertAfter,
1054 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1059 msg.message = message;
1060 msg.flags = sent|wparam|lparam;
1061 if (defwndproc_counter) msg.flags |= defwinproc;
1062 msg.wParam = wParam;
1063 msg.lParam = lParam;
1067 defwndproc_counter++;
1068 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1069 defwndproc_counter--;
1074 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1076 static long defwndproc_counter = 0;
1080 /* do not log painting messages */
1081 if (message != WM_PAINT &&
1082 message != WM_ERASEBKGND &&
1083 message != WM_NCPAINT &&
1084 message != WM_GETTEXT)
1086 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1088 msg.message = message;
1089 msg.flags = sent|wparam|lparam;
1090 if (defwndproc_counter) msg.flags |= defwinproc;
1091 msg.wParam = wParam;
1092 msg.lParam = lParam;
1096 defwndproc_counter++;
1097 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
1098 defwndproc_counter--;
1103 static BOOL mdi_RegisterWindowClasses(void)
1108 cls.lpfnWndProc = mdi_frame_wnd_proc;
1111 cls.hInstance = GetModuleHandleA(0);
1113 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1114 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1115 cls.lpszMenuName = NULL;
1116 cls.lpszClassName = "MDI_frame_class";
1117 if (!RegisterClassA(&cls)) return FALSE;
1119 cls.lpfnWndProc = mdi_child_wnd_proc;
1120 cls.lpszClassName = "MDI_child_class";
1121 if (!RegisterClassA(&cls)) return FALSE;
1123 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
1124 old_mdi_client_proc = cls.lpfnWndProc;
1125 cls.hInstance = GetModuleHandleA(0);
1126 cls.lpfnWndProc = mdi_client_hook_proc;
1127 cls.lpszClassName = "MDI_client_class";
1128 if (!RegisterClassA(&cls)) assert(0);
1133 static void test_mdi_messages(void)
1135 CLIENTCREATESTRUCT client_cs;
1136 HWND mdi_frame, mdi_child;
1138 assert(mdi_RegisterWindowClasses());
1142 trace("creating MDI frame window\n");
1143 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1144 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1145 WS_MAXIMIZEBOX | WS_VISIBLE,
1146 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1147 GetDesktopWindow(), 0,
1148 GetModuleHandleA(0), NULL);
1150 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
1152 trace("creating MDI client window\n");
1153 client_cs.hWindowMenu = 0;
1154 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
1155 mdi_client = CreateWindowExA(0, "MDI_client_class",
1157 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
1159 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
1161 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", TRUE);
1163 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
1168 trace("creating visible MDI child window\n");
1169 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1170 WS_CHILD | WS_VISIBLE,
1171 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1172 mdi_client, 0, GetModuleHandleA(0), NULL);
1174 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", TRUE);
1176 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1177 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1179 DestroyWindow(mdi_child);
1180 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
1185 trace("creating invisible MDI child window\n");
1186 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1188 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1189 mdi_client, 0, GetModuleHandleA(0), NULL);
1191 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", TRUE);
1193 ok(!(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
1194 ok(!IsWindowVisible(mdi_child), "MDI child should not be visible\n");
1196 DestroyWindow(mdi_child);
1197 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", TRUE);
1199 DestroyWindow(mdi_client);
1200 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
1202 DestroyWindow(mdi_frame);
1203 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
1205 /************************* End of MDI test **********************************/
1207 static void test_WM_SETREDRAW(HWND hwnd)
1209 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
1213 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
1214 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
1216 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
1217 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
1220 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
1221 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
1223 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1224 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
1226 /* restore original WS_VISIBLE state */
1227 SetWindowLongA(hwnd, GWL_STYLE, style);
1232 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1236 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1238 msg.message = message;
1239 msg.flags = sent|wparam|lparam;
1240 msg.wParam = wParam;
1241 msg.lParam = lParam;
1244 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
1245 if (message == WM_TIMER) EndDialog( hwnd, 0 );
1249 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1251 DWORD style, exstyle;
1254 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1255 style = GetWindowLongA(hwnd, GWL_STYLE);
1256 /* do not be confused by WS_DLGFRAME set */
1257 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1259 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1260 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1262 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1263 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1264 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
1266 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", TRUE);
1268 style = GetWindowLongA(hwnd, GWL_STYLE);
1269 if (set) ok(style & set, "style %08lx should be set\n", set);
1270 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1272 /* a subsequent call should do nothing */
1273 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1274 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
1278 trace("Ignore GetScrollRange error below if you are on Win9x\n");
1279 ok(GetScrollRange(hwnd, ctl, &xmin, &xmax), "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
1280 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
1281 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
1282 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
1285 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1287 DWORD style, exstyle;
1290 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1291 style = GetWindowLongA(hwnd, GWL_STYLE);
1292 /* do not be confused by WS_DLGFRAME set */
1293 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1295 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1296 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1298 si.cbSize = sizeof(si);
1299 si.fMask = SIF_RANGE;
1302 SetScrollInfo(hwnd, ctl, &si, TRUE);
1303 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1304 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
1306 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", TRUE);
1308 style = GetWindowLongA(hwnd, GWL_STYLE);
1309 if (set) ok(style & set, "style %08lx should be set\n", set);
1310 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1312 /* a subsequent call should do nothing */
1313 SetScrollInfo(hwnd, ctl, &si, TRUE);
1314 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
1316 si.fMask = SIF_PAGE;
1318 SetScrollInfo(hwnd, ctl, &si, FALSE);
1319 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
1323 SetScrollInfo(hwnd, ctl, &si, FALSE);
1324 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
1326 si.fMask = SIF_RANGE;
1327 si.nMin = 0xdeadbeef;
1328 si.nMax = 0xdeadbeef;
1329 ok(GetScrollInfo(hwnd, ctl, &si), "GetScrollInfo error %ld\n", GetLastError());
1330 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
1331 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
1332 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
1335 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
1336 static void test_scroll_messages(HWND hwnd)
1343 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1344 if (sequence->message != WmGetScrollRangeSeq[0].message)
1345 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1346 /* values of min and max are undefined */
1349 ok(SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE), "SetScrollRange error %ld\n", GetLastError());
1350 if (sequence->message != WmSetScrollRangeSeq[0].message)
1351 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1356 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1357 if (sequence->message != WmGetScrollRangeSeq[0].message)
1358 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1359 /* values of min and max are undefined */
1362 si.cbSize = sizeof(si);
1363 si.fMask = SIF_RANGE;
1366 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1367 if (sequence->message != WmSetScrollRangeSeq[0].message)
1368 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1371 si.fMask = SIF_PAGE;
1373 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1374 if (sequence->message != WmSetScrollRangeSeq[0].message)
1375 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1380 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1381 if (sequence->message != WmSetScrollRangeSeq[0].message)
1382 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1385 si.fMask = SIF_RANGE;
1386 si.nMin = 0xdeadbeef;
1387 si.nMax = 0xdeadbeef;
1388 ok(GetScrollInfo(hwnd, SB_CTL, &si), "GetScrollInfo error %ld\n", GetLastError());
1389 if (sequence->message != WmGetScrollInfoSeq[0].message)
1390 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1391 /* values of min and max are undefined */
1394 /* set WS_HSCROLL */
1395 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1396 /* clear WS_HSCROLL */
1397 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1399 /* set WS_HSCROLL */
1400 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1401 /* clear WS_HSCROLL */
1402 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1404 /* set WS_VSCROLL */
1405 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1406 /* clear WS_VSCROLL */
1407 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1409 /* set WS_VSCROLL */
1410 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1411 /* clear WS_VSCROLL */
1412 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1415 /* test if we receive the right sequence of messages */
1416 static void test_messages(void)
1418 HWND hwnd, hparent, hchild;
1419 HWND hchild2, hbutton;
1422 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1423 100, 100, 200, 200, 0, 0, 0, NULL);
1424 ok (hwnd != 0, "Failed to create overlapped window\n");
1425 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
1427 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
1428 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
1429 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
1431 /* test WM_SETREDRAW on a not visible top level window */
1432 test_WM_SETREDRAW(hwnd);
1434 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1435 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
1436 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
1438 ok(GetActiveWindow() == hwnd, "window should be active\n");
1439 ok(GetFocus() == hwnd, "window should have input focus\n");
1440 ShowWindow(hwnd, SW_HIDE);
1441 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
1443 ShowWindow(hwnd, SW_SHOW);
1444 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
1446 ok(GetActiveWindow() == hwnd, "window should be active\n");
1447 ok(GetFocus() == hwnd, "window should have input focus\n");
1448 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1449 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
1450 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
1452 /* test WM_SETREDRAW on a visible top level window */
1453 ShowWindow(hwnd, SW_SHOW);
1454 test_WM_SETREDRAW(hwnd);
1456 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
1457 test_scroll_messages(hwnd);
1459 DestroyWindow(hwnd);
1460 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
1462 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1463 100, 100, 200, 200, 0, 0, 0, NULL);
1464 ok (hparent != 0, "Failed to create parent window\n");
1467 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
1468 0, 0, 10, 10, hparent, 0, 0, NULL);
1469 ok (hchild != 0, "Failed to create child window\n");
1470 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE);
1471 DestroyWindow(hchild);
1474 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1475 0, 0, 10, 10, hparent, 0, 0, NULL);
1476 ok (hchild != 0, "Failed to create child window\n");
1477 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
1479 trace("testing scroll APIs on a visible child window %p\n", hchild);
1480 test_scroll_messages(hchild);
1482 DestroyWindow(hchild);
1485 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
1486 0, 0, 10, 10, hparent, 0, 0, NULL);
1487 ok (hchild != 0, "Failed to create child window\n");
1488 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
1490 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
1491 100, 100, 50, 50, hparent, 0, 0, NULL);
1492 ok (hchild2 != 0, "Failed to create child2 window\n");
1495 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
1496 0, 100, 50, 50, hchild, 0, 0, NULL);
1497 ok (hbutton != 0, "Failed to create button window\n");
1499 /* test WM_SETREDRAW on a not visible child window */
1500 test_WM_SETREDRAW(hchild);
1502 ShowWindow(hchild, SW_SHOW);
1503 ok_sequence(WmShowChildSeq, "ShowWindow:child", FALSE);
1505 /* test WM_SETREDRAW on a visible child window */
1506 test_WM_SETREDRAW(hchild);
1508 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
1509 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
1511 ShowWindow(hchild, SW_HIDE);
1513 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1514 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
1516 ShowWindow(hchild, SW_HIDE);
1518 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
1519 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
1521 /* DestroyWindow sequence below expects that a child has focus */
1525 DestroyWindow(hchild);
1526 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
1527 DestroyWindow(hchild2);
1528 DestroyWindow(hbutton);
1531 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
1532 0, 0, 100, 100, hparent, 0, 0, NULL);
1533 ok (hchild != 0, "Failed to create child popup window\n");
1534 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
1535 DestroyWindow(hchild);
1537 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
1539 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
1540 0, 0, 100, 100, hparent, 0, 0, NULL);
1541 ok (hchild != 0, "Failed to create popup window\n");
1542 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
1543 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1544 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1546 ShowWindow(hchild, SW_SHOW);
1547 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
1549 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1550 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
1552 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1553 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
1554 DestroyWindow(hchild);
1556 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
1557 * changes nothing in message sequences.
1560 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
1561 0, 0, 100, 100, hparent, 0, 0, NULL);
1562 ok (hchild != 0, "Failed to create popup window\n");
1563 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
1564 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1565 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1567 ShowWindow(hchild, SW_SHOW);
1568 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
1570 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1571 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
1572 DestroyWindow(hchild);
1575 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
1576 0, 0, 100, 100, hparent, 0, 0, NULL);
1577 ok(hwnd != 0, "Failed to create custom dialog window\n");
1578 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
1580 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
1581 test_scroll_messages(hwnd);
1584 after_end_dialog = 1;
1585 EndDialog( hwnd, 0 );
1586 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
1588 DestroyWindow(hwnd);
1589 after_end_dialog = 0;
1592 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
1593 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
1595 DestroyWindow(hparent);
1598 /* Message sequence for SetMenu */
1599 hmenu = CreateMenu();
1600 ok (hmenu != 0, "Failed to create menu\n");
1601 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
1602 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1603 100, 100, 200, 200, 0, hmenu, 0, NULL);
1604 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
1605 ok (SetMenu(hwnd, 0), "SetMenu\n");
1606 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
1607 ok (SetMenu(hwnd, 0), "SetMenu\n");
1608 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
1609 ShowWindow(hwnd, SW_SHOW);
1611 ok (SetMenu(hwnd, 0), "SetMenu\n");
1612 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
1613 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
1614 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
1616 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
1617 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
1619 DestroyWindow(hwnd);
1622 /* Message sequence for EnableWindow */
1623 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1624 100, 100, 200, 200, 0, 0, 0, NULL);
1625 ok (hparent != 0, "Failed to create parent window\n");
1626 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1627 0, 0, 10, 10, hparent, 0, 0, NULL);
1628 ok (hchild != 0, "Failed to create child window\n");
1633 EnableWindow(hparent, FALSE);
1634 ok_sequence(WmEnableWindowSeq, "EnableWindow", FALSE);
1636 DestroyWindow(hparent);
1640 /****************** button message test *************************/
1641 static const struct message WmSetFocusButtonSeq[] =
1643 { HCBT_SETFOCUS, hook },
1644 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1645 { WM_SETFOCUS, sent|wparam, 0 },
1646 { WM_CTLCOLORBTN, sent|defwinproc },
1649 static const struct message WmKillFocusButtonSeq[] =
1651 { HCBT_SETFOCUS, hook },
1652 { WM_KILLFOCUS, sent|wparam, 0 },
1653 { WM_CTLCOLORBTN, sent|defwinproc },
1654 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1657 static const struct message WmSetFocusStaticSeq[] =
1659 { HCBT_SETFOCUS, hook },
1660 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1661 { WM_SETFOCUS, sent|wparam, 0 },
1662 { WM_CTLCOLORSTATIC, sent|defwinproc },
1665 static const struct message WmKillFocusStaticSeq[] =
1667 { HCBT_SETFOCUS, hook },
1668 { WM_KILLFOCUS, sent|wparam, 0 },
1669 { WM_CTLCOLORSTATIC, sent|defwinproc },
1670 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1673 static const struct message WmLButtonDownSeq[] =
1675 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
1676 { HCBT_SETFOCUS, hook },
1677 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1678 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
1679 { WM_CTLCOLORBTN, sent|defwinproc },
1680 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
1681 { WM_CTLCOLORBTN, sent|defwinproc },
1684 static const struct message WmLButtonUpSeq[] =
1686 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
1687 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
1688 { WM_CTLCOLORBTN, sent|defwinproc },
1689 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
1693 static WNDPROC old_button_proc;
1695 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1697 static long defwndproc_counter = 0;
1701 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1703 msg.message = message;
1704 msg.flags = sent|wparam|lparam;
1705 if (defwndproc_counter) msg.flags |= defwinproc;
1706 msg.wParam = wParam;
1707 msg.lParam = lParam;
1710 if (message == BM_SETSTATE)
1711 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
1713 defwndproc_counter++;
1714 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
1715 defwndproc_counter--;
1720 static void subclass_button(void)
1724 if (!GetClassInfoA(0, "button", &cls)) assert(0);
1726 old_button_proc = cls.lpfnWndProc;
1728 cls.hInstance = GetModuleHandle(0);
1729 cls.lpfnWndProc = button_hook_proc;
1730 cls.lpszClassName = "my_button_class";
1731 if (!RegisterClassA(&cls)) assert(0);
1734 static void test_button_messages(void)
1739 const struct message *setfocus;
1740 const struct message *killfocus;
1742 { BS_PUSHBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq },
1743 { BS_DEFPUSHBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq },
1744 { BS_CHECKBOX, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1745 { BS_AUTOCHECKBOX, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1746 { BS_RADIOBUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1747 { BS_3STATE, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1748 { BS_AUTO3STATE, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1749 { BS_GROUPBOX, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1750 { BS_USERBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq },
1751 { BS_AUTORADIOBUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq },
1752 { BS_OWNERDRAW, WmSetFocusButtonSeq, WmKillFocusButtonSeq }
1759 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
1761 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
1762 0, 0, 50, 14, 0, 0, 0, NULL);
1763 ok(hwnd != 0, "Failed to create button window\n");
1765 ShowWindow(hwnd, SW_SHOW);
1770 trace("button style %08lx\n", button[i].style);
1772 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
1775 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
1777 DestroyWindow(hwnd);
1780 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE,
1781 0, 0, 50, 14, 0, 0, 0, NULL);
1782 ok(hwnd != 0, "Failed to create button window\n");
1787 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
1788 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
1790 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
1791 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONDOWN on a button", FALSE);
1792 DestroyWindow(hwnd);
1795 /************* painting message test ********************/
1797 static void dump_region(HRGN hrgn)
1800 RGNDATA *data = NULL;
1805 printf( "null region\n" );
1808 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
1809 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
1810 GetRegionData( hrgn, size, data );
1811 printf("%ld rects:", data->rdh.nCount );
1812 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
1813 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
1815 HeapFree( GetProcessHeap(), 0, data );
1818 static void check_update_rgn( HWND hwnd, HRGN hrgn )
1822 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
1823 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
1825 ret = GetUpdateRgn( hwnd, update, FALSE );
1826 ok( ret != ERROR, "GetUpdateRgn failed\n" );
1827 if (ret == NULLREGION)
1829 ok( !hrgn, "Update region shouldn't be empty\n" );
1833 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
1835 ok( 0, "Regions are different\n" );
1836 if (winetest_debug > 0)
1838 printf( "Update region: " );
1839 dump_region( update );
1840 printf( "Wanted region: " );
1841 dump_region( hrgn );
1845 GetRgnBox( update, &r1 );
1846 GetUpdateRect( hwnd, &r2, FALSE );
1847 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
1848 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
1849 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
1851 DeleteObject( tmp );
1852 DeleteObject( update );
1855 static const struct message WmInvalidateRgn[] = {
1856 { WM_NCPAINT, sent },
1857 { WM_GETTEXT, sent|defwinproc|optional },
1861 static const struct message WmInvalidateFull[] = {
1862 { WM_NCPAINT, sent|wparam, 1 },
1863 { WM_GETTEXT, sent|defwinproc|optional },
1867 static const struct message WmInvalidateErase[] = {
1868 { WM_NCPAINT, sent|wparam, 1 },
1869 { WM_GETTEXT, sent|defwinproc|optional },
1870 { WM_ERASEBKGND, sent },
1874 static const struct message WmInvalidatePaint[] = {
1876 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
1877 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
1881 static const struct message WmInvalidateErasePaint[] = {
1883 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
1884 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
1885 { WM_ERASEBKGND, sent|beginpaint },
1889 static const struct message WmErase[] = {
1890 { WM_ERASEBKGND, sent },
1894 static const struct message WmPaint[] = {
1899 static void test_paint_messages(void)
1903 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
1904 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1905 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1906 100, 100, 200, 200, 0, 0, 0, NULL);
1907 ok (hwnd != 0, "Failed to create overlapped window\n");
1909 ShowWindow( hwnd, SW_SHOW );
1910 UpdateWindow( hwnd );
1911 check_update_rgn( hwnd, 0 );
1912 SetRectRgn( hrgn, 10, 10, 20, 20 );
1913 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
1914 check_update_rgn( hwnd, hrgn );
1915 SetRectRgn( hrgn2, 20, 20, 30, 30 );
1916 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
1917 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
1918 check_update_rgn( hwnd, hrgn );
1919 /* validate everything */
1920 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
1921 check_update_rgn( hwnd, 0 );
1922 /* now with frame */
1923 SetRectRgn( hrgn, -5, -5, 20, 20 );
1926 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
1927 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
1929 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
1930 check_update_rgn( hwnd, hrgn );
1933 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
1934 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
1937 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
1938 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
1940 GetClientRect( hwnd, &rect );
1941 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
1942 check_update_rgn( hwnd, hrgn );
1945 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
1946 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
1949 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
1950 ok_sequence( WmInvalidatePaint, "InvalidatePaint", TRUE );
1951 check_update_rgn( hwnd, 0 );
1954 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
1955 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
1956 check_update_rgn( hwnd, 0 );
1959 SetRectRgn( hrgn, 0, 0, 100, 100 );
1960 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
1961 SetRectRgn( hrgn, 0, 0, 50, 100 );
1962 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
1963 SetRectRgn( hrgn, 50, 0, 100, 100 );
1964 check_update_rgn( hwnd, hrgn );
1965 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
1966 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
1967 check_update_rgn( hwnd, 0 );
1970 SetRectRgn( hrgn, 0, 0, 100, 100 );
1971 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
1972 SetRectRgn( hrgn, 0, 0, 100, 50 );
1973 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
1974 ok_sequence( WmErase, "Erase", FALSE );
1975 SetRectRgn( hrgn, 0, 50, 100, 100 );
1976 check_update_rgn( hwnd, hrgn );
1979 SetRectRgn( hrgn, 0, 0, 100, 100 );
1980 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
1981 SetRectRgn( hrgn, 0, 0, 50, 50 );
1982 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
1983 ok_sequence( WmPaint, "Paint", FALSE );
1986 SetRectRgn( hrgn, -4, -4, -2, -2 );
1987 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
1988 SetRectRgn( hrgn, -4, -4, -3, -3 );
1989 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
1990 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
1993 SetRectRgn( hrgn, -4, -4, -2, -2 );
1994 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
1995 SetRectRgn( hrgn, -4, -4, -3, -3 );
1996 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
1997 SetRectRgn( hrgn, 0, 0, 1, 1 );
1998 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
1999 ok_sequence( WmPaint, "Paint", TRUE );
2002 SetRectRgn( hrgn, -4, -4, -1, -1 );
2003 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
2004 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
2005 /* make sure no WM_PAINT was generated */
2006 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
2007 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
2010 SetRectRgn( hrgn, -4, -4, -1, -1 );
2011 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
2012 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
2014 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
2016 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
2017 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
2018 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
2019 ret = GetUpdateRect( hwnd, &rect, FALSE );
2020 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
2021 /* this will send WM_NCPAINT and validate the non client area */
2022 ret = GetUpdateRect( hwnd, &rect, TRUE );
2023 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
2025 else DispatchMessage( &msg );
2027 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
2029 DeleteObject( hrgn );
2030 DeleteObject( hrgn2 );
2031 DestroyWindow( hwnd );
2035 /************* window procedures ********************/
2037 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2039 static long defwndproc_counter = 0;
2040 static long beginpaint_counter = 0;
2044 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2046 msg.message = message;
2047 msg.flags = sent|wparam|lparam;
2048 if (defwndproc_counter) msg.flags |= defwinproc;
2049 if (beginpaint_counter) msg.flags |= beginpaint;
2050 msg.wParam = wParam;
2051 msg.lParam = lParam;
2054 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
2056 HWND parent = GetParent(hwnd);
2058 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
2060 GetClientRect(parent, &rc);
2061 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
2063 trace("ptReserved = (%ld,%ld)\n"
2064 "ptMaxSize = (%ld,%ld)\n"
2065 "ptMaxPosition = (%ld,%ld)\n"
2066 "ptMinTrackSize = (%ld,%ld)\n"
2067 "ptMaxTrackSize = (%ld,%ld)\n",
2068 minmax->ptReserved.x, minmax->ptReserved.y,
2069 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
2070 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
2071 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
2072 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
2074 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
2075 minmax->ptMaxSize.x, rc.right);
2076 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
2077 minmax->ptMaxSize.y, rc.bottom);
2080 if (message == WM_PAINT)
2083 beginpaint_counter++;
2084 BeginPaint( hwnd, &ps );
2085 beginpaint_counter--;
2086 EndPaint( hwnd, &ps );
2090 defwndproc_counter++;
2091 ret = DefWindowProcA(hwnd, message, wParam, lParam);
2092 defwndproc_counter--;
2097 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2099 static long defwndproc_counter = 0;
2103 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2105 msg.message = message;
2106 msg.flags = sent|wparam|lparam;
2107 if (defwndproc_counter) msg.flags |= defwinproc;
2108 msg.wParam = wParam;
2109 msg.lParam = lParam;
2112 if (message == WM_CREATE)
2114 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
2115 SetWindowLongA(hwnd, GWL_STYLE, style);
2118 defwndproc_counter++;
2119 ret = DefWindowProcA(hwnd, message, wParam, lParam);
2120 defwndproc_counter--;
2125 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2127 static long defwndproc_counter = 0;
2131 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2133 if (message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
2134 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
2135 message == WM_ENABLE || message == WM_ENTERIDLE ||
2136 message == WM_IME_SETCONTEXT)
2138 msg.message = message;
2139 msg.flags = sent|parent|wparam|lparam;
2140 if (defwndproc_counter) msg.flags |= defwinproc;
2141 msg.wParam = wParam;
2142 msg.lParam = lParam;
2146 defwndproc_counter++;
2147 ret = DefWindowProcA(hwnd, message, wParam, lParam);
2148 defwndproc_counter--;
2153 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2155 static long defwndproc_counter = 0;
2159 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2161 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
2162 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
2163 if (after_end_dialog)
2164 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
2166 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
2168 msg.message = message;
2169 msg.flags = sent|wparam|lparam;
2170 if (defwndproc_counter) msg.flags |= defwinproc;
2171 msg.wParam = wParam;
2172 msg.lParam = lParam;
2175 defwndproc_counter++;
2176 ret = DefDlgProcA(hwnd, message, wParam, lParam);
2177 defwndproc_counter--;
2182 static BOOL RegisterWindowClasses(void)
2187 cls.lpfnWndProc = MsgCheckProcA;
2190 cls.hInstance = GetModuleHandleA(0);
2192 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
2193 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2194 cls.lpszMenuName = NULL;
2195 cls.lpszClassName = "TestWindowClass";
2196 if(!RegisterClassA(&cls)) return FALSE;
2198 cls.lpfnWndProc = PopupMsgCheckProcA;
2199 cls.lpszClassName = "TestPopupClass";
2200 if(!RegisterClassA(&cls)) return FALSE;
2202 cls.lpfnWndProc = ParentMsgCheckProcA;
2203 cls.lpszClassName = "TestParentClass";
2204 if(!RegisterClassA(&cls)) return FALSE;
2206 cls.lpfnWndProc = DefWindowProcA;
2207 cls.lpszClassName = "SimpleWindowClass";
2208 if(!RegisterClassA(&cls)) return FALSE;
2210 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
2211 cls.lpfnWndProc = TestDlgProcA;
2212 cls.lpszClassName = "TestDialogClass";
2213 if(!RegisterClassA(&cls)) return FALSE;
2218 static HHOOK hCBT_hook;
2220 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
2224 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
2226 /* Log also SetFocus(0) calls */
2227 if (!wParam) wParam = lParam;
2229 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
2231 if (!strcmp(buf, "TestWindowClass") ||
2232 !strcmp(buf, "TestParentClass") ||
2233 !strcmp(buf, "TestPopupClass") ||
2234 !strcmp(buf, "SimpleWindowClass") ||
2235 !strcmp(buf, "TestDialogClass") ||
2236 !strcmp(buf, "MDI_frame_class") ||
2237 !strcmp(buf, "MDI_client_class") ||
2238 !strcmp(buf, "MDI_child_class") ||
2239 !strcmp(buf, "my_button_class") ||
2240 !strcmp(buf, "#32770"))
2244 msg.message = nCode;
2246 msg.wParam = wParam;
2247 msg.lParam = lParam;
2251 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
2256 if (!RegisterWindowClasses()) assert(0);
2258 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
2262 test_mdi_messages();
2263 test_button_messages();
2264 test_paint_messages();
2266 UnhookWindowsHookEx(hCBT_hook);