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_IME_NOTIFY
, sent
|defwinproc
|optional
},
99 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
100 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
101 { WM_GETTEXT
, sent
|defwinproc
|optional
},
102 { WM_ERASEBKGND
, sent
|optional
},
103 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
104 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
105 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
106 { WM_ERASEBKGND
, sent
|optional
},
109 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
110 * for a visible overlapped window.
112 static const struct message WmSWP_HideOverlappedSeq
[] = {
113 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
114 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
117 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
118 static const struct message WmShowOverlappedSeq
[] = {
119 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
120 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
121 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
122 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
123 { WM_GETTEXT
, sent
|defwinproc
|optional
},
124 { WM_ERASEBKGND
, sent
|optional
},
125 { HCBT_ACTIVATE
, hook
},
126 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
127 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
128 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
129 { WM_NCACTIVATE
, sent
|wparam
, 1 },
130 { WM_GETTEXT
, sent
|defwinproc
|optional
},
131 { WM_ACTIVATE
, sent
|wparam
, 1 },
132 { HCBT_SETFOCUS
, hook
},
133 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
134 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
135 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
136 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
137 { WM_GETTEXT
, sent
|defwinproc
|optional
},
138 { WM_ERASEBKGND
, sent
|optional
},
139 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
140 { WM_NCCALCSIZE
, sent
|optional
},
141 { WM_NCPAINT
, sent
|optional
},
142 { WM_ERASEBKGND
, sent
|optional
},
143 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
144 * messages. Does that mean that CreateWindow doesn't set initial
145 * window dimensions for overlapped windows?
152 /* ShowWindow(SW_HIDE) for a visible overlapped window */
153 static const struct message WmHideOverlappedSeq
[] = {
154 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
155 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
156 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
159 { WM_NCACTIVATE
, sent
|wparam
, 0 },
160 { WM_ACTIVATE
, sent
|wparam
, 0 },
161 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
162 { WM_KILLFOCUS
, sent
|wparam
, 0 },
163 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
164 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
167 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
168 static const struct message WmHideInvisibleOverlappedSeq
[] = {
171 /* DestroyWindow for a visible overlapped window */
172 static const struct message WmDestroyOverlappedSeq
[] = {
173 { HCBT_DESTROYWND
, hook
},
174 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
175 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
176 { WM_NCACTIVATE
, sent
|wparam
, 0 },
177 { WM_ACTIVATE
, sent
|wparam
, 0 },
178 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
179 { WM_KILLFOCUS
, sent
|wparam
, 0 },
180 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
181 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
182 { WM_DESTROY
, sent
},
183 { WM_NCDESTROY
, sent
},
186 /* CreateWindow (for a child popup window, not initially visible) */
187 static const struct message WmCreateChildPopupSeq
[] = {
188 { HCBT_CREATEWND
, hook
},
189 { WM_NCCREATE
, sent
},
190 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
196 /* CreateWindow (for a popup window, not initially visible,
197 * which sets WS_VISIBLE in WM_CREATE handler)
199 static const struct message WmCreateInvisiblePopupSeq
[] = {
200 { HCBT_CREATEWND
, hook
},
201 { WM_NCCREATE
, sent
},
202 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
204 { WM_STYLECHANGING
, sent
},
205 { WM_STYLECHANGED
, sent
},
210 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
211 * for a popup window with WS_VISIBLE style set
213 static const struct message WmShowVisiblePopupSeq_2
[] = {
214 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
217 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
218 * for a popup window with WS_VISIBLE style set
220 static const struct message WmShowVisiblePopupSeq_3
[] = {
221 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
222 { HCBT_ACTIVATE
, hook
},
223 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
224 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
225 { WM_NCACTIVATE
, sent
|wparam
, 1 },
226 { WM_ACTIVATE
, sent
|wparam
, 1 },
227 { HCBT_SETFOCUS
, hook
},
228 { WM_KILLFOCUS
, sent
|parent
},
229 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
230 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
231 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
232 { WM_SETFOCUS
, sent
|defwinproc
},
235 /* CreateWindow (for child window, not initially visible) */
236 static const struct message WmCreateChildSeq
[] = {
237 { HCBT_CREATEWND
, hook
},
238 { WM_NCCREATE
, sent
},
239 /* child is inserted into parent's child list after WM_NCCREATE returns */
240 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
244 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
247 /* CreateWindow (for maximized child window, not initially visible) */
248 static const struct message WmCreateMaximizedChildSeq
[] = {
249 { HCBT_CREATEWND
, hook
},
250 { WM_NCCREATE
, sent
},
251 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
255 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
256 { WM_GETMINMAXINFO
, sent
},
257 { WM_WINDOWPOSCHANGING
, sent
},
258 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
259 { WM_WINDOWPOSCHANGED
, sent
},
260 { WM_SIZE
, sent
|defwinproc
},
261 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
264 /* CreateWindow (for a child window, initially visible) */
265 static const struct message WmCreateVisibleChildSeq
[] = {
266 { HCBT_CREATEWND
, hook
},
267 { WM_NCCREATE
, sent
},
268 /* child is inserted into parent's child list after WM_NCCREATE returns */
269 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
273 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
274 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
275 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
276 { WM_ERASEBKGND
, sent
|parent
|optional
},
277 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
280 /* ShowWindow(SW_SHOW) for a not visible child window */
281 static const struct message WmShowChildSeq
[] = {
282 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
283 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
284 { WM_ERASEBKGND
, sent
|parent
|optional
},
285 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
288 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
289 * for a not visible child window
291 static const struct message WmShowChildSeq_2
[] = {
292 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
293 { WM_CHILDACTIVATE
, sent
},
294 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
297 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
298 * for a not visible child window
300 static const struct message WmShowChildSeq_3
[] = {
301 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
302 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
305 /* ShowWindow(SW_SHOW) for child with invisible parent */
306 static const struct message WmShowChildInvisibleParentSeq
[] = {
307 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
310 /* ShowWindow(SW_HIDE) for child with invisible parent */
311 static const struct message WmHideChildInvisibleParentSeq
[] = {
312 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
315 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
316 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
317 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
318 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
321 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
322 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
323 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
324 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
327 /* DestroyWindow for a visible child window */
328 static const struct message WmDestroyChildSeq
[] = {
329 { HCBT_DESTROYWND
, hook
},
330 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
331 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
332 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
333 { WM_ERASEBKGND
, sent
|parent
|optional
},
334 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
335 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
336 { WM_KILLFOCUS
, sent
},
337 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
338 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
339 { WM_SETFOCUS
, sent
|parent
},
340 { WM_DESTROY
, sent
},
341 { WM_DESTROY
, sent
|optional
}, /* a bug in win2k sp4 ? */
342 { WM_NCDESTROY
, sent
},
343 { WM_NCDESTROY
, sent
|optional
}, /* a bug in win2k sp4 ? */
346 /* Moving the mouse in nonclient area */
347 static const struct message WmMouseMoveInNonClientAreaSeq
[] = { /* FIXME: add */
348 { WM_NCHITTEST
, sent
},
349 { WM_SETCURSOR
, sent
},
350 { WM_NCMOUSEMOVE
, posted
},
353 /* Moving the mouse in client area */
354 static const struct message WmMouseMoveInClientAreaSeq
[] = { /* FIXME: add */
355 { WM_NCHITTEST
, sent
},
356 { WM_SETCURSOR
, sent
},
357 { WM_MOUSEMOVE
, posted
},
360 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
361 static const struct message WmDragTitleBarSeq
[] = { /* FIXME: add */
362 { WM_NCLBUTTONDOWN
, sent
|wparam
, HTCAPTION
},
363 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_MOVE
+2 },
364 { WM_GETMINMAXINFO
, sent
|defwinproc
},
365 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
366 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
367 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
368 { WM_MOVE
, sent
|defwinproc
},
369 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
372 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
373 static const struct message WmDragThickBordersBarSeq
[] = { /* FIXME: add */
374 { WM_NCLBUTTONDOWN
, sent
|wparam
, 0xd },
375 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, 0xf004 },
376 { WM_GETMINMAXINFO
, sent
|defwinproc
},
377 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
378 { WM_SIZING
, sent
|defwinproc
|wparam
, 4}, /* one for each mouse movement */
379 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
380 { WM_GETMINMAXINFO
, sent
|defwinproc
},
381 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
382 { WM_NCPAINT
, sent
|defwinproc
|wparam
, 1 },
383 { WM_GETTEXT
, sent
|defwinproc
},
384 { WM_ERASEBKGND
, sent
|defwinproc
},
385 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
386 { WM_MOVE
, sent
|defwinproc
},
387 { WM_SIZE
, sent
|defwinproc
},
388 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
391 /* Resizing child window with MoveWindow (32) */
392 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
393 { WM_WINDOWPOSCHANGING
, sent
},
394 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
395 { WM_ERASEBKGND
, sent
|optional
},
396 { WM_WINDOWPOSCHANGED
, sent
},
397 { WM_MOVE
, sent
|defwinproc
},
398 { WM_SIZE
, sent
|defwinproc
},
401 /* Clicking on inactive button */
402 static const struct message WmClickInactiveButtonSeq
[] = { /* FIXME: add */
403 { WM_NCHITTEST
, sent
},
404 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_LBUTTONDOWN
},
405 { WM_MOUSEACTIVATE
, sent
},
406 { WM_MOUSEACTIVATE
, sent
|parent
|defwinproc
},
407 { WM_SETCURSOR
, sent
},
408 { WM_SETCURSOR
, sent
|parent
|defwinproc
},
409 { WM_LBUTTONDOWN
, posted
},
410 { WM_KILLFOCUS
, posted
|parent
},
411 { WM_SETFOCUS
, posted
},
412 { WM_CTLCOLORBTN
, posted
|parent
},
413 { BM_SETSTATE
, posted
},
414 { WM_CTLCOLORBTN
, posted
|parent
},
415 { WM_LBUTTONUP
, posted
},
416 { BM_SETSTATE
, posted
},
417 { WM_CTLCOLORBTN
, posted
|parent
},
418 { WM_COMMAND
, posted
|parent
},
421 /* Reparenting a button (16/32) */
422 /* The last child (button) reparented gets topmost for its new parent. */
423 static const struct message WmReparentButtonSeq
[] = { /* FIXME: add */
424 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
425 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
426 { WM_ERASEBKGND
, sent
|parent
},
427 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
428 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOZORDER
},
429 { WM_CHILDACTIVATE
, sent
},
430 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOZORDER
},
431 { WM_MOVE
, sent
|defwinproc
},
432 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
435 /* Creation of a custom dialog (32) */
436 static const struct message WmCreateCustomDialogSeq
[] = {
437 { HCBT_CREATEWND
, hook
},
438 { WM_GETMINMAXINFO
, sent
},
439 { WM_NCCREATE
, sent
},
440 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
442 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
443 { HCBT_ACTIVATE
, hook
},
444 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
445 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
446 { WM_NCACTIVATE
, sent
|wparam
, 1 },
447 { WM_GETTEXT
, sent
|optional
|defwinproc
},
448 { WM_GETICON
, sent
|optional
|defwinproc
},
449 { WM_GETICON
, sent
|optional
|defwinproc
},
450 { WM_GETICON
, sent
|optional
|defwinproc
},
451 { WM_GETTEXT
, sent
|optional
|defwinproc
},
452 { WM_ACTIVATE
, sent
|wparam
, 1 },
453 { WM_KILLFOCUS
, sent
|parent
},
454 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
455 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
456 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
457 { WM_SETFOCUS
, sent
},
458 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
459 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
460 { WM_NCPAINT
, sent
|wparam
, 1 },
461 { WM_GETTEXT
, sent
|optional
|defwinproc
},
462 { WM_GETICON
, sent
|optional
|defwinproc
},
463 { WM_GETICON
, sent
|optional
|defwinproc
},
464 { WM_GETICON
, sent
|optional
|defwinproc
},
465 { WM_GETTEXT
, sent
|optional
|defwinproc
},
466 { WM_ERASEBKGND
, sent
},
467 { WM_CTLCOLORDLG
, sent
|defwinproc
},
468 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
469 { WM_GETTEXT
, sent
|optional
},
470 { WM_GETICON
, sent
|optional
},
471 { WM_GETICON
, sent
|optional
},
472 { WM_GETICON
, sent
|optional
},
473 { WM_GETTEXT
, sent
|optional
},
474 { WM_NCCALCSIZE
, sent
|optional
},
475 { WM_NCPAINT
, sent
|optional
},
476 { WM_GETTEXT
, sent
|optional
|defwinproc
},
477 { WM_GETICON
, sent
|optional
|defwinproc
},
478 { WM_GETICON
, sent
|optional
|defwinproc
},
479 { WM_GETICON
, sent
|optional
|defwinproc
},
480 { WM_GETTEXT
, sent
|optional
|defwinproc
},
481 { WM_ERASEBKGND
, sent
|optional
},
482 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
487 /* Calling EndDialog for a custom dialog (32) */
488 static const struct message WmEndCustomDialogSeq
[] = {
489 { WM_WINDOWPOSCHANGING
, sent
},
490 { WM_WINDOWPOSCHANGED
, sent
},
491 { WM_GETTEXT
, sent
|optional
},
492 { WM_GETICON
, sent
|optional
},
493 { WM_GETICON
, sent
|optional
},
494 { WM_GETICON
, sent
|optional
},
495 { HCBT_ACTIVATE
, hook
},
496 { WM_NCACTIVATE
, sent
|wparam
, 0 },
497 { WM_GETTEXT
, sent
|optional
|defwinproc
},
498 { WM_GETICON
, sent
|optional
|defwinproc
},
499 { WM_GETICON
, sent
|optional
|defwinproc
},
500 { WM_GETICON
, sent
|optional
|defwinproc
},
501 { WM_GETTEXT
, sent
|optional
|defwinproc
},
502 { WM_ACTIVATE
, sent
|wparam
, 0 },
503 { WM_WINDOWPOSCHANGING
, sent
|optional
},
504 { HCBT_SETFOCUS
, hook
},
505 { WM_KILLFOCUS
, sent
},
506 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
507 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
508 { WM_IME_NOTIFY
, sent
|optional
},
509 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
512 /* Creation and destruction of a modal dialog (32) */
513 static const struct message WmModalDialogSeq
[] = {
514 { WM_CANCELMODE
, sent
|parent
},
515 { HCBT_SETFOCUS
, hook
},
516 { WM_KILLFOCUS
, sent
|parent
},
517 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
518 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
519 { HCBT_CREATEWND
, hook
},
520 { WM_SETFONT
, sent
},
521 { WM_INITDIALOG
, sent
},
522 { WM_CHANGEUISTATE
, sent
|optional
},
523 { WM_SHOWWINDOW
, sent
},
524 { HCBT_ACTIVATE
, hook
},
525 { WM_WINDOWPOSCHANGING
, sent
},
526 { WM_NCACTIVATE
, sent
|wparam
, 1 },
527 { WM_GETICON
, sent
|optional
},
528 { WM_GETICON
, sent
|optional
},
529 { WM_GETICON
, sent
|optional
},
530 { WM_GETTEXT
, sent
|optional
},
531 { WM_ACTIVATE
, sent
|wparam
, 1 },
532 { WM_WINDOWPOSCHANGING
, sent
},
533 { WM_NCPAINT
, sent
},
534 { WM_GETICON
, sent
|optional
},
535 { WM_GETICON
, sent
|optional
},
536 { WM_GETICON
, sent
|optional
},
537 { WM_GETTEXT
, sent
|optional
},
538 { WM_ERASEBKGND
, sent
},
539 { WM_CTLCOLORDLG
, sent
},
540 { WM_WINDOWPOSCHANGED
, sent
},
541 { WM_GETICON
, sent
|optional
},
542 { WM_GETICON
, sent
|optional
},
543 { WM_GETICON
, sent
|optional
},
544 { WM_GETTEXT
, sent
|optional
},
545 { WM_NCCALCSIZE
, sent
|optional
},
546 { WM_NCPAINT
, sent
|optional
},
547 { WM_GETICON
, sent
|optional
},
548 { WM_GETICON
, sent
|optional
},
549 { WM_GETICON
, sent
|optional
},
550 { WM_GETTEXT
, sent
|optional
},
551 { WM_ERASEBKGND
, sent
|optional
},
552 { WM_CTLCOLORDLG
, sent
|optional
},
553 { WM_PAINT
, sent
|optional
},
554 { WM_CTLCOLORBTN
, sent
},
555 { WM_ENTERIDLE
, sent
|parent
|optional
},
557 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
558 { WM_WINDOWPOSCHANGING
, sent
},
559 { WM_WINDOWPOSCHANGED
, sent
},
560 { WM_GETICON
, sent
|optional
},
561 { WM_GETICON
, sent
|optional
},
562 { WM_GETICON
, sent
|optional
},
563 { WM_GETTEXT
, sent
|optional
},
564 { HCBT_ACTIVATE
, hook
},
565 { WM_NCACTIVATE
, sent
|wparam
, 0 },
566 { WM_GETICON
, sent
|optional
},
567 { WM_GETICON
, sent
|optional
},
568 { WM_GETICON
, sent
|optional
},
569 { WM_GETTEXT
, sent
|optional
},
570 { WM_ACTIVATE
, sent
|wparam
, 0 },
571 { WM_WINDOWPOSCHANGING
, sent
|optional
},
572 { HCBT_SETFOCUS
, hook
},
573 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
574 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
575 { HCBT_DESTROYWND
, hook
},
576 { WM_DESTROY
, sent
},
577 { WM_NCDESTROY
, sent
},
580 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
581 static const struct message WmCreateModalDialogResizeSeq
[] = { /* FIXME: add */
582 /* (inside dialog proc, handling WM_INITDIALOG) */
583 { WM_WINDOWPOSCHANGING
, sent
},
584 { WM_NCCALCSIZE
, sent
},
585 { WM_NCACTIVATE
, sent
|parent
|wparam
, 0 },
586 { WM_GETTEXT
, sent
|defwinproc
},
587 { WM_ACTIVATE
, sent
|parent
|wparam
, 0 },
588 { WM_WINDOWPOSCHANGING
, sent
},
589 { WM_WINDOWPOSCHANGING
, sent
|parent
},
590 { WM_NCACTIVATE
, sent
|wparam
, 1 },
591 { WM_ACTIVATE
, sent
|wparam
, 1 },
592 { WM_WINDOWPOSCHANGED
, sent
},
593 { WM_SIZE
, sent
|defwinproc
},
594 /* (setting focus) */
595 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
596 { WM_WINDOWPOSCHANGING
, sent
},
597 { WM_NCPAINT
, sent
},
598 { WM_GETTEXT
, sent
|defwinproc
},
599 { WM_ERASEBKGND
, sent
},
600 { WM_CTLCOLORDLG
, sent
|defwinproc
},
601 { WM_WINDOWPOSCHANGED
, sent
},
603 /* (bunch of WM_CTLCOLOR* for each control) */
604 { WM_PAINT
, sent
|parent
},
605 { WM_ENTERIDLE
, sent
|parent
|wparam
, 0 },
606 { WM_SETCURSOR
, sent
|parent
},
609 /* SetMenu for NonVisible windows with size change*/
610 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
611 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
612 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
613 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
614 { WM_MOVE
, sent
|defwinproc
},
615 { WM_SIZE
, sent
|defwinproc
},
616 { WM_GETICON
, sent
|optional
},
617 { WM_GETICON
, sent
|optional
},
618 { WM_GETICON
, sent
|optional
},
619 { WM_GETTEXT
, sent
|optional
},
620 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
623 /* SetMenu for NonVisible windows with no size change */
624 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
625 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
626 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
627 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
630 /* SetMenu for Visible windows with size change */
631 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
632 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
633 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
634 { WM_NCPAINT
, sent
|wparam
, 1 },
635 { WM_GETTEXT
, sent
|defwinproc
|optional
},
636 { WM_ERASEBKGND
, sent
|optional
},
637 { WM_ACTIVATE
, sent
|optional
},
638 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
639 { WM_MOVE
, sent
|defwinproc
},
640 { WM_SIZE
, sent
|defwinproc
},
641 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
642 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
643 { WM_ERASEBKGND
, sent
|optional
},
646 /* SetMenu for Visible windows with no size change */
647 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
648 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
649 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
650 { WM_NCPAINT
, sent
|wparam
, 1 },
651 { WM_GETTEXT
, sent
|defwinproc
|optional
},
652 { WM_ERASEBKGND
, sent
|optional
},
653 { WM_ACTIVATE
, sent
|optional
},
654 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
657 /* DrawMenuBar for a visible window */
658 static const struct message WmDrawMenuBarSeq
[] =
660 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
661 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
662 { WM_NCPAINT
, sent
|wparam
, 1 },
663 { WM_GETTEXT
, sent
|defwinproc
|optional
},
664 { WM_ERASEBKGND
, sent
|optional
},
665 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
669 static const struct message WmSetRedrawFalseSeq
[] =
671 { WM_SETREDRAW
, sent
|wparam
, 0 },
675 static const struct message WmSetRedrawTrueSeq
[] =
677 { WM_SETREDRAW
, sent
|wparam
, 1 },
681 static const struct message WmEnableWindowSeq
[] =
683 { WM_CANCELMODE
, sent
},
688 static const struct message WmGetScrollRangeSeq
[] =
690 { SBM_GETRANGE
, sent
},
693 static const struct message WmGetScrollInfoSeq
[] =
695 { SBM_GETSCROLLINFO
, sent
},
698 static const struct message WmSetScrollRangeSeq
[] =
700 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
701 sends SBM_SETSCROLLINFO.
703 { SBM_SETSCROLLINFO
, sent
},
706 /* SetScrollRange for a window without a non-client area */
707 static const struct message WmSetScrollRangeHVSeq
[] =
709 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
710 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
711 { WM_GETTEXT
, sent
|defwinproc
|optional
},
712 { WM_ERASEBKGND
, sent
|optional
},
713 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
716 /* SetScrollRange for a window with a non-client area */
717 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
719 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
720 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
721 { WM_NCPAINT
, sent
|optional
},
722 { WM_GETTEXT
, sent
|defwinproc
|optional
},
723 { WM_GETICON
, sent
|optional
|defwinproc
},
724 { WM_GETICON
, sent
|optional
|defwinproc
},
725 { WM_GETICON
, sent
|optional
|defwinproc
},
726 { WM_GETTEXT
, sent
|defwinproc
|optional
},
727 { WM_ERASEBKGND
, sent
|optional
},
728 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
729 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
730 { WM_SIZE
, sent
|defwinproc
},
731 { WM_GETTEXT
, sent
|optional
},
732 { WM_GETICON
, sent
|optional
},
733 { WM_GETICON
, sent
|optional
},
734 { WM_GETICON
, sent
|optional
},
735 { WM_GETTEXT
, sent
|optional
},
736 { WM_GETICON
, sent
|optional
},
737 { WM_GETICON
, sent
|optional
},
738 { WM_GETICON
, sent
|optional
},
739 { WM_GETTEXT
, sent
|optional
},
740 { WM_GETICON
, sent
|optional
},
741 { WM_GETICON
, sent
|optional
},
742 { WM_GETICON
, sent
|optional
},
743 { WM_GETTEXT
, sent
|optional
},
747 static int after_end_dialog
;
748 static int sequence_cnt
, sequence_size
;
749 static struct message
* sequence
;
751 static void add_message(const struct message
*msg
)
756 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof (struct message
) );
758 if (sequence_cnt
== sequence_size
)
761 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof (struct message
) );
765 sequence
[sequence_cnt
].message
= msg
->message
;
766 sequence
[sequence_cnt
].flags
= msg
->flags
;
767 sequence
[sequence_cnt
].wParam
= msg
->wParam
;
768 sequence
[sequence_cnt
].lParam
= msg
->lParam
;
773 static void flush_sequence()
775 HeapFree(GetProcessHeap(), 0, sequence
);
777 sequence_cnt
= sequence_size
= 0;
780 static void ok_sequence(const struct message
*expected
, const char *context
, int todo
)
782 static const struct message end_of_sequence
= { 0, 0, 0, 0 };
783 const struct message
*actual
;
785 add_message(&end_of_sequence
);
789 while (expected
->message
&& actual
->message
)
791 trace("expected %04x - actual %04x\n", expected
->message
, actual
->message
);
793 if (expected
->message
== actual
->message
)
795 if (expected
->flags
& wparam
)
796 ok (expected
->wParam
== actual
->wParam
,
797 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
798 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
799 if (expected
->flags
& lparam
)
800 ok (expected
->lParam
== actual
->lParam
,
801 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
802 context
, expected
->message
, expected
->lParam
, actual
->lParam
);
803 ok ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
804 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
805 context
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
806 ok ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
807 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
808 context
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
809 ok ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
810 "%s: the msg 0x%04x should have been %s\n",
811 context
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
812 ok ((expected
->flags
& parent
) == (actual
->flags
& parent
),
813 "%s: the msg 0x%04x was expected in %s\n",
814 context
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
815 ok ((expected
->flags
& hook
) == (actual
->flags
& hook
),
816 "%s: the msg 0x%04x should have been sent by a hook\n",
817 context
, expected
->message
);
821 else if (expected
->flags
& optional
)
826 ok (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
827 context
, expected
->message
, actual
->message
);
834 ok (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
835 context
, expected
->message
, actual
->message
);
841 /* skip all optional trailing messages */
842 while (expected
->message
&& (expected
->flags
& optional
))
848 if (expected
->message
|| actual
->message
)
849 ok (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
850 context
, expected
->message
, actual
->message
);
855 if (expected
->message
|| actual
->message
)
856 ok (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
857 context
, expected
->message
, actual
->message
);
863 /******************************** MDI test **********************************/
865 /* CreateWindow for MDI frame window, initially visible */
866 static const struct message WmCreateMDIframeSeq
[] = {
867 { HCBT_CREATEWND
, hook
},
868 { WM_GETMINMAXINFO
, sent
},
869 { WM_NCCREATE
, sent
},
870 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
872 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
873 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
874 { HCBT_ACTIVATE
, hook
},
875 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
876 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
877 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, 0 }, /* Win9x */
878 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
879 { WM_NCACTIVATE
, sent
|wparam
, 1 },
880 { WM_ACTIVATE
, sent
|wparam
, 1 },
881 { HCBT_SETFOCUS
, hook
},
882 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
883 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
884 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
889 /* DestroyWindow for MDI frame window, initially visible */
890 static const struct message WmDestroyMDIframeSeq
[] = {
891 { HCBT_DESTROYWND
, hook
},
892 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
893 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
894 { WM_NCACTIVATE
, sent
|wparam
, 0 },
895 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
896 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
897 { WM_DESTROY
, sent
},
898 { WM_NCDESTROY
, sent
},
901 /* CreateWindow for MDI client window, initially visible */
902 static const struct message WmCreateMDIclientSeq
[] = {
903 { HCBT_CREATEWND
, hook
},
904 { WM_NCCREATE
, sent
},
905 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
909 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
910 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
911 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
912 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
915 /* DestroyWindow for MDI client window, initially visible */
916 static const struct message WmDestroyMDIclientSeq
[] = {
917 { HCBT_DESTROYWND
, hook
},
918 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
919 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
920 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
921 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
922 { WM_DESTROY
, sent
},
923 { WM_NCDESTROY
, sent
},
926 /* CreateWindow for MDI child window, initially visible */
927 static const struct message WmCreateMDIchildVisibleSeq
[] = {
928 { HCBT_CREATEWND
, hook
},
929 { WM_NCCREATE
, sent
},
930 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
934 /* Win2k sends wparam set to
935 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
936 * while Win9x doesn't bother to set child window id according to
937 * CLIENTCREATESTRUCT.idFirstChild
939 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
940 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
941 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 }, /*SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
942 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
943 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
944 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 }, /*SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE*/
945 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
946 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 }, /*SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/
948 /* Win9x: message sequence terminates here. */
950 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
951 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
952 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
953 { WM_SETFOCUS
, sent
}, /* in MDI client */
954 { HCBT_SETFOCUS
, hook
},
955 { WM_KILLFOCUS
, sent
}, /* in MDI client */
956 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
957 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
958 { WM_SETFOCUS
, sent
|defwinproc
},
959 { WM_MDIACTIVATE
, sent
|defwinproc
},
962 /* DestroyWindow for MDI child window, initially visible */
963 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
964 { HCBT_DESTROYWND
, hook
},
965 /* Win2k sends wparam set to
966 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
967 * while Win9x doesn't bother to set child window id according to
968 * CLIENTCREATESTRUCT.idFirstChild
970 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
971 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
972 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 }, /*SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
973 { WM_ERASEBKGND
, sent
|parent
|optional
},
974 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
976 /* { WM_DESTROY, sent }
977 * Win9x: message sequence terminates here.
980 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
981 { WM_KILLFOCUS
, sent
},
982 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
983 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
984 { WM_SETFOCUS
, sent
}, /* in MDI client */
986 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
987 { WM_KILLFOCUS
, sent
}, /* in MDI client */
988 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
989 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
990 { WM_SETFOCUS
, sent
}, /* in MDI client */
992 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
993 { WM_KILLFOCUS
, sent
},
994 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
995 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
996 { WM_SETFOCUS
, sent
}, /* in MDI client */
998 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
999 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1000 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1001 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1002 { WM_SETFOCUS
, sent
}, /* in MDI client */
1004 { WM_DESTROY
, sent
},
1006 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1007 { WM_KILLFOCUS
, sent
},
1008 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1009 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1010 { WM_SETFOCUS
, sent
}, /* in MDI client */
1012 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1013 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1014 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1015 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1016 { WM_SETFOCUS
, sent
}, /* in MDI client */
1018 { WM_NCDESTROY
, sent
},
1021 /* CreateWindow for MDI child window, initially invisible */
1022 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
1023 { HCBT_CREATEWND
, hook
},
1024 { WM_NCCREATE
, sent
},
1025 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1026 { WM_CREATE
, sent
},
1029 /* Win2k sends wparam set to
1030 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1031 * while Win9x doesn't bother to set child window id according to
1032 * CLIENTCREATESTRUCT.idFirstChild
1034 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1037 /* DestroyWindow for MDI child window, initially invisible */
1038 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
1039 { HCBT_DESTROYWND
, hook
},
1040 /* Win2k sends wparam set to
1041 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1042 * while Win9x doesn't bother to set child window id according to
1043 * CLIENTCREATESTRUCT.idFirstChild
1045 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1046 { WM_DESTROY
, sent
},
1047 { WM_NCDESTROY
, sent
},
1051 static HWND mdi_client
;
1052 static WNDPROC old_mdi_client_proc
;
1054 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1058 /* do not log painting messages */
1059 if (message
!= WM_PAINT
&&
1060 message
!= WM_ERASEBKGND
&&
1061 message
!= WM_NCPAINT
&&
1062 message
!= WM_GETTEXT
)
1064 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1066 msg
.message
= message
;
1067 msg
.flags
= sent
|wparam
|lparam
;
1068 msg
.wParam
= wParam
;
1069 msg
.lParam
= lParam
;
1073 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
1076 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1078 static long defwndproc_counter
= 0;
1082 /* do not log painting messages */
1083 if (message
!= WM_PAINT
&&
1084 message
!= WM_ERASEBKGND
&&
1085 message
!= WM_NCPAINT
&&
1086 message
!= WM_GETTEXT
)
1088 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1092 case WM_WINDOWPOSCHANGING
:
1093 case WM_WINDOWPOSCHANGED
:
1095 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1097 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1098 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1099 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1100 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1105 msg
.message
= message
;
1106 msg
.flags
= sent
|wparam
|lparam
;
1107 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1108 msg
.wParam
= wParam
;
1109 msg
.lParam
= lParam
;
1113 defwndproc_counter
++;
1114 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
1115 defwndproc_counter
--;
1120 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1122 static long defwndproc_counter
= 0;
1126 /* do not log painting messages */
1127 if (message
!= WM_PAINT
&&
1128 message
!= WM_ERASEBKGND
&&
1129 message
!= WM_NCPAINT
&&
1130 message
!= WM_GETTEXT
)
1132 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1134 msg
.message
= message
;
1135 msg
.flags
= sent
|wparam
|lparam
;
1136 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1137 msg
.wParam
= wParam
;
1138 msg
.lParam
= lParam
;
1142 defwndproc_counter
++;
1143 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
1144 defwndproc_counter
--;
1149 static BOOL
mdi_RegisterWindowClasses(void)
1154 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
1157 cls
.hInstance
= GetModuleHandleA(0);
1159 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
1160 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
1161 cls
.lpszMenuName
= NULL
;
1162 cls
.lpszClassName
= "MDI_frame_class";
1163 if (!RegisterClassA(&cls
)) return FALSE
;
1165 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
1166 cls
.lpszClassName
= "MDI_child_class";
1167 if (!RegisterClassA(&cls
)) return FALSE
;
1169 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
1170 old_mdi_client_proc
= cls
.lpfnWndProc
;
1171 cls
.hInstance
= GetModuleHandleA(0);
1172 cls
.lpfnWndProc
= mdi_client_hook_proc
;
1173 cls
.lpszClassName
= "MDI_client_class";
1174 if (!RegisterClassA(&cls
)) assert(0);
1179 static void test_mdi_messages(void)
1181 CLIENTCREATESTRUCT client_cs
;
1182 HWND mdi_frame
, mdi_child
;
1184 assert(mdi_RegisterWindowClasses());
1188 trace("creating MDI frame window\n");
1189 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1190 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
1191 WS_MAXIMIZEBOX
| WS_VISIBLE
,
1192 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
1193 GetDesktopWindow(), 0,
1194 GetModuleHandleA(0), NULL
);
1196 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", TRUE
);
1198 trace("creating MDI client window\n");
1199 client_cs
.hWindowMenu
= 0;
1200 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
1201 mdi_client
= CreateWindowExA(0, "MDI_client_class",
1203 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
1205 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
1207 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", TRUE
);
1209 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
1214 trace("creating visible MDI child window\n");
1215 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1216 WS_CHILD
| WS_VISIBLE
,
1217 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1218 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1220 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", TRUE
);
1222 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1223 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
1225 DestroyWindow(mdi_child
);
1226 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
1231 trace("creating invisible MDI child window\n");
1232 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1234 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1235 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1237 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", TRUE
);
1239 ok(!(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
1240 ok(!IsWindowVisible(mdi_child
), "MDI child should not be visible\n");
1242 DestroyWindow(mdi_child
);
1243 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", TRUE
);
1245 DestroyWindow(mdi_client
);
1246 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
1248 DestroyWindow(mdi_frame
);
1249 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
1251 /************************* End of MDI test **********************************/
1253 static void test_WM_SETREDRAW(HWND hwnd
)
1255 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1259 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
1260 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
1262 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
1263 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
1266 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
1267 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
1269 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
1270 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
1272 /* restore original WS_VISIBLE state */
1273 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
1278 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1282 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1284 msg
.message
= message
;
1285 msg
.flags
= sent
|wparam
|lparam
;
1286 msg
.wParam
= wParam
;
1287 msg
.lParam
= lParam
;
1290 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
1291 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
1295 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
1297 DWORD style
, exstyle
;
1300 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1301 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1302 /* do not be confused by WS_DLGFRAME set */
1303 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
1305 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
1306 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
1308 ok(SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
), "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
1309 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
1310 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
1312 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", TRUE
);
1314 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1315 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
1316 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
1318 /* a subsequent call should do nothing */
1319 ok(SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
), "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
1320 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
1324 trace("Ignore GetScrollRange error below if you are on Win9x\n");
1325 ok(GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
), "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
1326 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
1327 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
1328 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
1331 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
1333 DWORD style
, exstyle
;
1336 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1337 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1338 /* do not be confused by WS_DLGFRAME set */
1339 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
1341 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
1342 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
1344 si
.cbSize
= sizeof(si
);
1345 si
.fMask
= SIF_RANGE
;
1348 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
1349 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
1350 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
1352 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", TRUE
);
1354 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1355 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
1356 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
1358 /* a subsequent call should do nothing */
1359 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
1360 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
1362 si
.fMask
= SIF_PAGE
;
1364 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
1365 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
1369 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
1370 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
1372 si
.fMask
= SIF_RANGE
;
1373 si
.nMin
= 0xdeadbeef;
1374 si
.nMax
= 0xdeadbeef;
1375 ok(GetScrollInfo(hwnd
, ctl
, &si
), "GetScrollInfo error %ld\n", GetLastError());
1376 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
1377 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
1378 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
1381 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
1382 static void test_scroll_messages(HWND hwnd
)
1389 ok(GetScrollRange(hwnd
, SB_CTL
, &min
, &max
), "GetScrollRange error %ld\n", GetLastError());
1390 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
1391 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1392 /* values of min and max are undefined */
1395 ok(SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
), "SetScrollRange error %ld\n", GetLastError());
1396 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1397 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1402 ok(GetScrollRange(hwnd
, SB_CTL
, &min
, &max
), "GetScrollRange error %ld\n", GetLastError());
1403 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
1404 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1405 /* values of min and max are undefined */
1408 si
.cbSize
= sizeof(si
);
1409 si
.fMask
= SIF_RANGE
;
1412 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
1413 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1414 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1417 si
.fMask
= SIF_PAGE
;
1419 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
1420 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1421 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1426 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
1427 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1428 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1431 si
.fMask
= SIF_RANGE
;
1432 si
.nMin
= 0xdeadbeef;
1433 si
.nMax
= 0xdeadbeef;
1434 ok(GetScrollInfo(hwnd
, SB_CTL
, &si
), "GetScrollInfo error %ld\n", GetLastError());
1435 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
1436 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1437 /* values of min and max are undefined */
1440 /* set WS_HSCROLL */
1441 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
1442 /* clear WS_HSCROLL */
1443 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
1445 /* set WS_HSCROLL */
1446 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
1447 /* clear WS_HSCROLL */
1448 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
1450 /* set WS_VSCROLL */
1451 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
1452 /* clear WS_VSCROLL */
1453 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
1455 /* set WS_VSCROLL */
1456 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
1457 /* clear WS_VSCROLL */
1458 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
1461 /* test if we receive the right sequence of messages */
1462 static void test_messages(void)
1464 HWND hwnd
, hparent
, hchild
;
1465 HWND hchild2
, hbutton
;
1468 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
1469 100, 100, 200, 200, 0, 0, 0, NULL
);
1470 ok (hwnd
!= 0, "Failed to create overlapped window\n");
1471 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
1473 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
1474 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
1475 ok_sequence(WmHideInvisibleOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
1477 /* test WM_SETREDRAW on a not visible top level window */
1478 test_WM_SETREDRAW(hwnd
);
1480 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1481 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
1482 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
1484 ok(GetActiveWindow() == hwnd
, "window should be active\n");
1485 ok(GetFocus() == hwnd
, "window should have input focus\n");
1486 ShowWindow(hwnd
, SW_HIDE
);
1487 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", TRUE
);
1489 ShowWindow(hwnd
, SW_SHOW
);
1490 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
1492 ok(GetActiveWindow() == hwnd
, "window should be active\n");
1493 ok(GetFocus() == hwnd
, "window should have input focus\n");
1494 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1495 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
1496 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
1498 /* test WM_SETREDRAW on a visible top level window */
1499 ShowWindow(hwnd
, SW_SHOW
);
1500 test_WM_SETREDRAW(hwnd
);
1502 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
1503 test_scroll_messages(hwnd
);
1505 DestroyWindow(hwnd
);
1506 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
1508 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
1509 100, 100, 200, 200, 0, 0, 0, NULL
);
1510 ok (hparent
!= 0, "Failed to create parent window\n");
1513 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
1514 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1515 ok (hchild
!= 0, "Failed to create child window\n");
1516 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
1517 DestroyWindow(hchild
);
1520 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
1521 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1522 ok (hchild
!= 0, "Failed to create child window\n");
1523 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
1525 trace("testing scroll APIs on a visible child window %p\n", hchild
);
1526 test_scroll_messages(hchild
);
1528 DestroyWindow(hchild
);
1531 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
1532 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1533 ok (hchild
!= 0, "Failed to create child window\n");
1534 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
1536 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
1537 100, 100, 50, 50, hparent
, 0, 0, NULL
);
1538 ok (hchild2
!= 0, "Failed to create child2 window\n");
1541 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
1542 0, 100, 50, 50, hchild
, 0, 0, NULL
);
1543 ok (hbutton
!= 0, "Failed to create button window\n");
1545 /* test WM_SETREDRAW on a not visible child window */
1546 test_WM_SETREDRAW(hchild
);
1548 ShowWindow(hchild
, SW_SHOW
);
1549 ok_sequence(WmShowChildSeq
, "ShowWindow:child", FALSE
);
1551 /* test WM_SETREDRAW on a visible child window */
1552 test_WM_SETREDRAW(hchild
);
1554 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
1555 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
1557 ShowWindow(hchild
, SW_HIDE
);
1559 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1560 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
1562 ShowWindow(hchild
, SW_HIDE
);
1564 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
1565 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
1567 /* DestroyWindow sequence below expects that a child has focus */
1571 DestroyWindow(hchild
);
1572 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
1573 DestroyWindow(hchild2
);
1574 DestroyWindow(hbutton
);
1577 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
1578 0, 0, 100, 100, hparent
, 0, 0, NULL
);
1579 ok (hchild
!= 0, "Failed to create child popup window\n");
1580 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
1581 DestroyWindow(hchild
);
1583 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
1585 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
1586 0, 0, 100, 100, hparent
, 0, 0, NULL
);
1587 ok (hchild
!= 0, "Failed to create popup window\n");
1588 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
1589 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
1590 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
1592 ShowWindow(hchild
, SW_SHOW
);
1593 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
1595 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1596 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
1598 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1599 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
1600 DestroyWindow(hchild
);
1602 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
1603 * changes nothing in message sequences.
1606 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
1607 0, 0, 100, 100, hparent
, 0, 0, NULL
);
1608 ok (hchild
!= 0, "Failed to create popup window\n");
1609 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
1610 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
1611 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
1613 ShowWindow(hchild
, SW_SHOW
);
1614 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
1616 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1617 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
1618 DestroyWindow(hchild
);
1621 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
1622 0, 0, 100, 100, hparent
, 0, 0, NULL
);
1623 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
1624 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
1626 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
1627 test_scroll_messages(hwnd
);
1630 after_end_dialog
= 1;
1631 EndDialog( hwnd
, 0 );
1632 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
1634 DestroyWindow(hwnd
);
1635 after_end_dialog
= 0;
1638 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
1639 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
1641 /* test showing child with hidden parent */
1642 ShowWindow( hparent
, SW_HIDE
);
1645 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
1646 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1647 ok (hchild
!= 0, "Failed to create child window\n");
1648 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
1650 ShowWindow( hchild
, SW_SHOW
);
1651 ok_sequence(WmShowChildInvisibleParentSeq
, "ShowWindow:show child with invisible parent", TRUE
);
1652 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
1653 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
1655 ShowWindow( hchild
, SW_HIDE
);
1656 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", TRUE
);
1657 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
1658 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
1660 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1661 ok_sequence(WmShowChildInvisibleParentSeq_2
, "SetWindowPos:show child with invisible parent", FALSE
);
1662 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
1663 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
1665 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1666 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
1667 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
1668 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
1670 DestroyWindow(hparent
);
1673 /* Message sequence for SetMenu */
1674 hmenu
= CreateMenu();
1675 ok (hmenu
!= 0, "Failed to create menu\n");
1676 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
1677 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
1678 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
1679 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
1680 ok (SetMenu(hwnd
, 0), "SetMenu\n");
1681 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
1682 ok (SetMenu(hwnd
, 0), "SetMenu\n");
1683 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
1684 ShowWindow(hwnd
, SW_SHOW
);
1686 ok (SetMenu(hwnd
, 0), "SetMenu\n");
1687 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", TRUE
);
1688 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
1689 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", TRUE
);
1691 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
1692 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", TRUE
);
1694 DestroyWindow(hwnd
);
1697 /* Message sequence for EnableWindow */
1698 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
1699 100, 100, 200, 200, 0, 0, 0, NULL
);
1700 ok (hparent
!= 0, "Failed to create parent window\n");
1701 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
1702 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1703 ok (hchild
!= 0, "Failed to create child window\n");
1708 EnableWindow(hparent
, FALSE
);
1709 ok_sequence(WmEnableWindowSeq
, "EnableWindow", FALSE
);
1711 DestroyWindow(hparent
);
1715 /****************** button message test *************************/
1716 static const struct message WmSetFocusButtonSeq
[] =
1718 { HCBT_SETFOCUS
, hook
},
1719 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1720 { WM_SETFOCUS
, sent
|wparam
, 0 },
1721 { WM_CTLCOLORBTN
, sent
|defwinproc
},
1724 static const struct message WmKillFocusButtonSeq
[] =
1726 { HCBT_SETFOCUS
, hook
},
1727 { WM_KILLFOCUS
, sent
|wparam
, 0 },
1728 { WM_CTLCOLORBTN
, sent
|defwinproc
},
1729 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1732 static const struct message WmSetFocusStaticSeq
[] =
1734 { HCBT_SETFOCUS
, hook
},
1735 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1736 { WM_SETFOCUS
, sent
|wparam
, 0 },
1737 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
1740 static const struct message WmKillFocusStaticSeq
[] =
1742 { HCBT_SETFOCUS
, hook
},
1743 { WM_KILLFOCUS
, sent
|wparam
, 0 },
1744 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
1745 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1748 static const struct message WmLButtonDownSeq
[] =
1750 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
1751 { HCBT_SETFOCUS
, hook
},
1752 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1753 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
1754 { WM_CTLCOLORBTN
, sent
|defwinproc
},
1755 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
1756 { WM_CTLCOLORBTN
, sent
|defwinproc
},
1759 static const struct message WmLButtonUpSeq
[] =
1761 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
1762 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
1763 { WM_CTLCOLORBTN
, sent
|defwinproc
},
1764 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
1768 static WNDPROC old_button_proc
;
1770 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1772 static long defwndproc_counter
= 0;
1776 trace("button: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1778 msg
.message
= message
;
1779 msg
.flags
= sent
|wparam
|lparam
;
1780 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1781 msg
.wParam
= wParam
;
1782 msg
.lParam
= lParam
;
1785 if (message
== BM_SETSTATE
)
1786 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
1788 defwndproc_counter
++;
1789 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
1790 defwndproc_counter
--;
1795 static void subclass_button(void)
1799 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
1801 old_button_proc
= cls
.lpfnWndProc
;
1803 cls
.hInstance
= GetModuleHandle(0);
1804 cls
.lpfnWndProc
= button_hook_proc
;
1805 cls
.lpszClassName
= "my_button_class";
1806 if (!RegisterClassA(&cls
)) assert(0);
1809 static void test_button_messages(void)
1814 const struct message
*setfocus
;
1815 const struct message
*killfocus
;
1817 { BS_PUSHBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
1818 { BS_DEFPUSHBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
1819 { BS_CHECKBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
1820 { BS_AUTOCHECKBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
1821 { BS_RADIOBUTTON
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
1822 { BS_3STATE
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
1823 { BS_AUTO3STATE
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
1824 { BS_GROUPBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
1825 { BS_USERBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
1826 { BS_AUTORADIOBUTTON
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
1827 { BS_OWNERDRAW
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
}
1834 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
1836 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
,
1837 0, 0, 50, 14, 0, 0, 0, NULL
);
1838 ok(hwnd
!= 0, "Failed to create button window\n");
1840 ShowWindow(hwnd
, SW_SHOW
);
1845 trace("button style %08lx\n", button
[i
].style
);
1847 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
1850 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
1852 DestroyWindow(hwnd
);
1855 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
1856 0, 0, 50, 14, 0, 0, 0, NULL
);
1857 ok(hwnd
!= 0, "Failed to create button window\n");
1862 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
1863 ok_sequence(WmLButtonDownSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
1865 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
1866 ok_sequence(WmLButtonUpSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
1867 DestroyWindow(hwnd
);
1870 /************* painting message test ********************/
1872 static void dump_region(HRGN hrgn
)
1875 RGNDATA
*data
= NULL
;
1880 printf( "null region\n" );
1883 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
1884 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
1885 GetRegionData( hrgn
, size
, data
);
1886 printf("%ld rects:", data
->rdh
.nCount
);
1887 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
1888 printf( " (%ld,%ld)-(%ld,%ld)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
1890 HeapFree( GetProcessHeap(), 0, data
);
1893 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
1897 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
1898 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
1900 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
1901 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
1902 if (ret
== NULLREGION
)
1904 ok( !hrgn
, "Update region shouldn't be empty\n" );
1908 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
1910 ok( 0, "Regions are different\n" );
1911 if (winetest_debug
> 0)
1913 printf( "Update region: " );
1914 dump_region( update
);
1915 printf( "Wanted region: " );
1916 dump_region( hrgn
);
1920 GetRgnBox( update
, &r1
);
1921 GetUpdateRect( hwnd
, &r2
, FALSE
);
1922 ok( r1
.left
== r2
.left
&& r1
.top
== r2
.top
&& r1
.right
== r2
.right
&& r1
.bottom
== r2
.bottom
,
1923 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
1924 r1
.left
, r1
.top
, r1
.right
, r1
.bottom
, r2
.left
, r2
.top
, r2
.right
, r2
.bottom
);
1926 DeleteObject( tmp
);
1927 DeleteObject( update
);
1930 static const struct message WmInvalidateRgn
[] = {
1931 { WM_NCPAINT
, sent
},
1932 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1936 static const struct message WmInvalidateFull
[] = {
1937 { WM_NCPAINT
, sent
|wparam
, 1 },
1938 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1942 static const struct message WmInvalidateErase
[] = {
1943 { WM_NCPAINT
, sent
|wparam
, 1 },
1944 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1945 { WM_ERASEBKGND
, sent
},
1949 static const struct message WmInvalidatePaint
[] = {
1951 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
1952 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
1956 static const struct message WmInvalidateErasePaint
[] = {
1958 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
1959 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
1960 { WM_ERASEBKGND
, sent
|beginpaint
},
1964 static const struct message WmErase
[] = {
1965 { WM_ERASEBKGND
, sent
},
1969 static const struct message WmPaint
[] = {
1974 static void test_paint_messages(void)
1978 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
1979 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1980 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
1981 100, 100, 200, 200, 0, 0, 0, NULL
);
1982 ok (hwnd
!= 0, "Failed to create overlapped window\n");
1984 ShowWindow( hwnd
, SW_SHOW
);
1985 UpdateWindow( hwnd
);
1986 check_update_rgn( hwnd
, 0 );
1987 SetRectRgn( hrgn
, 10, 10, 20, 20 );
1988 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
1989 check_update_rgn( hwnd
, hrgn
);
1990 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
1991 RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
1992 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
1993 check_update_rgn( hwnd
, hrgn
);
1994 /* validate everything */
1995 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
1996 check_update_rgn( hwnd
, 0 );
1997 /* now with frame */
1998 SetRectRgn( hrgn
, -5, -5, 20, 20 );
2001 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2002 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
2004 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
2005 check_update_rgn( hwnd
, hrgn
);
2008 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
2009 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2012 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
2013 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
2015 GetClientRect( hwnd
, &rect
);
2016 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2017 check_update_rgn( hwnd
, hrgn
);
2020 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
2021 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
2024 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
2025 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", TRUE
);
2026 check_update_rgn( hwnd
, 0 );
2029 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
2030 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
2031 check_update_rgn( hwnd
, 0 );
2034 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2035 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
2036 SetRectRgn( hrgn
, 0, 0, 50, 100 );
2037 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
2038 SetRectRgn( hrgn
, 50, 0, 100, 100 );
2039 check_update_rgn( hwnd
, hrgn
);
2040 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
2041 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
2042 check_update_rgn( hwnd
, 0 );
2045 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2046 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
2047 SetRectRgn( hrgn
, 0, 0, 100, 50 );
2048 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
2049 ok_sequence( WmErase
, "Erase", FALSE
);
2050 SetRectRgn( hrgn
, 0, 50, 100, 100 );
2051 check_update_rgn( hwnd
, hrgn
);
2054 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2055 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
2056 SetRectRgn( hrgn
, 0, 0, 50, 50 );
2057 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
2058 ok_sequence( WmPaint
, "Paint", FALSE
);
2061 SetRectRgn( hrgn
, -4, -4, -2, -2 );
2062 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2063 SetRectRgn( hrgn
, -4, -4, -3, -3 );
2064 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
2065 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
2068 SetRectRgn( hrgn
, -4, -4, -2, -2 );
2069 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2070 SetRectRgn( hrgn
, -4, -4, -3, -3 );
2071 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
2072 SetRectRgn( hrgn
, 0, 0, 1, 1 );
2073 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
2074 ok_sequence( WmPaint
, "Paint", TRUE
);
2077 SetRectRgn( hrgn
, -4, -4, -1, -1 );
2078 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2079 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
2080 /* make sure no WM_PAINT was generated */
2081 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
2082 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2085 SetRectRgn( hrgn
, -4, -4, -1, -1 );
2086 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2087 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
2089 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
2091 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
2092 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
2093 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
2094 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
2095 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
2096 /* this will send WM_NCPAINT and validate the non client area */
2097 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
2098 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
2100 else DispatchMessage( &msg
);
2102 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2104 DeleteObject( hrgn
);
2105 DeleteObject( hrgn2
);
2106 DestroyWindow( hwnd
);
2110 /************* window procedures ********************/
2112 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2114 static long defwndproc_counter
= 0;
2115 static long beginpaint_counter
= 0;
2119 trace("%p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2121 msg
.message
= message
;
2122 msg
.flags
= sent
|wparam
|lparam
;
2123 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2124 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
2125 msg
.wParam
= wParam
;
2126 msg
.lParam
= lParam
;
2129 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
2131 HWND parent
= GetParent(hwnd
);
2133 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
2135 GetClientRect(parent
, &rc
);
2136 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
2138 trace("ptReserved = (%ld,%ld)\n"
2139 "ptMaxSize = (%ld,%ld)\n"
2140 "ptMaxPosition = (%ld,%ld)\n"
2141 "ptMinTrackSize = (%ld,%ld)\n"
2142 "ptMaxTrackSize = (%ld,%ld)\n",
2143 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
2144 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
2145 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
2146 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
2147 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
2149 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
2150 minmax
->ptMaxSize
.x
, rc
.right
);
2151 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
2152 minmax
->ptMaxSize
.y
, rc
.bottom
);
2155 if (message
== WM_PAINT
)
2158 beginpaint_counter
++;
2159 BeginPaint( hwnd
, &ps
);
2160 beginpaint_counter
--;
2161 EndPaint( hwnd
, &ps
);
2165 defwndproc_counter
++;
2166 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2167 defwndproc_counter
--;
2172 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2174 static long defwndproc_counter
= 0;
2178 trace("popup: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2180 msg
.message
= message
;
2181 msg
.flags
= sent
|wparam
|lparam
;
2182 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2183 msg
.wParam
= wParam
;
2184 msg
.lParam
= lParam
;
2187 if (message
== WM_CREATE
)
2189 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
2190 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
2193 defwndproc_counter
++;
2194 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2195 defwndproc_counter
--;
2200 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2202 static long defwndproc_counter
= 0;
2206 trace("parent: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2208 if (message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
2209 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
2210 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
2211 message
== WM_IME_SETCONTEXT
)
2213 msg
.message
= message
;
2214 msg
.flags
= sent
|parent
|wparam
|lparam
;
2215 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2216 msg
.wParam
= wParam
;
2217 msg
.lParam
= lParam
;
2221 defwndproc_counter
++;
2222 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2223 defwndproc_counter
--;
2228 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2230 static long defwndproc_counter
= 0;
2234 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2236 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
2237 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
2238 if (after_end_dialog
)
2239 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
2241 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
2243 msg
.message
= message
;
2244 msg
.flags
= sent
|wparam
|lparam
;
2245 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2246 msg
.wParam
= wParam
;
2247 msg
.lParam
= lParam
;
2250 defwndproc_counter
++;
2251 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
2252 defwndproc_counter
--;
2257 static BOOL
RegisterWindowClasses(void)
2262 cls
.lpfnWndProc
= MsgCheckProcA
;
2265 cls
.hInstance
= GetModuleHandleA(0);
2267 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
2268 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
2269 cls
.lpszMenuName
= NULL
;
2270 cls
.lpszClassName
= "TestWindowClass";
2271 if(!RegisterClassA(&cls
)) return FALSE
;
2273 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
2274 cls
.lpszClassName
= "TestPopupClass";
2275 if(!RegisterClassA(&cls
)) return FALSE
;
2277 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
2278 cls
.lpszClassName
= "TestParentClass";
2279 if(!RegisterClassA(&cls
)) return FALSE
;
2281 cls
.lpfnWndProc
= DefWindowProcA
;
2282 cls
.lpszClassName
= "SimpleWindowClass";
2283 if(!RegisterClassA(&cls
)) return FALSE
;
2285 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
2286 cls
.lpfnWndProc
= TestDlgProcA
;
2287 cls
.lpszClassName
= "TestDialogClass";
2288 if(!RegisterClassA(&cls
)) return FALSE
;
2293 static HHOOK hCBT_hook
;
2295 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
2299 trace("CBT: %d, %08x, %08lx\n", nCode
, wParam
, lParam
);
2301 /* Log also SetFocus(0) calls */
2302 if (!wParam
) wParam
= lParam
;
2304 if (GetClassNameA((HWND
)wParam
, buf
, sizeof(buf
)))
2306 if (!strcmp(buf
, "TestWindowClass") ||
2307 !strcmp(buf
, "TestParentClass") ||
2308 !strcmp(buf
, "TestPopupClass") ||
2309 !strcmp(buf
, "SimpleWindowClass") ||
2310 !strcmp(buf
, "TestDialogClass") ||
2311 !strcmp(buf
, "MDI_frame_class") ||
2312 !strcmp(buf
, "MDI_client_class") ||
2313 !strcmp(buf
, "MDI_child_class") ||
2314 !strcmp(buf
, "my_button_class") ||
2315 !strcmp(buf
, "#32770"))
2319 msg
.message
= nCode
;
2321 msg
.wParam
= wParam
;
2322 msg
.lParam
= lParam
;
2326 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
2331 if (!RegisterWindowClasses()) assert(0);
2333 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
2337 test_mdi_messages();
2338 test_button_messages();
2339 test_paint_messages();
2341 UnhookWindowsHookEx(hCBT_hook
);