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
31 #include "wine/test.h"
33 #define MDI_FIRST_CHILD_ID 2004
36 FIXME: add tests for these
37 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
38 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
39 WS_THICKFRAME: thick border
40 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
41 WS_BORDER (default for overlapped windows): single black border
42 none (default for child (and popup?) windows): no border
46 sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10,
47 defwinproc=0x20, optional=0x40, hook=0x80
51 UINT message; /* the WM_* code */
52 msg_flags_t flags; /* message props */
53 WPARAM wParam; /* expected value of wParam */
54 LPARAM lParam; /* expected value of lParam */
57 /* Empty message sequence */
58 static const struct message WmEmptySeq[] =
62 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
63 static const struct message WmCreateOverlappedSeq[] = {
64 { HCBT_CREATEWND, hook },
65 { WM_GETMINMAXINFO, sent },
66 { WM_NCCREATE, sent },
67 { WM_NCCALCSIZE, sent|wparam, 0 },
71 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
72 * for a not visible overlapped window.
74 static const struct message WmSWP_ShowOverlappedSeq[] = {
75 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
76 { WM_NCPAINT, sent|wparam|optional, 1 },
77 { WM_GETTEXT, sent|defwinproc|optional },
78 { WM_ERASEBKGND, sent|optional },
79 { HCBT_ACTIVATE, hook },
80 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
81 { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, /* Win9x: SWP_NOSENDCHANGING */
82 { WM_ACTIVATEAPP, sent|wparam, 1 },
83 { WM_NCACTIVATE, sent|wparam, 1 },
84 { WM_GETTEXT, sent|defwinproc|optional },
85 { WM_ACTIVATE, sent|wparam, 1 },
86 { HCBT_SETFOCUS, hook },
87 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
88 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
89 { WM_NCPAINT, sent|wparam|optional, 1 },
90 { WM_GETTEXT, sent|defwinproc|optional },
91 { WM_ERASEBKGND, sent|optional },
92 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
93 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
94 { WM_NCPAINT, sent|wparam|optional, 1 },
95 { WM_ERASEBKGND, sent|optional },
98 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
99 * for a visible overlapped window.
101 static const struct message WmSWP_HideOverlappedSeq[] = {
102 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
103 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
106 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
107 static const struct message WmShowOverlappedSeq[] = {
108 { WM_SHOWWINDOW, sent|wparam, 1 },
109 { WM_NCPAINT, sent|wparam|optional, 1 },
110 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
111 { WM_NCPAINT, sent|wparam|optional, 1 },
112 { WM_GETTEXT, sent|defwinproc|optional },
113 { WM_ERASEBKGND, sent|optional },
114 { HCBT_ACTIVATE, hook },
115 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
116 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
117 { WM_ACTIVATEAPP, sent|wparam, 1 },
118 { WM_NCACTIVATE, sent|wparam, 1 },
119 { WM_GETTEXT, sent|defwinproc|optional },
120 { WM_ACTIVATE, sent|wparam, 1 },
121 { HCBT_SETFOCUS, hook },
122 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
123 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
124 { WM_NCPAINT, sent|wparam|optional, 1 },
125 { WM_GETTEXT, sent|defwinproc|optional },
126 { WM_ERASEBKGND, sent|optional },
127 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
128 { WM_NCCALCSIZE, sent|optional },
129 { WM_NCPAINT, sent|optional },
130 { WM_ERASEBKGND, sent|optional },
131 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
132 * messages. Does that mean that CreateWindow doesn't set initial
133 * window dimensions for overlapped windows?
140 /* ShowWindow(SW_HIDE) for a visible overlapped window */
141 static const struct message WmHideOverlappedSeq[] = {
142 { WM_SHOWWINDOW, sent|wparam, 0 },
143 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
144 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
147 { WM_NCACTIVATE, sent|wparam, 0 },
148 { WM_ACTIVATE, sent|wparam, 0 },
149 { WM_ACTIVATEAPP, sent|wparam, 0 },
150 { WM_KILLFOCUS, sent|wparam, 0 },
151 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
154 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
155 static const struct message WmHideInvisibleOverlappedSeq[] = {
158 /* DestroyWindow for a visible overlapped window */
159 static const struct message WmDestroyOverlappedSeq[] = {
160 { HCBT_DESTROYWND, hook },
161 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
162 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
163 { WM_NCACTIVATE, sent|wparam, 0 },
164 { WM_ACTIVATE, sent|wparam, 0 },
165 { WM_ACTIVATEAPP, sent|wparam, 0 },
166 { WM_KILLFOCUS, sent|wparam, 0 },
167 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
168 { WM_DESTROY, sent },
169 { WM_NCDESTROY, sent },
172 /* CreateWindow (for a child popup window, not initially visible) */
173 static const struct message WmCreateChildPopupSeq[] = {
174 { HCBT_CREATEWND, hook },
175 { WM_NCCREATE, sent },
176 { WM_NCCALCSIZE, sent|wparam, 0 },
182 /* CreateWindow (for a popup window, not initially visible,
183 * which sets WS_VISIBLE in WM_CREATE handler)
185 static const struct message WmCreateInvisiblePopupSeq[] = {
186 { HCBT_CREATEWND, hook },
187 { WM_NCCREATE, sent },
188 { WM_NCCALCSIZE, sent|wparam, 0 },
190 { WM_STYLECHANGING, sent },
191 { WM_STYLECHANGED, sent },
196 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
197 * for a popup window with WS_VISIBLE style set
199 static const struct message WmShowVisiblePopupSeq_2[] = {
200 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
203 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
204 * for a popup window with WS_VISIBLE style set
206 static const struct message WmShowVisiblePopupSeq_3[] = {
207 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
208 { HCBT_ACTIVATE, hook },
209 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
210 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
211 { WM_NCACTIVATE, sent|wparam, 1 },
212 { WM_ACTIVATE, sent|wparam, 1 },
213 { HCBT_SETFOCUS, hook },
214 { WM_KILLFOCUS, sent|parent },
215 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
216 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
217 { WM_SETFOCUS, sent|defwinproc },
220 /* CreateWindow (for child window, not initially visible) */
221 static const struct message WmCreateChildSeq[] = {
222 { HCBT_CREATEWND, hook },
223 { WM_NCCREATE, sent },
224 /* child is inserted into parent's child list after WM_NCCREATE returns */
225 { WM_NCCALCSIZE, sent|wparam, 0 },
229 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
232 /* CreateWindow (for maximized child window, not initially visible) */
233 static const struct message WmCreateMaximizedChildSeq[] = {
234 { HCBT_CREATEWND, hook },
235 { WM_NCCREATE, sent },
236 { WM_NCCALCSIZE, sent|wparam, 0 },
240 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
241 { WM_GETMINMAXINFO, sent },
242 { WM_WINDOWPOSCHANGING, sent },
243 { WM_NCCALCSIZE, sent|wparam, 1 },
244 { WM_WINDOWPOSCHANGED, sent },
245 { WM_SIZE, sent|defwinproc },
246 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
249 /* CreateWindow (for a child window, initially visible) */
250 static const struct message WmCreateVisibleChildSeq[] = {
251 { HCBT_CREATEWND, hook },
252 { WM_NCCREATE, sent },
253 /* child is inserted into parent's child list after WM_NCCREATE returns */
254 { WM_NCCALCSIZE, sent|wparam, 0 },
258 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
259 { WM_SHOWWINDOW, sent|wparam, 1 },
260 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
261 { WM_ERASEBKGND, sent|parent|optional },
262 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
265 /* ShowWindow(SW_SHOW) for a not visible child window */
266 static const struct message WmShowChildSeq[] = {
267 { WM_SHOWWINDOW, sent|wparam, 1 },
268 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
269 { WM_ERASEBKGND, sent|parent|optional },
270 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
273 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
274 * for a not visible child window
276 static const struct message WmShowChildSeq_2[] = {
277 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
278 { WM_CHILDACTIVATE, sent },
279 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
282 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
283 * for a not visible child window
285 static const struct message WmShowChildSeq_3[] = {
286 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
287 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
290 /* DestroyWindow for a visible child window */
291 static const struct message WmDestroyChildSeq[] = {
292 { HCBT_DESTROYWND, hook },
293 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
294 { WM_SHOWWINDOW, sent|wparam, 0 },
295 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
296 { WM_ERASEBKGND, sent|parent|optional },
297 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
298 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
299 { WM_KILLFOCUS, sent },
300 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
301 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
302 { WM_SETFOCUS, sent|parent },
303 { WM_DESTROY, sent },
304 { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
305 { WM_NCDESTROY, sent },
306 { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
309 /* Moving the mouse in nonclient area */
310 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
311 { WM_NCHITTEST, sent },
312 { WM_SETCURSOR, sent },
313 { WM_NCMOUSEMOVE, posted },
316 /* Moving the mouse in client area */
317 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
318 { WM_NCHITTEST, sent },
319 { WM_SETCURSOR, sent },
320 { WM_MOUSEMOVE, posted },
323 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
324 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
325 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
326 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
327 { WM_GETMINMAXINFO, sent|defwinproc },
328 { WM_ENTERSIZEMOVE, sent|defwinproc },
329 { WM_WINDOWPOSCHANGING, sent|defwinproc },
330 { WM_WINDOWPOSCHANGED, sent|defwinproc },
331 { WM_MOVE, sent|defwinproc },
332 { WM_EXITSIZEMOVE, sent|defwinproc },
335 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
336 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
337 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
338 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
339 { WM_GETMINMAXINFO, sent|defwinproc },
340 { WM_ENTERSIZEMOVE, sent|defwinproc },
341 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
342 { WM_WINDOWPOSCHANGING, sent|defwinproc },
343 { WM_GETMINMAXINFO, sent|defwinproc },
344 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
345 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
346 { WM_GETTEXT, sent|defwinproc },
347 { WM_ERASEBKGND, sent|defwinproc },
348 { WM_WINDOWPOSCHANGED, sent|defwinproc },
349 { WM_MOVE, sent|defwinproc },
350 { WM_SIZE, sent|defwinproc },
351 { WM_EXITSIZEMOVE, sent|defwinproc },
354 /* Resizing child window with MoveWindow (32) */
355 static const struct message WmResizingChildWithMoveWindowSeq[] = {
356 { WM_WINDOWPOSCHANGING, sent },
357 { WM_NCCALCSIZE, sent|wparam, 1 },
358 { WM_ERASEBKGND, sent|optional },
359 { WM_WINDOWPOSCHANGED, sent },
360 { WM_MOVE, sent|defwinproc },
361 { WM_SIZE, sent|defwinproc },
364 /* Clicking on inactive button */
365 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
366 { WM_NCHITTEST, sent },
367 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
368 { WM_MOUSEACTIVATE, sent },
369 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
370 { WM_SETCURSOR, sent },
371 { WM_SETCURSOR, sent|parent|defwinproc },
372 { WM_LBUTTONDOWN, posted },
373 { WM_KILLFOCUS, posted|parent },
374 { WM_SETFOCUS, posted },
375 { WM_CTLCOLORBTN, posted|parent },
376 { BM_SETSTATE, posted },
377 { WM_CTLCOLORBTN, posted|parent },
378 { WM_LBUTTONUP, posted },
379 { BM_SETSTATE, posted },
380 { WM_CTLCOLORBTN, posted|parent },
381 { WM_COMMAND, posted|parent },
384 /* Reparenting a button (16/32) */
385 /* The last child (button) reparented gets topmost for its new parent. */
386 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
387 { WM_SHOWWINDOW, sent|wparam, 0 },
388 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
389 { WM_ERASEBKGND, sent|parent },
390 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
391 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
392 { WM_CHILDACTIVATE, sent },
393 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
394 { WM_MOVE, sent|defwinproc },
395 { WM_SHOWWINDOW, sent|wparam, 1 },
398 /* Creation of a custom dialog (32) */
399 static const struct message WmCreateCustomDialogSeq[] = {
400 { HCBT_CREATEWND, hook },
401 { WM_GETMINMAXINFO, sent },
402 { WM_NCCREATE, sent },
403 { WM_NCCALCSIZE, sent|wparam, 0 },
405 { WM_SHOWWINDOW, sent|wparam, 1 },
406 { HCBT_ACTIVATE, hook },
407 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
408 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
409 { WM_NCACTIVATE, sent|wparam, 1 },
410 { WM_GETTEXT, sent|optional|defwinproc },
411 { WM_GETICON, sent|optional|defwinproc },
412 { WM_GETICON, sent|optional|defwinproc },
413 { WM_GETICON, sent|optional|defwinproc },
414 { WM_GETTEXT, sent|optional|defwinproc },
415 { WM_ACTIVATE, sent|wparam, 1 },
416 { WM_KILLFOCUS, sent|parent },
417 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
418 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
419 { WM_SETFOCUS, sent },
420 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
421 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
422 { WM_NCPAINT, sent|wparam, 1 },
423 { WM_GETTEXT, sent|optional|defwinproc },
424 { WM_GETICON, sent|optional|defwinproc },
425 { WM_GETICON, sent|optional|defwinproc },
426 { WM_GETICON, sent|optional|defwinproc },
427 { WM_GETTEXT, sent|optional|defwinproc },
428 { WM_ERASEBKGND, sent },
429 { WM_CTLCOLORDLG, sent|defwinproc },
430 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
431 { WM_GETTEXT, sent|optional },
432 { WM_GETICON, sent|optional },
433 { WM_GETICON, sent|optional },
434 { WM_GETICON, sent|optional },
435 { WM_GETTEXT, sent|optional },
436 { WM_NCCALCSIZE, sent|optional },
437 { WM_NCPAINT, sent|optional },
438 { WM_GETTEXT, sent|optional|defwinproc },
439 { WM_GETICON, sent|optional|defwinproc },
440 { WM_GETICON, sent|optional|defwinproc },
441 { WM_GETICON, sent|optional|defwinproc },
442 { WM_GETTEXT, sent|optional|defwinproc },
443 { WM_ERASEBKGND, sent|optional },
444 { WM_CTLCOLORDLG, sent|optional|defwinproc },
449 /* Calling EndDialog for a custom dialog (32) */
450 static const struct message WmEndCustomDialogSeq[] = {
451 { WM_WINDOWPOSCHANGING, sent },
452 { WM_WINDOWPOSCHANGED, sent },
453 { WM_GETTEXT, sent|optional },
454 { WM_GETICON, sent|optional },
455 { WM_GETICON, sent|optional },
456 { WM_GETICON, sent|optional },
457 { HCBT_ACTIVATE, hook },
458 { WM_NCACTIVATE, sent|wparam, 0 },
459 { WM_GETTEXT, sent|optional|defwinproc },
460 { WM_GETICON, sent|optional|defwinproc },
461 { WM_GETICON, sent|optional|defwinproc },
462 { WM_GETICON, sent|optional|defwinproc },
463 { WM_GETTEXT, sent|optional|defwinproc },
464 { WM_ACTIVATE, sent|wparam, 0 },
465 { WM_WINDOWPOSCHANGING, sent|optional },
466 { HCBT_SETFOCUS, hook },
467 { WM_KILLFOCUS, sent },
468 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
469 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
470 { WM_SETFOCUS, sent|parent|defwinproc },
473 /* Creation and destruction of a modal dialog (32) */
474 static const struct message WmModalDialogSeq[] = {
475 { WM_CANCELMODE, sent|parent },
476 { WM_KILLFOCUS, sent|parent },
477 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
478 { WM_ENABLE, sent|parent|wparam, 0 },
479 { HCBT_CREATEWND, hook },
480 { WM_SETFONT, sent },
481 { WM_INITDIALOG, sent },
482 { WM_CHANGEUISTATE, sent|optional },
483 { WM_SHOWWINDOW, sent },
484 { HCBT_ACTIVATE, hook },
485 { WM_WINDOWPOSCHANGING, sent },
486 { WM_NCACTIVATE, sent|wparam, 1 },
487 { WM_GETICON, sent|optional },
488 { WM_GETICON, sent|optional },
489 { WM_GETICON, sent|optional },
490 { WM_GETTEXT, sent|optional },
491 { WM_ACTIVATE, sent|wparam, 1 },
492 { WM_WINDOWPOSCHANGING, sent },
493 { WM_NCPAINT, sent },
494 { WM_GETICON, sent|optional },
495 { WM_GETICON, sent|optional },
496 { WM_GETICON, sent|optional },
497 { WM_GETTEXT, sent|optional },
498 { WM_ERASEBKGND, sent },
499 { WM_CTLCOLORDLG, sent },
500 { WM_WINDOWPOSCHANGED, sent },
501 { WM_GETICON, sent|optional },
502 { WM_GETICON, sent|optional },
503 { WM_GETICON, sent|optional },
504 { WM_GETTEXT, sent|optional },
505 { WM_NCCALCSIZE, sent|optional },
506 { WM_NCPAINT, sent|optional },
507 { WM_GETICON, sent|optional },
508 { WM_GETICON, sent|optional },
509 { WM_GETICON, sent|optional },
510 { WM_GETTEXT, sent|optional },
511 { WM_ERASEBKGND, sent|optional },
512 { WM_CTLCOLORDLG, sent|optional },
513 { WM_PAINT, sent|optional },
514 { WM_CTLCOLORBTN, sent },
515 { WM_ENTERIDLE, sent|parent },
517 { WM_ENABLE, sent|parent|wparam, 1 },
518 { WM_WINDOWPOSCHANGING, sent },
519 { WM_WINDOWPOSCHANGED, sent },
520 { WM_GETICON, sent|optional },
521 { WM_GETICON, sent|optional },
522 { WM_GETICON, sent|optional },
523 { WM_GETTEXT, sent|optional },
524 { HCBT_ACTIVATE, hook },
525 { WM_NCACTIVATE, sent|wparam, 0 },
526 { WM_GETICON, sent|optional },
527 { WM_GETICON, sent|optional },
528 { WM_GETICON, sent|optional },
529 { WM_GETTEXT, sent|optional },
530 { WM_ACTIVATE, sent|wparam, 0 },
531 { WM_WINDOWPOSCHANGING, sent|optional },
532 { HCBT_SETFOCUS, hook },
533 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
534 { WM_SETFOCUS, sent|parent|defwinproc },
535 { HCBT_DESTROYWND, hook },
536 { WM_DESTROY, sent },
537 { WM_NCDESTROY, sent },
540 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
541 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
542 /* (inside dialog proc, handling WM_INITDIALOG) */
543 { WM_WINDOWPOSCHANGING, sent },
544 { WM_NCCALCSIZE, sent },
545 { WM_NCACTIVATE, sent|parent|wparam, 0 },
546 { WM_GETTEXT, sent|defwinproc },
547 { WM_ACTIVATE, sent|parent|wparam, 0 },
548 { WM_WINDOWPOSCHANGING, sent },
549 { WM_WINDOWPOSCHANGING, sent|parent },
550 { WM_NCACTIVATE, sent|wparam, 1 },
551 { WM_ACTIVATE, sent|wparam, 1 },
552 { WM_WINDOWPOSCHANGED, sent },
553 { WM_SIZE, sent|defwinproc },
554 /* (setting focus) */
555 { WM_SHOWWINDOW, sent|wparam, 1 },
556 { WM_WINDOWPOSCHANGING, sent },
557 { WM_NCPAINT, sent },
558 { WM_GETTEXT, sent|defwinproc },
559 { WM_ERASEBKGND, sent },
560 { WM_CTLCOLORDLG, sent|defwinproc },
561 { WM_WINDOWPOSCHANGED, sent },
563 /* (bunch of WM_CTLCOLOR* for each control) */
564 { WM_PAINT, sent|parent },
565 { WM_ENTERIDLE, sent|parent|wparam, 0 },
566 { WM_SETCURSOR, sent|parent },
569 /* SetMenu for NonVisible windows with size change*/
570 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
571 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
572 { WM_NCCALCSIZE, sent|wparam, 1 },
573 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
574 { WM_MOVE, sent|defwinproc },
575 { WM_SIZE, sent|defwinproc },
576 { WM_GETICON, sent|optional },
577 { WM_GETICON, sent|optional },
578 { WM_GETICON, sent|optional },
579 { WM_GETTEXT, sent|optional },
580 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
583 /* SetMenu for NonVisible windows with no size change */
584 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
585 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
586 { WM_NCCALCSIZE, sent|wparam, 1 },
587 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
590 /* SetMenu for Visible windows with size change */
591 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
592 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
593 { WM_NCCALCSIZE, sent|wparam, 1 },
594 { WM_NCPAINT, sent|wparam, 1 },
595 { WM_GETTEXT, sent|defwinproc|optional },
596 { WM_ERASEBKGND, sent|optional },
597 { WM_ACTIVATE, sent|optional },
598 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
599 { WM_MOVE, sent|defwinproc },
600 { WM_SIZE, sent|defwinproc },
601 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
602 { WM_NCPAINT, sent|wparam|optional, 1 },
603 { WM_ERASEBKGND, sent|optional },
606 /* SetMenu for Visible windows with no size change */
607 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
608 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
609 { WM_NCCALCSIZE, sent|wparam, 1 },
610 { WM_NCPAINT, sent|wparam, 1 },
611 { WM_GETTEXT, sent|defwinproc|optional },
612 { WM_ERASEBKGND, sent|optional },
613 { WM_ACTIVATE, sent|optional },
614 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
617 /* DrawMenuBar for a visible window */
618 static const struct message WmDrawMenuBarSeq[] =
620 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
621 { WM_NCCALCSIZE, sent|wparam, 1 },
622 { WM_NCPAINT, sent|wparam, 1 },
623 { WM_GETTEXT, sent|defwinproc|optional },
624 { WM_ERASEBKGND, sent|optional },
625 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
629 static const struct message WmSetRedrawFalseSeq[] =
631 { WM_SETREDRAW, sent|wparam, 0 },
635 static const struct message WmSetRedrawTrueSeq[] =
637 { WM_SETREDRAW, sent|wparam, 1 },
641 static const struct message WmEnableWindowSeq[] =
643 { WM_CANCELMODE, sent },
648 static const struct message WmGetScrollRangeSeq[] =
650 { SBM_GETRANGE, sent },
653 static const struct message WmGetScrollInfoSeq[] =
655 { SBM_GETSCROLLINFO, sent },
658 static const struct message WmSetScrollRangeSeq[] =
660 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
661 sends SBM_SETSCROLLINFO.
663 { SBM_SETSCROLLINFO, sent },
666 /* SetScrollRange for a window without a non-client area */
667 static const struct message WmSetScrollRangeHVSeq[] =
669 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
670 { WM_NCCALCSIZE, sent|wparam, 1 },
671 { WM_GETTEXT, sent|defwinproc|optional },
672 { WM_ERASEBKGND, sent|optional },
673 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
676 /* SetScrollRange for a window with a non-client area */
677 static const struct message WmSetScrollRangeHV_NC_Seq[] =
679 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
680 { WM_NCCALCSIZE, sent|wparam, 1 },
681 { WM_NCPAINT, sent|optional },
682 { WM_GETTEXT, sent|defwinproc|optional },
683 { WM_ERASEBKGND, sent|optional },
684 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
685 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
686 { WM_SIZE, sent|defwinproc },
690 static int after_end_dialog;
691 static int sequence_cnt, sequence_size;
692 static struct message* sequence;
694 static void add_message(const struct message *msg)
699 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
701 if (sequence_cnt == sequence_size)
704 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
708 sequence[sequence_cnt].message = msg->message;
709 sequence[sequence_cnt].flags = msg->flags;
710 sequence[sequence_cnt].wParam = msg->wParam;
711 sequence[sequence_cnt].lParam = msg->lParam;
716 static void flush_sequence()
718 HeapFree(GetProcessHeap(), 0, sequence);
720 sequence_cnt = sequence_size = 0;
723 static void ok_sequence(const struct message *expected, const char *context)
725 static const struct message end_of_sequence = { 0, 0, 0, 0 };
726 const struct message *actual;
728 add_message(&end_of_sequence);
732 while (expected->message && actual->message)
734 trace("expected %04x - actual %04x\n", expected->message, actual->message);
736 if (expected->message == actual->message)
738 if (expected->flags & wparam)
739 ok (expected->wParam == actual->wParam,
740 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
741 context, expected->message, expected->wParam, actual->wParam);
742 if (expected->flags & lparam)
743 ok (expected->lParam == actual->lParam,
744 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
745 context, expected->message, expected->lParam, actual->lParam);
746 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
747 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
748 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
749 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
750 "%s: the msg 0x%04x should have been %s\n",
751 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
752 ok ((expected->flags & parent) == (actual->flags & parent),
753 "%s: the msg 0x%04x was expected in %s\n",
754 context, expected->message, (expected->flags & parent) ? "parent" : "child");
755 ok ((expected->flags & hook) == (actual->flags & hook),
756 "%s: the msg 0x%04x should have been sent by a hook\n",
757 context, expected->message);
761 else if (expected->flags & optional)
766 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
767 context, expected->message, actual->message);
774 /* skip all optional trailing messages */
775 while (expected->message && (expected->flags & optional))
779 if (expected->message || actual->message)
780 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
781 context, expected->message, actual->message);
787 /******************************** MDI test **********************************/
789 /* CreateWindow for MDI frame window, initially visible */
790 static const struct message WmCreateMDIframeSeq[] = {
791 { HCBT_CREATEWND, hook },
792 { WM_GETMINMAXINFO, sent },
793 { WM_NCCREATE, sent },
794 { WM_NCCALCSIZE, sent|wparam, 0 },
796 { WM_SHOWWINDOW, sent|wparam, 1 },
797 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
798 { HCBT_ACTIVATE, hook },
799 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
800 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
801 { WM_WINDOWPOSCHANGED, sent|wparam|optional, 0 }, /* Win9x */
802 { WM_ACTIVATEAPP, sent|wparam, 1 },
803 { WM_NCACTIVATE, sent|wparam, 1 },
804 { WM_ACTIVATE, sent|wparam, 1 },
805 { HCBT_SETFOCUS, hook },
806 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
807 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
808 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
813 /* DestroyWindow for MDI frame window, initially visible */
814 static const struct message WmDestroyMDIframeSeq[] = {
815 { HCBT_DESTROYWND, hook },
816 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
817 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
818 { WM_NCACTIVATE, sent|wparam, 0 },
819 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
820 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
821 { WM_DESTROY, sent },
822 { WM_NCDESTROY, sent },
825 /* CreateWindow for MDI client window, initially visible */
826 static const struct message WmCreateMDIclientSeq[] = {
827 { HCBT_CREATEWND, hook },
828 { WM_NCCREATE, sent },
829 { WM_NCCALCSIZE, sent|wparam, 0 },
833 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
834 { WM_SHOWWINDOW, sent|wparam, 1 },
835 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
836 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
839 /* DestroyWindow for MDI client window, initially visible */
840 static const struct message WmDestroyMDIclientSeq[] = {
841 { HCBT_DESTROYWND, hook },
842 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
843 { WM_SHOWWINDOW, sent|wparam, 0 },
844 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
845 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
846 { WM_DESTROY, sent },
847 { WM_NCDESTROY, sent },
850 /* CreateWindow for MDI child window, initially visible */
851 static const struct message WmCreateMDIchildVisibleSeq[] = {
852 { HCBT_CREATEWND, hook },
853 { WM_NCCREATE, sent },
854 { WM_NCCALCSIZE, sent|wparam, 0 },
858 /* Win2k sends wparam set to
859 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
860 * while Win9x doesn't bother to set child window id according to
861 * CLIENTCREATESTRUCT.idFirstChild
863 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
864 { WM_SHOWWINDOW, sent|wparam, 1 },
865 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
866 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
867 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
868 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE*/
869 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
870 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 }, /*SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/
872 /* Win9x: message sequence terminates here. */
874 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
875 { HCBT_SETFOCUS, hook }, /* in MDI client */
876 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
877 { WM_SETFOCUS, sent }, /* in MDI client */
878 { HCBT_SETFOCUS, hook },
879 { WM_KILLFOCUS, sent }, /* in MDI client */
880 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
881 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
882 { WM_SETFOCUS, sent|defwinproc },
883 { WM_MDIACTIVATE, sent|defwinproc },
886 /* DestroyWindow for MDI child window, initially visible */
887 static const struct message WmDestroyMDIchildVisibleSeq[] = {
888 { HCBT_DESTROYWND, hook },
889 /* Win2k sends wparam set to
890 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
891 * while Win9x doesn't bother to set child window id according to
892 * CLIENTCREATESTRUCT.idFirstChild
894 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
895 { WM_SHOWWINDOW, sent|wparam, 0 },
896 { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
897 { WM_ERASEBKGND, sent|parent|optional },
898 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
900 /* { WM_DESTROY, sent }
901 * Win9x: message sequence terminates here.
904 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
905 { WM_KILLFOCUS, sent },
906 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
907 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
908 { WM_SETFOCUS, sent }, /* in MDI client */
910 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
911 { WM_KILLFOCUS, sent }, /* in MDI client */
912 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
913 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
914 { WM_SETFOCUS, sent }, /* in MDI client */
916 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
917 { WM_KILLFOCUS, sent },
918 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
919 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
920 { WM_SETFOCUS, sent }, /* in MDI client */
922 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
923 { WM_KILLFOCUS, sent }, /* in MDI client */
924 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
925 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
926 { WM_SETFOCUS, sent }, /* in MDI client */
928 { WM_DESTROY, sent },
930 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
931 { WM_KILLFOCUS, sent },
932 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
933 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
934 { WM_SETFOCUS, sent }, /* in MDI client */
936 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
937 { WM_KILLFOCUS, sent }, /* in MDI client */
938 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
939 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
940 { WM_SETFOCUS, sent }, /* in MDI client */
942 { WM_NCDESTROY, sent },
945 /* CreateWindow for MDI child window, initially invisible */
946 static const struct message WmCreateMDIchildInvisibleSeq[] = {
947 { HCBT_CREATEWND, hook },
948 { WM_NCCREATE, sent },
949 { WM_NCCALCSIZE, sent|wparam, 0 },
953 /* Win2k sends wparam set to
954 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
955 * while Win9x doesn't bother to set child window id according to
956 * CLIENTCREATESTRUCT.idFirstChild
958 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
961 /* DestroyWindow for MDI child window, initially invisible */
962 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
963 { HCBT_DESTROYWND, hook },
964 /* Win2k sends wparam set to
965 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
966 * while Win9x doesn't bother to set child window id according to
967 * CLIENTCREATESTRUCT.idFirstChild
969 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
970 { WM_DESTROY, sent },
971 { WM_NCDESTROY, sent },
975 static HWND mdi_client;
976 static WNDPROC old_mdi_client_proc;
978 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
982 /* do not log painting messages */
983 if (message != WM_PAINT &&
984 message != WM_ERASEBKGND &&
985 message != WM_NCPAINT &&
986 message != WM_GETTEXT)
988 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
990 msg.message = message;
991 msg.flags = sent|wparam|lparam;
997 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1000 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1002 static long defwndproc_counter = 0;
1006 /* do not log painting messages */
1007 if (message != WM_PAINT &&
1008 message != WM_ERASEBKGND &&
1009 message != WM_NCPAINT &&
1010 message != WM_GETTEXT)
1012 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1016 case WM_WINDOWPOSCHANGING:
1017 case WM_WINDOWPOSCHANGED:
1019 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1021 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1022 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1023 winpos->hwnd, winpos->hwndInsertAfter,
1024 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1029 msg.message = message;
1030 msg.flags = sent|wparam|lparam;
1031 if (defwndproc_counter) msg.flags |= defwinproc;
1032 msg.wParam = wParam;
1033 msg.lParam = lParam;
1037 defwndproc_counter++;
1038 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1039 defwndproc_counter--;
1044 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1046 static long defwndproc_counter = 0;
1050 /* do not log painting messages */
1051 if (message != WM_PAINT &&
1052 message != WM_ERASEBKGND &&
1053 message != WM_NCPAINT &&
1054 message != WM_GETTEXT)
1056 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1058 msg.message = message;
1059 msg.flags = sent|wparam|lparam;
1060 if (defwndproc_counter) msg.flags |= defwinproc;
1061 msg.wParam = wParam;
1062 msg.lParam = lParam;
1066 defwndproc_counter++;
1067 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
1068 defwndproc_counter--;
1073 static BOOL mdi_RegisterWindowClasses(void)
1078 cls.lpfnWndProc = mdi_frame_wnd_proc;
1081 cls.hInstance = GetModuleHandleA(0);
1083 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1084 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1085 cls.lpszMenuName = NULL;
1086 cls.lpszClassName = "MDI_frame_class";
1087 if (!RegisterClassA(&cls)) return FALSE;
1089 cls.lpfnWndProc = mdi_child_wnd_proc;
1090 cls.lpszClassName = "MDI_child_class";
1091 if (!RegisterClassA(&cls)) return FALSE;
1093 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
1094 old_mdi_client_proc = cls.lpfnWndProc;
1095 cls.hInstance = GetModuleHandleA(0);
1096 cls.lpfnWndProc = mdi_client_hook_proc;
1097 cls.lpszClassName = "MDI_client_class";
1098 if (!RegisterClassA(&cls)) assert(0);
1103 static void test_mdi_messages(void)
1105 CLIENTCREATESTRUCT client_cs;
1106 HWND mdi_frame, mdi_child;
1108 assert(mdi_RegisterWindowClasses());
1112 trace("creating MDI frame window\n");
1113 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1114 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1115 WS_MAXIMIZEBOX | WS_VISIBLE,
1116 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1117 GetDesktopWindow(), 0,
1118 GetModuleHandleA(0), NULL);
1120 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window");
1122 trace("creating MDI client window\n");
1123 client_cs.hWindowMenu = 0;
1124 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
1125 mdi_client = CreateWindowExA(0, "MDI_client_class",
1127 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
1129 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
1131 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window");
1133 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
1138 trace("creating visible MDI child window\n");
1139 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1140 WS_CHILD | WS_VISIBLE,
1141 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1142 mdi_client, 0, GetModuleHandleA(0), NULL);
1144 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window");
1146 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1147 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1149 DestroyWindow(mdi_child);
1150 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window");
1155 trace("creating invisible MDI child window\n");
1156 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1158 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1159 mdi_client, 0, GetModuleHandleA(0), NULL);
1161 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window");
1163 ok(!(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
1164 ok(!IsWindowVisible(mdi_child), "MDI child should not be visible\n");
1166 DestroyWindow(mdi_child);
1167 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window");
1169 DestroyWindow(mdi_client);
1170 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window");
1172 DestroyWindow(mdi_frame);
1173 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window");
1175 /************************* End of MDI test **********************************/
1177 static void test_WM_SETREDRAW(HWND hwnd)
1179 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
1183 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
1184 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE");
1186 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
1187 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
1190 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
1191 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE");
1193 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1194 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
1196 /* restore original WS_VISIBLE state */
1197 SetWindowLongA(hwnd, GWL_STYLE, style);
1202 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1206 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1208 msg.message = message;
1209 msg.flags = sent|wparam|lparam;
1210 msg.wParam = wParam;
1211 msg.lParam = lParam;
1214 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
1215 if (message == WM_TIMER) EndDialog( hwnd, 0 );
1219 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1221 DWORD style, exstyle;
1224 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1225 style = GetWindowLongA(hwnd, GWL_STYLE);
1226 /* do not be confused by WS_DLGFRAME set */
1227 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1229 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1230 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1232 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1233 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1234 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC");
1236 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)");
1238 style = GetWindowLongA(hwnd, GWL_STYLE);
1239 if (set) ok(style & set, "style %08lx should be set\n", set);
1240 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1242 /* a subsequent call should do nothing */
1243 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1244 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT)");
1248 trace("Ignore GetScrollRange error below if you are on Win9x\n");
1249 ok(GetScrollRange(hwnd, ctl, &xmin, &xmax), "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
1250 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)");
1251 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
1252 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
1255 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1257 DWORD style, exstyle;
1260 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1261 style = GetWindowLongA(hwnd, GWL_STYLE);
1262 /* do not be confused by WS_DLGFRAME set */
1263 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1265 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1266 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1268 si.cbSize = sizeof(si);
1269 si.fMask = SIF_RANGE;
1272 SetScrollInfo(hwnd, ctl, &si, TRUE);
1273 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1274 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC");
1276 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1278 style = GetWindowLongA(hwnd, GWL_STYLE);
1279 if (set) ok(style & set, "style %08lx should be set\n", set);
1280 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1282 /* a subsequent call should do nothing */
1283 SetScrollInfo(hwnd, ctl, &si, TRUE);
1284 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1286 si.fMask = SIF_PAGE;
1288 SetScrollInfo(hwnd, ctl, &si, FALSE);
1289 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1293 SetScrollInfo(hwnd, ctl, &si, FALSE);
1294 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1296 si.fMask = SIF_RANGE;
1297 si.nMin = 0xdeadbeef;
1298 si.nMax = 0xdeadbeef;
1299 ok(GetScrollInfo(hwnd, ctl, &si), "GetScrollInfo error %ld\n", GetLastError());
1300 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)");
1301 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
1302 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
1305 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
1306 static void test_scroll_messages(HWND hwnd)
1313 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1314 if (sequence->message != WmGetScrollRangeSeq[0].message)
1315 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1316 /* values of min and max are undefined */
1319 ok(SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE), "SetScrollRange error %ld\n", GetLastError());
1320 if (sequence->message != WmSetScrollRangeSeq[0].message)
1321 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1326 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1327 if (sequence->message != WmGetScrollRangeSeq[0].message)
1328 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1329 /* values of min and max are undefined */
1332 si.cbSize = sizeof(si);
1333 si.fMask = SIF_RANGE;
1336 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1337 if (sequence->message != WmSetScrollRangeSeq[0].message)
1338 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1341 si.fMask = SIF_PAGE;
1343 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1344 if (sequence->message != WmSetScrollRangeSeq[0].message)
1345 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1350 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1351 if (sequence->message != WmSetScrollRangeSeq[0].message)
1352 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1355 si.fMask = SIF_RANGE;
1356 si.nMin = 0xdeadbeef;
1357 si.nMax = 0xdeadbeef;
1358 ok(GetScrollInfo(hwnd, SB_CTL, &si), "GetScrollInfo error %ld\n", GetLastError());
1359 if (sequence->message != WmGetScrollInfoSeq[0].message)
1360 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1361 /* values of min and max are undefined */
1364 /* set WS_HSCROLL */
1365 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1366 /* clear WS_HSCROLL */
1367 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1369 /* set WS_HSCROLL */
1370 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1371 /* clear WS_HSCROLL */
1372 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1374 /* set WS_VSCROLL */
1375 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1376 /* clear WS_VSCROLL */
1377 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1379 /* set WS_VSCROLL */
1380 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1381 /* clear WS_VSCROLL */
1382 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1385 /* test if we receive the right sequence of messages */
1386 static void test_messages(void)
1388 HWND hwnd, hparent, hchild;
1389 HWND hchild2, hbutton;
1392 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1393 100, 100, 200, 200, 0, 0, 0, NULL);
1394 ok (hwnd != 0, "Failed to create overlapped window\n");
1395 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
1397 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
1398 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
1399 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible");
1401 /* test WM_SETREDRAW on a not visible top level window */
1402 test_WM_SETREDRAW(hwnd);
1404 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1405 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped");
1406 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
1408 ok(GetActiveWindow() == hwnd, "window should be active\n");
1409 ok(GetFocus() == hwnd, "window should have input focus\n");
1410 ShowWindow(hwnd, SW_HIDE);
1411 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped");
1413 ShowWindow(hwnd, SW_SHOW);
1414 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped");
1416 ok(GetActiveWindow() == hwnd, "window should be active\n");
1417 ok(GetFocus() == hwnd, "window should have input focus\n");
1418 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1419 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped");
1420 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
1422 /* test WM_SETREDRAW on a visible top level window */
1423 ShowWindow(hwnd, SW_SHOW);
1424 test_WM_SETREDRAW(hwnd);
1426 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
1427 test_scroll_messages(hwnd);
1429 DestroyWindow(hwnd);
1430 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
1432 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1433 100, 100, 200, 200, 0, 0, 0, NULL);
1434 ok (hparent != 0, "Failed to create parent window\n");
1437 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
1438 0, 0, 10, 10, hparent, 0, 0, NULL);
1439 ok (hchild != 0, "Failed to create child window\n");
1440 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child");
1441 DestroyWindow(hchild);
1444 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1445 0, 0, 10, 10, hparent, 0, 0, NULL);
1446 ok (hchild != 0, "Failed to create child window\n");
1447 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child");
1449 trace("testing scroll APIs on a visible child window %p\n", hchild);
1450 test_scroll_messages(hchild);
1452 DestroyWindow(hchild);
1455 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
1456 0, 0, 10, 10, hparent, 0, 0, NULL);
1457 ok (hchild != 0, "Failed to create child window\n");
1458 ok_sequence(WmCreateChildSeq, "CreateWindow:child");
1460 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
1461 100, 100, 50, 50, hparent, 0, 0, NULL);
1462 ok (hchild2 != 0, "Failed to create child2 window\n");
1465 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
1466 0, 100, 50, 50, hchild, 0, 0, NULL);
1467 ok (hbutton != 0, "Failed to create button window\n");
1469 /* test WM_SETREDRAW on a not visible child window */
1470 test_WM_SETREDRAW(hchild);
1472 ShowWindow(hchild, SW_SHOW);
1473 ok_sequence(WmShowChildSeq, "ShowWindow:child");
1475 /* test WM_SETREDRAW on a visible child window */
1476 test_WM_SETREDRAW(hchild);
1478 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
1479 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
1481 ShowWindow(hchild, SW_HIDE);
1483 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1484 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2");
1486 ShowWindow(hchild, SW_HIDE);
1488 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
1489 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3");
1491 /* DestroyWindow sequence below expects that a child has focus */
1495 DestroyWindow(hchild);
1496 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
1497 DestroyWindow(hchild2);
1498 DestroyWindow(hbutton);
1501 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
1502 0, 0, 100, 100, hparent, 0, 0, NULL);
1503 ok (hchild != 0, "Failed to create child popup window\n");
1504 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup");
1505 DestroyWindow(hchild);
1507 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
1509 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
1510 0, 0, 100, 100, hparent, 0, 0, NULL);
1511 ok (hchild != 0, "Failed to create popup window\n");
1512 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
1513 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1514 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1516 ShowWindow(hchild, SW_SHOW);
1517 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup");
1519 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1520 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2");
1522 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1523 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3");
1524 DestroyWindow(hchild);
1526 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
1527 * changes nothing in message sequences.
1530 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
1531 0, 0, 100, 100, hparent, 0, 0, NULL);
1532 ok (hchild != 0, "Failed to create popup window\n");
1533 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
1534 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1535 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1537 ShowWindow(hchild, SW_SHOW);
1538 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup");
1540 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1541 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2");
1542 DestroyWindow(hchild);
1545 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
1546 0, 0, 100, 100, hparent, 0, 0, NULL);
1547 ok(hwnd != 0, "Failed to create custom dialog window\n");
1548 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog");
1550 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
1551 test_scroll_messages(hwnd);
1554 after_end_dialog = 1;
1555 EndDialog( hwnd, 0 );
1556 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog");
1558 DestroyWindow(hwnd);
1559 after_end_dialog = 0;
1562 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
1563 ok_sequence(WmModalDialogSeq, "ModalDialog");
1565 DestroyWindow(hparent);
1568 /* Message sequence for SetMenu */
1569 hmenu = CreateMenu();
1570 ok (hmenu != 0, "Failed to create menu\n");
1571 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
1572 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1573 100, 100, 200, 200, 0, hmenu, 0, NULL);
1574 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
1575 ok (SetMenu(hwnd, 0), "SetMenu\n");
1576 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");
1577 ok (SetMenu(hwnd, 0), "SetMenu\n");
1578 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");
1579 ShowWindow(hwnd, SW_SHOW);
1581 ok (SetMenu(hwnd, 0), "SetMenu\n");
1582 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");
1583 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
1584 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");
1586 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
1587 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar");
1589 DestroyWindow(hwnd);
1592 /* Message sequence for EnableWindow */
1593 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1594 100, 100, 200, 200, 0, 0, 0, NULL);
1595 ok (hparent != 0, "Failed to create parent window\n");
1596 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1597 0, 0, 10, 10, hparent, 0, 0, NULL);
1598 ok (hchild != 0, "Failed to create child window\n");
1603 EnableWindow(hparent, FALSE);
1604 ok_sequence(WmEnableWindowSeq, "EnableWindow");
1606 DestroyWindow(hparent);
1610 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1612 static long defwndproc_counter = 0;
1616 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1618 msg.message = message;
1619 msg.flags = sent|wparam|lparam;
1620 if (defwndproc_counter) msg.flags |= defwinproc;
1621 msg.wParam = wParam;
1622 msg.lParam = lParam;
1625 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
1627 HWND parent = GetParent(hwnd);
1629 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
1631 GetClientRect(parent, &rc);
1632 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
1634 trace("ptReserved = (%ld,%ld)\n"
1635 "ptMaxSize = (%ld,%ld)\n"
1636 "ptMaxPosition = (%ld,%ld)\n"
1637 "ptMinTrackSize = (%ld,%ld)\n"
1638 "ptMaxTrackSize = (%ld,%ld)\n",
1639 minmax->ptReserved.x, minmax->ptReserved.y,
1640 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
1641 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
1642 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
1643 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
1645 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
1646 minmax->ptMaxSize.x, rc.right);
1647 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
1648 minmax->ptMaxSize.y, rc.bottom);
1651 defwndproc_counter++;
1652 ret = DefWindowProcA(hwnd, message, wParam, lParam);
1653 defwndproc_counter--;
1658 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1660 static long defwndproc_counter = 0;
1664 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1666 msg.message = message;
1667 msg.flags = sent|wparam|lparam;
1668 if (defwndproc_counter) msg.flags |= defwinproc;
1669 msg.wParam = wParam;
1670 msg.lParam = lParam;
1673 if (message == WM_CREATE)
1675 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
1676 SetWindowLongA(hwnd, GWL_STYLE, style);
1679 defwndproc_counter++;
1680 ret = DefWindowProcA(hwnd, message, wParam, lParam);
1681 defwndproc_counter--;
1686 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1688 static long defwndproc_counter = 0;
1692 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1694 if (message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
1695 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
1696 message == WM_ENABLE || message == WM_ENTERIDLE ||
1697 message == WM_IME_SETCONTEXT)
1699 msg.message = message;
1700 msg.flags = sent|parent|wparam|lparam;
1701 if (defwndproc_counter) msg.flags |= defwinproc;
1702 msg.wParam = wParam;
1703 msg.lParam = lParam;
1707 defwndproc_counter++;
1708 ret = DefWindowProcA(hwnd, message, wParam, lParam);
1709 defwndproc_counter--;
1714 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1716 static long defwndproc_counter = 0;
1720 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1722 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
1723 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
1724 if (after_end_dialog)
1725 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
1727 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
1729 msg.message = message;
1730 msg.flags = sent|wparam|lparam;
1731 if (defwndproc_counter) msg.flags |= defwinproc;
1732 msg.wParam = wParam;
1733 msg.lParam = lParam;
1736 defwndproc_counter++;
1737 ret = DefDlgProcA(hwnd, message, wParam, lParam);
1738 defwndproc_counter--;
1743 static BOOL RegisterWindowClasses(void)
1748 cls.lpfnWndProc = MsgCheckProcA;
1751 cls.hInstance = GetModuleHandleA(0);
1753 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1754 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1755 cls.lpszMenuName = NULL;
1756 cls.lpszClassName = "TestWindowClass";
1757 if(!RegisterClassA(&cls)) return FALSE;
1759 cls.lpfnWndProc = PopupMsgCheckProcA;
1760 cls.lpszClassName = "TestPopupClass";
1761 if(!RegisterClassA(&cls)) return FALSE;
1763 cls.lpfnWndProc = ParentMsgCheckProcA;
1764 cls.lpszClassName = "TestParentClass";
1765 if(!RegisterClassA(&cls)) return FALSE;
1767 cls.lpfnWndProc = DefWindowProcA;
1768 cls.lpszClassName = "SimpleWindowClass";
1769 if(!RegisterClassA(&cls)) return FALSE;
1771 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
1772 cls.lpfnWndProc = TestDlgProcA;
1773 cls.lpszClassName = "TestDialogClass";
1774 if(!RegisterClassA(&cls)) return FALSE;
1779 static HHOOK hCBT_hook;
1781 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
1785 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
1787 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
1789 if (!strcmp(buf, "TestWindowClass") ||
1790 !strcmp(buf, "TestParentClass") ||
1791 !strcmp(buf, "TestPopupClass") ||
1792 !strcmp(buf, "SimpleWindowClass") ||
1793 !strcmp(buf, "TestDialogClass") ||
1794 !strcmp(buf, "MDI_frame_class") ||
1795 !strcmp(buf, "MDI_client_class") ||
1796 !strcmp(buf, "MDI_child_class") ||
1797 !strcmp(buf, "#32770"))
1801 msg.message = nCode;
1803 msg.wParam = wParam;
1804 msg.lParam = lParam;
1808 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
1813 if (!RegisterWindowClasses()) assert(0);
1815 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
1819 test_mdi_messages();
1821 UnhookWindowsHookEx(hCBT_hook);