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
38 /* undocumented SWP flags - from SDK 3.1 */
39 #define SWP_NOCLIENTSIZE 0x0800
40 #define SWP_NOCLIENTMOVE 0x1000
43 FIXME: add tests for these
44 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
45 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
46 WS_THICKFRAME: thick border
47 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
48 WS_BORDER (default for overlapped windows): single black border
49 none (default for child (and popup?) windows): no border
65 UINT message
; /* the WM_* code */
66 msg_flags_t flags
; /* message props */
67 WPARAM wParam
; /* expected value of wParam */
68 LPARAM lParam
; /* expected value of lParam */
71 /* Empty message sequence */
72 static const struct message WmEmptySeq
[] =
76 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
77 static const struct message WmCreateOverlappedSeq
[] = {
78 { HCBT_CREATEWND
, hook
},
79 { WM_GETMINMAXINFO
, sent
},
80 { WM_NCCREATE
, sent
},
81 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
85 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
86 * for a not visible overlapped window.
88 static const struct message WmSWP_ShowOverlappedSeq
[] = {
89 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
90 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
91 { WM_GETTEXT
, sent
|defwinproc
|optional
},
92 { WM_ERASEBKGND
, sent
|optional
},
93 { HCBT_ACTIVATE
, hook
},
94 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
95 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
96 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
97 { WM_NCACTIVATE
, sent
|wparam
, 1 },
98 { WM_GETTEXT
, sent
|defwinproc
|optional
},
99 { WM_ACTIVATE
, sent
|wparam
, 1 },
100 { HCBT_SETFOCUS
, hook
},
101 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
102 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
103 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
104 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
105 { WM_GETTEXT
, sent
|defwinproc
|optional
},
106 { WM_ERASEBKGND
, sent
|optional
},
107 /* Win9x adds SWP_NOZORDER below */
108 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
109 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
110 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
111 { WM_ERASEBKGND
, sent
|optional
},
114 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
115 * for a visible overlapped window.
117 static const struct message WmSWP_HideOverlappedSeq
[] = {
118 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
119 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
122 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
123 static const struct message WmShowOverlappedSeq
[] = {
124 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
125 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
126 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
127 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
128 { WM_GETTEXT
, sent
|defwinproc
|optional
},
129 { WM_ERASEBKGND
, sent
|optional
},
130 { HCBT_ACTIVATE
, hook
},
131 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
132 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
133 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
134 { WM_NCACTIVATE
, sent
|wparam
, 1 },
135 { WM_GETTEXT
, sent
|defwinproc
|optional
},
136 { WM_ACTIVATE
, sent
|wparam
, 1 },
137 { HCBT_SETFOCUS
, hook
},
138 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
139 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
140 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
141 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
142 { WM_GETTEXT
, sent
|defwinproc
|optional
},
143 { WM_ERASEBKGND
, sent
|optional
},
144 /* Win9x adds SWP_NOZORDER below */
145 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
146 { WM_NCCALCSIZE
, sent
|optional
},
147 { WM_NCPAINT
, sent
|optional
},
148 { WM_ERASEBKGND
, sent
|optional
},
149 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
150 * messages. Does that mean that CreateWindow doesn't set initial
151 * window dimensions for overlapped windows?
158 /* ShowWindow(SW_HIDE) for a visible overlapped window */
159 static const struct message WmHideOverlappedSeq
[] = {
160 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
161 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
162 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
165 { WM_NCACTIVATE
, sent
|wparam
, 0 },
166 { WM_ACTIVATE
, sent
|wparam
, 0 },
167 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
168 { WM_KILLFOCUS
, sent
|wparam
, 0 },
169 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
170 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
173 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
174 static const struct message WmHideInvisibleOverlappedSeq
[] = {
177 /* DestroyWindow for a visible overlapped window */
178 static const struct message WmDestroyOverlappedSeq
[] = {
179 { HCBT_DESTROYWND
, hook
},
180 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
181 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
182 { WM_NCACTIVATE
, sent
|wparam
, 0 },
183 { WM_ACTIVATE
, sent
|wparam
, 0 },
184 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
185 { WM_KILLFOCUS
, sent
|wparam
, 0 },
186 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
187 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
188 { WM_DESTROY
, sent
},
189 { WM_NCDESTROY
, sent
},
192 /* CreateWindow (for a child popup window, not initially visible) */
193 static const struct message WmCreateChildPopupSeq
[] = {
194 { HCBT_CREATEWND
, hook
},
195 { WM_NCCREATE
, sent
},
196 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
202 /* CreateWindow (for a popup window, not initially visible,
203 * which sets WS_VISIBLE in WM_CREATE handler)
205 static const struct message WmCreateInvisiblePopupSeq
[] = {
206 { HCBT_CREATEWND
, hook
},
207 { WM_NCCREATE
, sent
},
208 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
210 { WM_STYLECHANGING
, sent
},
211 { WM_STYLECHANGED
, sent
},
216 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
217 * for a popup window with WS_VISIBLE style set
219 static const struct message WmShowVisiblePopupSeq_2
[] = {
220 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
223 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
224 * for a popup window with WS_VISIBLE style set
226 static const struct message WmShowVisiblePopupSeq_3
[] = {
227 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
228 { HCBT_ACTIVATE
, hook
},
229 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
230 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
231 { WM_NCACTIVATE
, sent
|wparam
, 1 },
232 { WM_ACTIVATE
, sent
|wparam
, 1 },
233 { HCBT_SETFOCUS
, hook
},
234 { WM_KILLFOCUS
, sent
|parent
},
235 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
236 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
237 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
238 { WM_SETFOCUS
, sent
|defwinproc
},
241 /* CreateWindow (for child window, not initially visible) */
242 static const struct message WmCreateChildSeq
[] = {
243 { HCBT_CREATEWND
, hook
},
244 { WM_NCCREATE
, sent
},
245 /* child is inserted into parent's child list after WM_NCCREATE returns */
246 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
250 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
253 /* CreateWindow (for maximized child window, not initially visible) */
254 static const struct message WmCreateMaximizedChildSeq
[] = {
255 { HCBT_CREATEWND
, hook
},
256 { WM_NCCREATE
, sent
},
257 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
261 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
262 { WM_GETMINMAXINFO
, sent
},
263 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
264 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
265 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|0x8000 },
266 { WM_SIZE
, sent
|defwinproc
},
267 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
270 /* CreateWindow (for a child window, initially visible) */
271 static const struct message WmCreateVisibleChildSeq
[] = {
272 { HCBT_CREATEWND
, hook
},
273 { WM_NCCREATE
, sent
},
274 /* child is inserted into parent's child list after WM_NCCREATE returns */
275 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
279 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
280 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
281 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
},
282 { WM_ERASEBKGND
, sent
|parent
|optional
},
283 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
286 /* ShowWindow(SW_SHOW) for a not visible child window */
287 static const struct message WmShowChildSeq
[] = {
288 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
289 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
290 { WM_ERASEBKGND
, sent
|parent
|optional
},
291 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
294 /* ShowWindow(SW_HIDE) for a visible child window */
295 static const struct message WmHideChildSeq
[] = {
296 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
297 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
298 { WM_ERASEBKGND
, sent
|parent
|optional
},
299 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
302 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
303 * for a not visible child window
305 static const struct message WmShowChildSeq_2
[] = {
306 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
307 { WM_CHILDACTIVATE
, sent
},
308 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
311 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
312 * for a not visible child window
314 static const struct message WmShowChildSeq_3
[] = {
315 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
316 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
319 /* ShowWindow(SW_SHOW) for child with invisible parent */
320 static const struct message WmShowChildInvisibleParentSeq
[] = {
321 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
324 /* ShowWindow(SW_HIDE) for child with invisible parent */
325 static const struct message WmHideChildInvisibleParentSeq
[] = {
326 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
329 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
330 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
331 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
},
332 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
335 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
336 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
337 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
338 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
341 /* DestroyWindow for a visible child window */
342 static const struct message WmDestroyChildSeq
[] = {
343 { HCBT_DESTROYWND
, hook
},
344 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
345 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
346 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
347 { WM_ERASEBKGND
, sent
|parent
|optional
},
348 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
349 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
350 { WM_KILLFOCUS
, sent
},
351 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
352 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
353 { WM_SETFOCUS
, sent
|parent
},
354 { WM_DESTROY
, sent
},
355 { WM_DESTROY
, sent
|optional
}, /* a bug in win2k sp4 ? */
356 { WM_NCDESTROY
, sent
},
357 { WM_NCDESTROY
, sent
|optional
}, /* a bug in win2k sp4 ? */
360 /* Moving the mouse in nonclient area */
361 static const struct message WmMouseMoveInNonClientAreaSeq
[] = { /* FIXME: add */
362 { WM_NCHITTEST
, sent
},
363 { WM_SETCURSOR
, sent
},
364 { WM_NCMOUSEMOVE
, posted
},
367 /* Moving the mouse in client area */
368 static const struct message WmMouseMoveInClientAreaSeq
[] = { /* FIXME: add */
369 { WM_NCHITTEST
, sent
},
370 { WM_SETCURSOR
, sent
},
371 { WM_MOUSEMOVE
, posted
},
374 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
375 static const struct message WmDragTitleBarSeq
[] = { /* FIXME: add */
376 { WM_NCLBUTTONDOWN
, sent
|wparam
, HTCAPTION
},
377 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_MOVE
+2 },
378 { WM_GETMINMAXINFO
, sent
|defwinproc
},
379 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
380 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
381 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
382 { WM_MOVE
, sent
|defwinproc
},
383 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
386 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
387 static const struct message WmDragThickBordersBarSeq
[] = { /* FIXME: add */
388 { WM_NCLBUTTONDOWN
, sent
|wparam
, 0xd },
389 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, 0xf004 },
390 { WM_GETMINMAXINFO
, sent
|defwinproc
},
391 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
392 { WM_SIZING
, sent
|defwinproc
|wparam
, 4}, /* one for each mouse movement */
393 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
394 { WM_GETMINMAXINFO
, sent
|defwinproc
},
395 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
396 { WM_NCPAINT
, sent
|defwinproc
|wparam
, 1 },
397 { WM_GETTEXT
, sent
|defwinproc
},
398 { WM_ERASEBKGND
, sent
|defwinproc
},
399 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
400 { WM_MOVE
, sent
|defwinproc
},
401 { WM_SIZE
, sent
|defwinproc
},
402 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
405 /* Resizing child window with MoveWindow (32) */
406 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
407 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
408 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
409 { WM_ERASEBKGND
, sent
|optional
},
410 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
411 { WM_MOVE
, sent
|defwinproc
},
412 { WM_SIZE
, sent
|defwinproc
},
415 /* Clicking on inactive button */
416 static const struct message WmClickInactiveButtonSeq
[] = { /* FIXME: add */
417 { WM_NCHITTEST
, sent
},
418 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_LBUTTONDOWN
},
419 { WM_MOUSEACTIVATE
, sent
},
420 { WM_MOUSEACTIVATE
, sent
|parent
|defwinproc
},
421 { WM_SETCURSOR
, sent
},
422 { WM_SETCURSOR
, sent
|parent
|defwinproc
},
423 { WM_LBUTTONDOWN
, posted
},
424 { WM_KILLFOCUS
, posted
|parent
},
425 { WM_SETFOCUS
, posted
},
426 { WM_CTLCOLORBTN
, posted
|parent
},
427 { BM_SETSTATE
, posted
},
428 { WM_CTLCOLORBTN
, posted
|parent
},
429 { WM_LBUTTONUP
, posted
},
430 { BM_SETSTATE
, posted
},
431 { WM_CTLCOLORBTN
, posted
|parent
},
432 { WM_COMMAND
, posted
|parent
},
435 /* Reparenting a button (16/32) */
436 /* The last child (button) reparented gets topmost for its new parent. */
437 static const struct message WmReparentButtonSeq
[] = { /* FIXME: add */
438 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
439 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
440 { WM_ERASEBKGND
, sent
|parent
},
441 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
442 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOZORDER
},
443 { WM_CHILDACTIVATE
, sent
},
444 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOZORDER
},
445 { WM_MOVE
, sent
|defwinproc
},
446 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
449 /* Creation of a custom dialog (32) */
450 static const struct message WmCreateCustomDialogSeq
[] = {
451 { HCBT_CREATEWND
, hook
},
452 { WM_GETMINMAXINFO
, sent
},
453 { WM_NCCREATE
, sent
},
454 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
456 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
457 { HCBT_ACTIVATE
, hook
},
458 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
459 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
460 { WM_NCACTIVATE
, 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_ACTIVATE
, sent
|wparam
, 1 },
467 { WM_KILLFOCUS
, sent
|parent
},
468 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
469 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
470 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
471 { WM_SETFOCUS
, sent
},
472 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
473 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
474 { WM_NCPAINT
, sent
|wparam
, 1 },
475 { WM_GETTEXT
, sent
|optional
|defwinproc
},
476 { WM_GETICON
, sent
|optional
|defwinproc
},
477 { WM_GETICON
, sent
|optional
|defwinproc
},
478 { WM_GETICON
, sent
|optional
|defwinproc
},
479 { WM_GETTEXT
, sent
|optional
|defwinproc
},
480 { WM_ERASEBKGND
, sent
},
481 { WM_CTLCOLORDLG
, sent
|defwinproc
},
482 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
483 { WM_GETTEXT
, sent
|optional
},
484 { WM_GETICON
, sent
|optional
},
485 { WM_GETICON
, sent
|optional
},
486 { WM_GETICON
, sent
|optional
},
487 { WM_GETTEXT
, sent
|optional
},
488 { WM_NCCALCSIZE
, sent
|optional
},
489 { WM_NCPAINT
, sent
|optional
},
490 { WM_GETTEXT
, sent
|optional
|defwinproc
},
491 { WM_GETICON
, sent
|optional
|defwinproc
},
492 { WM_GETICON
, sent
|optional
|defwinproc
},
493 { WM_GETICON
, sent
|optional
|defwinproc
},
494 { WM_GETTEXT
, sent
|optional
|defwinproc
},
495 { WM_ERASEBKGND
, sent
|optional
},
496 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
501 /* Calling EndDialog for a custom dialog (32) */
502 static const struct message WmEndCustomDialogSeq
[] = {
503 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
504 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
505 { WM_GETTEXT
, sent
|optional
},
506 { WM_GETICON
, sent
|optional
},
507 { WM_GETICON
, sent
|optional
},
508 { WM_GETICON
, sent
|optional
},
509 { HCBT_ACTIVATE
, hook
},
510 { WM_NCACTIVATE
, sent
|wparam
, 0 },
511 { WM_GETTEXT
, sent
|optional
|defwinproc
},
512 { WM_GETICON
, sent
|optional
|defwinproc
},
513 { WM_GETICON
, sent
|optional
|defwinproc
},
514 { WM_GETICON
, sent
|optional
|defwinproc
},
515 { WM_GETTEXT
, sent
|optional
|defwinproc
},
516 { WM_ACTIVATE
, sent
|wparam
, 0 },
517 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, 0 },
518 { HCBT_SETFOCUS
, hook
},
519 { WM_KILLFOCUS
, sent
},
520 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
521 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
522 { WM_IME_NOTIFY
, sent
|optional
},
523 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
526 /* Creation and destruction of a modal dialog (32) */
527 static const struct message WmModalDialogSeq
[] = {
528 { WM_CANCELMODE
, sent
|parent
},
529 { HCBT_SETFOCUS
, hook
},
530 { WM_KILLFOCUS
, sent
|parent
},
531 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
532 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
533 { HCBT_CREATEWND
, hook
},
534 { WM_SETFONT
, sent
},
535 { WM_INITDIALOG
, sent
},
536 { WM_CHANGEUISTATE
, sent
|optional
},
537 { WM_SHOWWINDOW
, sent
},
538 { HCBT_ACTIVATE
, hook
},
539 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
540 { WM_NCACTIVATE
, sent
|wparam
, 1 },
541 { WM_GETICON
, sent
|optional
},
542 { WM_GETICON
, sent
|optional
},
543 { WM_GETICON
, sent
|optional
},
544 { WM_GETTEXT
, sent
|optional
},
545 { WM_ACTIVATE
, sent
|wparam
, 1 },
546 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
547 { WM_NCPAINT
, sent
},
548 { WM_GETICON
, sent
|optional
},
549 { WM_GETICON
, sent
|optional
},
550 { WM_GETICON
, sent
|optional
},
551 { WM_GETTEXT
, sent
|optional
},
552 { WM_ERASEBKGND
, sent
},
553 { WM_CTLCOLORDLG
, sent
},
554 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
555 { WM_GETICON
, sent
|optional
},
556 { WM_GETICON
, sent
|optional
},
557 { WM_GETICON
, sent
|optional
},
558 { WM_GETTEXT
, sent
|optional
},
559 { WM_NCCALCSIZE
, sent
|optional
},
560 { WM_NCPAINT
, sent
|optional
},
561 { WM_GETICON
, sent
|optional
},
562 { WM_GETICON
, sent
|optional
},
563 { WM_GETICON
, sent
|optional
},
564 { WM_GETTEXT
, sent
|optional
},
565 { WM_ERASEBKGND
, sent
|optional
},
566 { WM_CTLCOLORDLG
, sent
|optional
},
567 { WM_PAINT
, sent
|optional
},
568 { WM_CTLCOLORBTN
, sent
},
569 { WM_ENTERIDLE
, sent
|parent
|optional
},
571 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
572 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
573 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
574 { WM_GETICON
, sent
|optional
},
575 { WM_GETICON
, sent
|optional
},
576 { WM_GETICON
, sent
|optional
},
577 { WM_GETTEXT
, sent
|optional
},
578 { HCBT_ACTIVATE
, hook
},
579 { WM_NCACTIVATE
, sent
|wparam
, 0 },
580 { WM_GETICON
, sent
|optional
},
581 { WM_GETICON
, sent
|optional
},
582 { WM_GETICON
, sent
|optional
},
583 { WM_GETTEXT
, sent
|optional
},
584 { WM_ACTIVATE
, sent
|wparam
, 0 },
585 { WM_WINDOWPOSCHANGING
, sent
|optional
},
586 { HCBT_SETFOCUS
, hook
},
587 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
588 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
589 { HCBT_DESTROYWND
, hook
},
590 { WM_DESTROY
, sent
},
591 { WM_NCDESTROY
, sent
},
594 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
595 static const struct message WmCreateModalDialogResizeSeq
[] = { /* FIXME: add */
596 /* (inside dialog proc, handling WM_INITDIALOG) */
597 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
598 { WM_NCCALCSIZE
, sent
},
599 { WM_NCACTIVATE
, sent
|parent
|wparam
, 0 },
600 { WM_GETTEXT
, sent
|defwinproc
},
601 { WM_ACTIVATE
, sent
|parent
|wparam
, 0 },
602 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
603 { WM_WINDOWPOSCHANGING
, sent
|parent
},
604 { WM_NCACTIVATE
, sent
|wparam
, 1 },
605 { WM_ACTIVATE
, sent
|wparam
, 1 },
606 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
607 { WM_SIZE
, sent
|defwinproc
},
608 /* (setting focus) */
609 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
610 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
611 { WM_NCPAINT
, sent
},
612 { WM_GETTEXT
, sent
|defwinproc
},
613 { WM_ERASEBKGND
, sent
},
614 { WM_CTLCOLORDLG
, sent
|defwinproc
},
615 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
617 /* (bunch of WM_CTLCOLOR* for each control) */
618 { WM_PAINT
, sent
|parent
},
619 { WM_ENTERIDLE
, sent
|parent
|wparam
, 0 },
620 { WM_SETCURSOR
, sent
|parent
},
623 /* SetMenu for NonVisible windows with size change*/
624 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
625 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
626 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
627 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
},
628 { WM_MOVE
, sent
|defwinproc
},
629 { WM_SIZE
, sent
|defwinproc
},
630 { WM_GETICON
, sent
|optional
},
631 { WM_GETICON
, sent
|optional
},
632 { WM_GETICON
, sent
|optional
},
633 { WM_GETTEXT
, sent
|optional
},
634 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
637 /* SetMenu for NonVisible windows with no size change */
638 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
639 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
640 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
641 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
644 /* SetMenu for Visible windows with size change */
645 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
646 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
647 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
648 { WM_NCPAINT
, sent
|wparam
, 1 },
649 { WM_GETTEXT
, sent
|defwinproc
|optional
},
650 { WM_ERASEBKGND
, sent
|optional
},
651 { WM_ACTIVATE
, sent
|optional
},
652 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
653 { WM_MOVE
, sent
|defwinproc
},
654 { WM_SIZE
, sent
|defwinproc
},
655 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
656 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
657 { WM_ERASEBKGND
, sent
|optional
},
660 /* SetMenu for Visible windows with no size change */
661 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
662 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
663 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
664 { WM_NCPAINT
, sent
|wparam
, 1 },
665 { WM_GETTEXT
, sent
|defwinproc
|optional
},
666 { WM_ERASEBKGND
, sent
|optional
},
667 { WM_ACTIVATE
, sent
|optional
},
668 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
671 /* DrawMenuBar for a visible window */
672 static const struct message WmDrawMenuBarSeq
[] =
674 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
675 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
676 { WM_NCPAINT
, sent
|wparam
, 1 },
677 { WM_GETTEXT
, sent
|defwinproc
|optional
},
678 { WM_ERASEBKGND
, sent
|optional
},
679 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
683 static const struct message WmSetRedrawFalseSeq
[] =
685 { WM_SETREDRAW
, sent
|wparam
, 0 },
689 static const struct message WmSetRedrawTrueSeq
[] =
691 { WM_SETREDRAW
, sent
|wparam
, 1 },
695 static const struct message WmEnableWindowSeq
[] =
697 { WM_CANCELMODE
, sent
},
702 static const struct message WmGetScrollRangeSeq
[] =
704 { SBM_GETRANGE
, sent
},
707 static const struct message WmGetScrollInfoSeq
[] =
709 { SBM_GETSCROLLINFO
, sent
},
712 static const struct message WmSetScrollRangeSeq
[] =
714 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
715 sends SBM_SETSCROLLINFO.
717 { SBM_SETSCROLLINFO
, sent
},
720 /* SetScrollRange for a window without a non-client area */
721 static const struct message WmSetScrollRangeHVSeq
[] =
723 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
724 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
725 { WM_GETTEXT
, sent
|defwinproc
|optional
},
726 { WM_ERASEBKGND
, sent
|optional
},
727 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
730 /* SetScrollRange for a window with a non-client area */
731 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
733 { WM_WINDOWPOSCHANGING
, sent
, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
734 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
735 { WM_NCPAINT
, sent
|optional
},
736 { WM_GETTEXT
, sent
|defwinproc
|optional
},
737 { WM_GETICON
, sent
|optional
|defwinproc
},
738 { WM_GETICON
, sent
|optional
|defwinproc
},
739 { WM_GETICON
, sent
|optional
|defwinproc
},
740 { WM_GETTEXT
, sent
|defwinproc
|optional
},
741 { WM_ERASEBKGND
, sent
|optional
},
742 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
743 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
744 { WM_SIZE
, sent
|defwinproc
},
745 { WM_GETTEXT
, sent
|optional
},
746 { WM_GETICON
, sent
|optional
},
747 { WM_GETICON
, sent
|optional
},
748 { WM_GETICON
, sent
|optional
},
749 { WM_GETTEXT
, sent
|optional
},
750 { WM_GETICON
, sent
|optional
},
751 { WM_GETICON
, sent
|optional
},
752 { WM_GETICON
, sent
|optional
},
753 { WM_GETTEXT
, sent
|optional
},
754 { WM_GETICON
, sent
|optional
},
755 { WM_GETICON
, sent
|optional
},
756 { WM_GETICON
, sent
|optional
},
757 { WM_GETTEXT
, sent
|optional
},
761 static int after_end_dialog
;
762 static int sequence_cnt
, sequence_size
;
763 static struct message
* sequence
;
765 static void add_message(const struct message
*msg
)
770 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof (struct message
) );
772 if (sequence_cnt
== sequence_size
)
775 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof (struct message
) );
779 sequence
[sequence_cnt
].message
= msg
->message
;
780 sequence
[sequence_cnt
].flags
= msg
->flags
;
781 sequence
[sequence_cnt
].wParam
= msg
->wParam
;
782 sequence
[sequence_cnt
].lParam
= msg
->lParam
;
787 static void flush_sequence()
789 HeapFree(GetProcessHeap(), 0, sequence
);
791 sequence_cnt
= sequence_size
= 0;
794 static void ok_sequence(const struct message
*expected
, const char *context
, int todo
)
796 static const struct message end_of_sequence
= { 0, 0, 0, 0 };
797 const struct message
*actual
;
799 add_message(&end_of_sequence
);
803 while (expected
->message
&& actual
->message
)
805 trace("expected %04x - actual %04x\n", expected
->message
, actual
->message
);
807 if (expected
->message
== actual
->message
)
809 if (expected
->flags
& wparam
)
811 if (expected
->wParam
!= actual
->wParam
&& todo
)
815 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
816 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
820 ok (expected
->wParam
== actual
->wParam
,
821 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
822 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
824 if (expected
->flags
& lparam
)
825 ok (expected
->lParam
== actual
->lParam
,
826 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
827 context
, expected
->message
, expected
->lParam
, actual
->lParam
);
828 ok ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
829 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
830 context
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
831 ok ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
832 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
833 context
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
834 ok ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
835 "%s: the msg 0x%04x should have been %s\n",
836 context
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
837 ok ((expected
->flags
& parent
) == (actual
->flags
& parent
),
838 "%s: the msg 0x%04x was expected in %s\n",
839 context
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
840 ok ((expected
->flags
& hook
) == (actual
->flags
& hook
),
841 "%s: the msg 0x%04x should have been sent by a hook\n",
842 context
, expected
->message
);
846 else if (expected
->flags
& optional
)
851 ok (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
852 context
, expected
->message
, actual
->message
);
859 ok (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
860 context
, expected
->message
, actual
->message
);
866 /* skip all optional trailing messages */
867 while (expected
->message
&& (expected
->flags
& optional
))
873 if (expected
->message
|| actual
->message
)
874 ok (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
875 context
, expected
->message
, actual
->message
);
880 if (expected
->message
|| actual
->message
)
881 ok (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
882 context
, expected
->message
, actual
->message
);
888 /******************************** MDI test **********************************/
890 /* CreateWindow for MDI frame window, initially visible */
891 static const struct message WmCreateMDIframeSeq
[] = {
892 { HCBT_CREATEWND
, hook
},
893 { WM_GETMINMAXINFO
, sent
},
894 { WM_NCCREATE
, sent
},
895 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
897 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
898 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
899 { HCBT_ACTIVATE
, hook
},
900 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
901 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
902 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* Win9x */
903 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
904 { WM_NCACTIVATE
, sent
|wparam
, 1 },
905 { WM_ACTIVATE
, sent
|wparam
, 1 },
906 { HCBT_SETFOCUS
, hook
},
907 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
908 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
909 /* Win9x adds SWP_NOZORDER below */
910 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
915 /* DestroyWindow for MDI frame window, initially visible */
916 static const struct message WmDestroyMDIframeSeq
[] = {
917 { HCBT_DESTROYWND
, hook
},
918 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
919 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
920 { WM_NCACTIVATE
, sent
|wparam
, 0 },
921 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
922 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
923 { WM_DESTROY
, sent
},
924 { WM_NCDESTROY
, sent
},
927 /* CreateWindow for MDI client window, initially visible */
928 static const struct message WmCreateMDIclientSeq
[] = {
929 { HCBT_CREATEWND
, hook
},
930 { WM_NCCREATE
, sent
},
931 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
935 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
936 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
937 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
},
938 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
941 /* DestroyWindow for MDI client window, initially visible */
942 static const struct message WmDestroyMDIclientSeq
[] = {
943 { HCBT_DESTROYWND
, hook
},
944 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
945 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
946 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
947 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
948 { WM_DESTROY
, sent
},
949 { WM_NCDESTROY
, sent
},
952 /* CreateWindow for MDI child window, initially visible */
953 static const struct message WmCreateMDIchildVisibleSeq
[] = {
954 { HCBT_CREATEWND
, hook
},
955 { WM_NCCREATE
, sent
},
956 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
960 /* Win2k sends wparam set to
961 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
962 * while Win9x doesn't bother to set child window id according to
963 * CLIENTCREATESTRUCT.idFirstChild
965 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
966 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
967 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
968 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
969 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
970 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
971 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
972 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
974 /* Win9x: message sequence terminates here. */
976 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
977 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
978 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
979 { WM_SETFOCUS
, sent
}, /* in MDI client */
980 { HCBT_SETFOCUS
, hook
},
981 { WM_KILLFOCUS
, sent
}, /* in MDI client */
982 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
983 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
984 { WM_SETFOCUS
, sent
|defwinproc
},
985 { WM_MDIACTIVATE
, sent
|defwinproc
},
988 /* DestroyWindow for MDI child window, initially visible */
989 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
990 { HCBT_DESTROYWND
, hook
},
991 /* Win2k sends wparam set to
992 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
993 * while Win9x doesn't bother to set child window id according to
994 * CLIENTCREATESTRUCT.idFirstChild
996 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
997 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
998 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
999 { WM_ERASEBKGND
, sent
|parent
|optional
},
1000 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1002 /* { WM_DESTROY, sent }
1003 * Win9x: message sequence terminates here.
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 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1019 { WM_KILLFOCUS
, sent
},
1020 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1021 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1022 { WM_SETFOCUS
, sent
}, /* in MDI client */
1024 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1025 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1026 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1027 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1028 { WM_SETFOCUS
, sent
}, /* in MDI client */
1030 { WM_DESTROY
, sent
},
1032 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1033 { WM_KILLFOCUS
, sent
},
1034 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1035 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1036 { WM_SETFOCUS
, sent
}, /* in MDI client */
1038 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1039 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1040 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1041 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1042 { WM_SETFOCUS
, sent
}, /* in MDI client */
1044 { WM_NCDESTROY
, sent
},
1047 /* CreateWindow for MDI child window, initially invisible */
1048 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
1049 { HCBT_CREATEWND
, hook
},
1050 { WM_NCCREATE
, sent
},
1051 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1052 { WM_CREATE
, sent
},
1055 /* Win2k sends wparam set to
1056 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1057 * while Win9x doesn't bother to set child window id according to
1058 * CLIENTCREATESTRUCT.idFirstChild
1060 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1063 /* DestroyWindow for MDI child window, initially invisible */
1064 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
1065 { HCBT_DESTROYWND
, hook
},
1066 /* Win2k sends wparam set to
1067 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1068 * while Win9x doesn't bother to set child window id according to
1069 * CLIENTCREATESTRUCT.idFirstChild
1071 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1072 { WM_DESTROY
, sent
},
1073 { WM_NCDESTROY
, sent
},
1076 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1077 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
1078 { HCBT_CREATEWND
, hook
},
1079 { WM_NCCREATE
, sent
},
1080 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1081 { WM_CREATE
, sent
},
1084 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1085 { WM_GETMINMAXINFO
, sent
},
1086 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1087 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1088 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1089 { WM_SIZE
, sent
|defwinproc
},
1091 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1092 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1093 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1094 /* Win2k sends wparam set to
1095 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1096 * while Win9x doesn't bother to set child window id according to
1097 * CLIENTCREATESTRUCT.idFirstChild
1099 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1100 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1101 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1102 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1103 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1104 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1105 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1106 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1108 /* Win9x: message sequence terminates here. */
1110 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1111 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1112 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1113 { WM_SETFOCUS
, sent
}, /* in MDI client */
1114 { HCBT_SETFOCUS
, hook
},
1115 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1116 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1117 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1118 { WM_SETFOCUS
, sent
|defwinproc
},
1119 { WM_MDIACTIVATE
, sent
|defwinproc
},
1121 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1122 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1123 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1126 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1127 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
1128 /* restore the 1st MDI child */
1129 { WM_SETREDRAW
, sent
|wparam
, 0 },
1130 { HCBT_MINMAX
, hook
},
1131 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1132 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1133 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1134 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1135 { WM_SIZE
, sent
|defwinproc
},
1137 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1138 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1139 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1140 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
1141 /* create the 2nd MDI child */
1142 { HCBT_CREATEWND
, hook
},
1143 { WM_NCCREATE
, sent
},
1144 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1145 { WM_CREATE
, sent
},
1148 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1149 { WM_GETMINMAXINFO
, sent
},
1150 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1151 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1152 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1153 { WM_SIZE
, sent
|defwinproc
},
1155 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1156 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1157 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1158 /* Win2k sends wparam set to
1159 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1160 * while Win9x doesn't bother to set child window id according to
1161 * CLIENTCREATESTRUCT.idFirstChild
1163 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1164 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1165 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1166 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1167 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1168 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1169 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1171 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1172 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1174 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1176 /* Win9x: message sequence terminates here. */
1178 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1179 { HCBT_SETFOCUS
, hook
},
1180 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
1181 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
1182 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1183 { WM_SETFOCUS
, sent
}, /* in MDI client */
1184 { HCBT_SETFOCUS
, hook
},
1185 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1186 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1187 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1188 { WM_SETFOCUS
, sent
|defwinproc
},
1190 { WM_MDIACTIVATE
, sent
|defwinproc
},
1192 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1193 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1194 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1197 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1198 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
1199 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
1200 { HCBT_SYSCOMMAND
, hook
},
1201 { WM_CLOSE
, sent
|defwinproc
},
1202 { WM_MDIDESTROY
, sent
}, /* in MDI client */
1204 /* bring the 1st MDI child to top */
1205 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
1206 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
1207 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
1208 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1209 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1211 /* maximize the 1st MDI child */
1212 { HCBT_MINMAX
, hook
},
1213 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1214 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|0x8000 },
1215 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1216 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
1217 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1218 { WM_SIZE
, sent
|defwinproc
},
1220 /* restore the 2nd MDI child */
1221 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
1222 { HCBT_MINMAX
, hook
},
1223 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOZORDER
|0x8000 },
1224 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1225 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1226 { WM_SIZE
, sent
|defwinproc
},
1227 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
1229 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1230 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1231 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1233 /* bring the 1st MDI child to top */
1234 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1235 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1236 { HCBT_SETFOCUS
, hook
},
1237 { WM_KILLFOCUS
, sent
|defwinproc
},
1238 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
1239 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1240 { WM_SETFOCUS
, sent
}, /* in MDI client */
1241 { HCBT_SETFOCUS
, hook
},
1242 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1243 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1244 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1245 { WM_SETFOCUS
, sent
|defwinproc
},
1246 { WM_MDIACTIVATE
, sent
|defwinproc
},
1247 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1249 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1250 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1251 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1252 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1253 { WM_MDIREFRESHMENU
, sent
},
1255 { HCBT_DESTROYWND
, hook
},
1256 /* Win2k sends wparam set to
1257 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1258 * while Win9x doesn't bother to set child window id according to
1259 * CLIENTCREATESTRUCT.idFirstChild
1261 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1262 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
1263 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1264 { WM_ERASEBKGND
, sent
|parent
|optional
},
1265 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1267 { WM_DESTROY
, sent
|defwinproc
},
1268 { WM_NCDESTROY
, sent
|defwinproc
},
1272 static HWND mdi_client
;
1273 static WNDPROC old_mdi_client_proc
;
1275 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1279 /* do not log painting messages */
1280 if (message
!= WM_PAINT
&&
1281 message
!= WM_ERASEBKGND
&&
1282 message
!= WM_NCPAINT
&&
1283 message
!= WM_GETTEXT
)
1285 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1289 case WM_WINDOWPOSCHANGING
:
1290 case WM_WINDOWPOSCHANGED
:
1292 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1294 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1295 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1296 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1297 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1299 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1300 * in the high word for internal purposes
1302 wParam
= winpos
->flags
& 0xffff;
1307 msg
.message
= message
;
1308 msg
.flags
= sent
|wparam
|lparam
;
1309 msg
.wParam
= wParam
;
1310 msg
.lParam
= lParam
;
1314 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
1317 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1319 static long defwndproc_counter
= 0;
1323 /* do not log painting messages */
1324 if (message
!= WM_PAINT
&&
1325 message
!= WM_ERASEBKGND
&&
1326 message
!= WM_NCPAINT
&&
1327 message
!= WM_GETTEXT
)
1329 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1333 case WM_WINDOWPOSCHANGING
:
1334 case WM_WINDOWPOSCHANGED
:
1336 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1338 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1339 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1340 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1341 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1343 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1344 * in the high word for internal purposes
1346 wParam
= winpos
->flags
& 0xffff;
1351 msg
.message
= message
;
1352 msg
.flags
= sent
|wparam
|lparam
;
1353 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1354 msg
.wParam
= wParam
;
1355 msg
.lParam
= lParam
;
1359 defwndproc_counter
++;
1360 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
1361 defwndproc_counter
--;
1366 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1368 static long defwndproc_counter
= 0;
1372 /* do not log painting messages */
1373 if (message
!= WM_PAINT
&&
1374 message
!= WM_ERASEBKGND
&&
1375 message
!= WM_NCPAINT
&&
1376 message
!= WM_GETTEXT
)
1378 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1382 case WM_WINDOWPOSCHANGING
:
1383 case WM_WINDOWPOSCHANGED
:
1385 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1387 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1388 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1389 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1390 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1392 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1393 * in the high word for internal purposes
1395 wParam
= winpos
->flags
& 0xffff;
1400 msg
.message
= message
;
1401 msg
.flags
= sent
|wparam
|lparam
;
1402 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1403 msg
.wParam
= wParam
;
1404 msg
.lParam
= lParam
;
1408 defwndproc_counter
++;
1409 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
1410 defwndproc_counter
--;
1415 static BOOL
mdi_RegisterWindowClasses(void)
1420 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
1423 cls
.hInstance
= GetModuleHandleA(0);
1425 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
1426 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
1427 cls
.lpszMenuName
= NULL
;
1428 cls
.lpszClassName
= "MDI_frame_class";
1429 if (!RegisterClassA(&cls
)) return FALSE
;
1431 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
1432 cls
.lpszClassName
= "MDI_child_class";
1433 if (!RegisterClassA(&cls
)) return FALSE
;
1435 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
1436 old_mdi_client_proc
= cls
.lpfnWndProc
;
1437 cls
.hInstance
= GetModuleHandleA(0);
1438 cls
.lpfnWndProc
= mdi_client_hook_proc
;
1439 cls
.lpszClassName
= "MDI_client_class";
1440 if (!RegisterClassA(&cls
)) assert(0);
1445 static void test_mdi_messages(void)
1447 CLIENTCREATESTRUCT client_cs
;
1448 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
1451 assert(mdi_RegisterWindowClasses());
1455 trace("creating MDI frame window\n");
1456 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1457 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
1458 WS_MAXIMIZEBOX
| WS_VISIBLE
,
1459 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
1460 GetDesktopWindow(), 0,
1461 GetModuleHandleA(0), NULL
);
1463 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", TRUE
);
1465 trace("creating MDI client window\n");
1466 client_cs
.hWindowMenu
= 0;
1467 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
1468 mdi_client
= CreateWindowExA(0, "MDI_client_class",
1470 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
1472 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
1474 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
1476 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
1478 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1479 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
1480 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1485 trace("creating visible MDI child window\n");
1486 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1487 WS_CHILD
| WS_VISIBLE
,
1488 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1489 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1491 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", TRUE
);
1493 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1494 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
1496 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1497 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
1498 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1501 DestroyWindow(mdi_child
);
1502 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
1504 /* Win2k: MDI client still returns a just destroyed child as active
1505 * Win9x: MDI client returns 0
1507 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1508 ok(active_child
== mdi_child
|| /* win2k */
1509 !active_child
, /* win9x */
1510 "wrong active MDI child %p\n", active_child
);
1511 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1516 trace("creating invisible MDI child window\n");
1517 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1519 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1520 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1522 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", TRUE
);
1524 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
1525 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
1527 /* Win2k: MDI client still returns a just destroyed child as active
1528 * Win9x: MDI client returns mdi_child2
1530 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1531 ok(active_child
== mdi_child
|| /* win2k */
1532 active_child
== mdi_child2
, /* win9x */
1533 "wrong active MDI child %p\n", active_child
);
1534 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1537 ShowWindow(mdi_child2
, SW_SHOW
);
1538 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", TRUE
);
1540 ShowWindow(mdi_child2
, SW_HIDE
);
1541 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
1543 DestroyWindow(mdi_child2
);
1544 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", TRUE
);
1546 /* test for maximized MDI children */
1547 trace("creating maximized visible MDI child window 1\n");
1548 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1549 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1550 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1551 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1553 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
1554 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
1556 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1557 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
1558 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1561 trace("creating maximized visible MDI child window 2\n");
1562 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1563 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1564 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1565 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1567 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
1568 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
1569 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
1571 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1572 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1573 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1576 DestroyWindow(mdi_child2
);
1577 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
1579 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
1580 ok(GetFocus() == 0, "GetFocus() = %p\n", GetFocus());
1582 /* Win2k: MDI client still returns a just destroyed child as active
1583 * Win9x: MDI client returns 0
1585 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1586 ok(active_child
== mdi_child2
|| /* win2k */
1587 !active_child
, /* win9x */
1588 "wrong active MDI child %p\n", active_child
);
1591 ShowWindow(mdi_child
, SW_MAXIMIZE
);
1592 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
1595 trace("re-creating maximized visible MDI child window 2\n");
1596 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1597 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1598 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1599 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1601 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
1602 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
1603 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
1605 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1606 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1607 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1610 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1611 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
1612 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
1614 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
1616 ok(GetFocus() == mdi_child
, "GetFocus() = %p\n", GetFocus());
1619 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1620 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
1621 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1624 DestroyWindow(mdi_child
);
1625 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
1627 /* Win2k: MDI client still returns a just destroyed child as active
1628 * Win9x: MDI client returns 0
1630 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1631 ok(active_child
== mdi_child
|| /* win2k */
1632 !active_child
, /* win9x */
1633 "wrong active MDI child %p\n", active_child
);
1635 /* end of test for maximized MDI children */
1637 DestroyWindow(mdi_client
);
1638 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
1640 DestroyWindow(mdi_frame
);
1641 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
1643 /************************* End of MDI test **********************************/
1645 static void test_WM_SETREDRAW(HWND hwnd
)
1647 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1651 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
1652 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
1654 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
1655 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
1658 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
1659 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
1661 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
1662 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
1664 /* restore original WS_VISIBLE state */
1665 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
1670 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1674 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1676 msg
.message
= message
;
1677 msg
.flags
= sent
|wparam
|lparam
;
1678 msg
.wParam
= wParam
;
1679 msg
.lParam
= lParam
;
1682 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
1683 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
1687 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
1689 DWORD style
, exstyle
;
1692 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1693 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1694 /* do not be confused by WS_DLGFRAME set */
1695 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
1697 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
1698 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
1700 ok(SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
), "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
1701 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
1702 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
1704 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", TRUE
);
1706 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1707 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
1708 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
1710 /* a subsequent call should do nothing */
1711 ok(SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
), "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
1712 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
1716 trace("Ignore GetScrollRange error below if you are on Win9x\n");
1717 ok(GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
), "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
1718 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
1719 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
1720 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
1723 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
1725 DWORD style
, exstyle
;
1728 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1729 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1730 /* do not be confused by WS_DLGFRAME set */
1731 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
1733 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
1734 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
1736 si
.cbSize
= sizeof(si
);
1737 si
.fMask
= SIF_RANGE
;
1740 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
1741 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
1742 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
1744 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", TRUE
);
1746 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1747 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
1748 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
1750 /* a subsequent call should do nothing */
1751 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
1752 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
1754 si
.fMask
= SIF_PAGE
;
1756 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
1757 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
1761 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
1762 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
1764 si
.fMask
= SIF_RANGE
;
1765 si
.nMin
= 0xdeadbeef;
1766 si
.nMax
= 0xdeadbeef;
1767 ok(GetScrollInfo(hwnd
, ctl
, &si
), "GetScrollInfo error %ld\n", GetLastError());
1768 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
1769 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
1770 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
1773 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
1774 static void test_scroll_messages(HWND hwnd
)
1781 ok(GetScrollRange(hwnd
, SB_CTL
, &min
, &max
), "GetScrollRange error %ld\n", GetLastError());
1782 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
1783 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1784 /* values of min and max are undefined */
1787 ok(SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
), "SetScrollRange error %ld\n", GetLastError());
1788 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1789 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1794 ok(GetScrollRange(hwnd
, SB_CTL
, &min
, &max
), "GetScrollRange error %ld\n", GetLastError());
1795 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
1796 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1797 /* values of min and max are undefined */
1800 si
.cbSize
= sizeof(si
);
1801 si
.fMask
= SIF_RANGE
;
1804 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
1805 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1806 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1809 si
.fMask
= SIF_PAGE
;
1811 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
1812 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1813 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1818 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
1819 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
1820 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1823 si
.fMask
= SIF_RANGE
;
1824 si
.nMin
= 0xdeadbeef;
1825 si
.nMax
= 0xdeadbeef;
1826 ok(GetScrollInfo(hwnd
, SB_CTL
, &si
), "GetScrollInfo error %ld\n", GetLastError());
1827 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
1828 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
1829 /* values of min and max are undefined */
1832 /* set WS_HSCROLL */
1833 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
1834 /* clear WS_HSCROLL */
1835 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
1837 /* set WS_HSCROLL */
1838 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
1839 /* clear WS_HSCROLL */
1840 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
1842 /* set WS_VSCROLL */
1843 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
1844 /* clear WS_VSCROLL */
1845 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
1847 /* set WS_VSCROLL */
1848 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
1849 /* clear WS_VSCROLL */
1850 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
1853 /* test if we receive the right sequence of messages */
1854 static void test_messages(void)
1856 HWND hwnd
, hparent
, hchild
;
1857 HWND hchild2
, hbutton
;
1860 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
1861 100, 100, 200, 200, 0, 0, 0, NULL
);
1862 ok (hwnd
!= 0, "Failed to create overlapped window\n");
1863 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
1865 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
1866 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
1867 ok_sequence(WmHideInvisibleOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
1869 /* test WM_SETREDRAW on a not visible top level window */
1870 test_WM_SETREDRAW(hwnd
);
1872 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1873 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
1874 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
1876 ok(GetActiveWindow() == hwnd
, "window should be active\n");
1877 ok(GetFocus() == hwnd
, "window should have input focus\n");
1878 ShowWindow(hwnd
, SW_HIDE
);
1879 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", TRUE
);
1881 ShowWindow(hwnd
, SW_SHOW
);
1882 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
1884 ok(GetActiveWindow() == hwnd
, "window should be active\n");
1885 ok(GetFocus() == hwnd
, "window should have input focus\n");
1886 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1887 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
1888 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
1890 /* test WM_SETREDRAW on a visible top level window */
1891 ShowWindow(hwnd
, SW_SHOW
);
1892 test_WM_SETREDRAW(hwnd
);
1894 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
1895 test_scroll_messages(hwnd
);
1897 DestroyWindow(hwnd
);
1898 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
1900 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
1901 100, 100, 200, 200, 0, 0, 0, NULL
);
1902 ok (hparent
!= 0, "Failed to create parent window\n");
1905 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
1906 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1907 ok (hchild
!= 0, "Failed to create child window\n");
1908 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", TRUE
);
1909 DestroyWindow(hchild
);
1912 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
1913 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1914 ok (hchild
!= 0, "Failed to create child window\n");
1915 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
1917 trace("testing scroll APIs on a visible child window %p\n", hchild
);
1918 test_scroll_messages(hchild
);
1920 DestroyWindow(hchild
);
1923 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
1924 0, 0, 10, 10, hparent
, 0, 0, NULL
);
1925 ok (hchild
!= 0, "Failed to create child window\n");
1926 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
1928 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
1929 100, 100, 50, 50, hparent
, 0, 0, NULL
);
1930 ok (hchild2
!= 0, "Failed to create child2 window\n");
1933 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
1934 0, 100, 50, 50, hchild
, 0, 0, NULL
);
1935 ok (hbutton
!= 0, "Failed to create button window\n");
1937 /* test WM_SETREDRAW on a not visible child window */
1938 test_WM_SETREDRAW(hchild
);
1940 ShowWindow(hchild
, SW_SHOW
);
1941 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
1943 ShowWindow(hchild
, SW_HIDE
);
1944 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
1946 ShowWindow(hchild
, SW_SHOW
);
1947 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
1949 /* test WM_SETREDRAW on a visible child window */
1950 test_WM_SETREDRAW(hchild
);
1952 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
1953 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
1955 ShowWindow(hchild
, SW_HIDE
);
1957 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1958 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
1960 ShowWindow(hchild
, SW_HIDE
);
1962 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
1963 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
1965 /* DestroyWindow sequence below expects that a child has focus */
1969 DestroyWindow(hchild
);
1970 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
1971 DestroyWindow(hchild2
);
1972 DestroyWindow(hbutton
);
1975 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
1976 0, 0, 100, 100, hparent
, 0, 0, NULL
);
1977 ok (hchild
!= 0, "Failed to create child popup window\n");
1978 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
1979 DestroyWindow(hchild
);
1981 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
1983 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
1984 0, 0, 100, 100, hparent
, 0, 0, NULL
);
1985 ok (hchild
!= 0, "Failed to create popup window\n");
1986 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
1987 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
1988 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
1990 ShowWindow(hchild
, SW_SHOW
);
1991 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
1993 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1994 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
1996 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
1997 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
1998 DestroyWindow(hchild
);
2000 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2001 * changes nothing in message sequences.
2004 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
2005 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2006 ok (hchild
!= 0, "Failed to create popup window\n");
2007 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
2008 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2009 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
2011 ShowWindow(hchild
, SW_SHOW
);
2012 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
2014 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2015 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
2016 DestroyWindow(hchild
);
2019 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
2020 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2021 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
2022 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
2024 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
2025 test_scroll_messages(hwnd
);
2028 after_end_dialog
= 1;
2029 EndDialog( hwnd
, 0 );
2030 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
2032 DestroyWindow(hwnd
);
2033 after_end_dialog
= 0;
2036 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
2037 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
2039 /* test showing child with hidden parent */
2040 ShowWindow( hparent
, SW_HIDE
);
2043 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
2044 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2045 ok (hchild
!= 0, "Failed to create child window\n");
2046 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
2048 ShowWindow( hchild
, SW_SHOW
);
2049 ok_sequence(WmShowChildInvisibleParentSeq
, "ShowWindow:show child with invisible parent", TRUE
);
2050 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2051 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2053 ShowWindow( hchild
, SW_HIDE
);
2054 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", TRUE
);
2055 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
2056 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2058 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2059 ok_sequence(WmShowChildInvisibleParentSeq_2
, "SetWindowPos:show child with invisible parent", TRUE
);
2060 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2061 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2063 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2064 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", TRUE
);
2065 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
2066 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2068 DestroyWindow(hparent
);
2071 /* Message sequence for SetMenu */
2072 hmenu
= CreateMenu();
2073 ok (hmenu
!= 0, "Failed to create menu\n");
2074 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
2075 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2076 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
2077 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
2078 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2079 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
2080 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2081 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
2082 ShowWindow(hwnd
, SW_SHOW
);
2084 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2085 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", TRUE
);
2086 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
2087 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", TRUE
);
2089 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
2090 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", TRUE
);
2092 DestroyWindow(hwnd
);
2095 /* Message sequence for EnableWindow */
2096 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
2097 100, 100, 200, 200, 0, 0, 0, NULL
);
2098 ok (hparent
!= 0, "Failed to create parent window\n");
2099 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
2100 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2101 ok (hchild
!= 0, "Failed to create child window\n");
2106 EnableWindow(hparent
, FALSE
);
2107 ok_sequence(WmEnableWindowSeq
, "EnableWindow", FALSE
);
2109 DestroyWindow(hparent
);
2113 /****************** button message test *************************/
2114 static const struct message WmSetFocusButtonSeq
[] =
2116 { HCBT_SETFOCUS
, hook
},
2117 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2118 { WM_SETFOCUS
, sent
|wparam
, 0 },
2119 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2122 static const struct message WmKillFocusButtonSeq
[] =
2124 { HCBT_SETFOCUS
, hook
},
2125 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2126 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2127 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2130 static const struct message WmSetFocusStaticSeq
[] =
2132 { HCBT_SETFOCUS
, hook
},
2133 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2134 { WM_SETFOCUS
, sent
|wparam
, 0 },
2135 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
2138 static const struct message WmKillFocusStaticSeq
[] =
2140 { HCBT_SETFOCUS
, hook
},
2141 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2142 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
2143 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2146 static const struct message WmLButtonDownSeq
[] =
2148 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
2149 { HCBT_SETFOCUS
, hook
},
2150 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2151 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2152 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2153 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
2154 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2157 static const struct message WmLButtonUpSeq
[] =
2159 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
2160 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
2161 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2162 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
2166 static WNDPROC old_button_proc
;
2168 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2170 static long defwndproc_counter
= 0;
2174 trace("button: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2176 msg
.message
= message
;
2177 msg
.flags
= sent
|wparam
|lparam
;
2178 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2179 msg
.wParam
= wParam
;
2180 msg
.lParam
= lParam
;
2183 if (message
== BM_SETSTATE
)
2184 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
2186 defwndproc_counter
++;
2187 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
2188 defwndproc_counter
--;
2193 static void subclass_button(void)
2197 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
2199 old_button_proc
= cls
.lpfnWndProc
;
2201 cls
.hInstance
= GetModuleHandle(0);
2202 cls
.lpfnWndProc
= button_hook_proc
;
2203 cls
.lpszClassName
= "my_button_class";
2204 if (!RegisterClassA(&cls
)) assert(0);
2207 static void test_button_messages(void)
2212 const struct message
*setfocus
;
2213 const struct message
*killfocus
;
2215 { BS_PUSHBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2216 { BS_DEFPUSHBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2217 { BS_CHECKBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2218 { BS_AUTOCHECKBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2219 { BS_RADIOBUTTON
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2220 { BS_3STATE
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2221 { BS_AUTO3STATE
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2222 { BS_GROUPBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2223 { BS_USERBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2224 { BS_AUTORADIOBUTTON
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2225 { BS_OWNERDRAW
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
}
2232 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
2234 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
,
2235 0, 0, 50, 14, 0, 0, 0, NULL
);
2236 ok(hwnd
!= 0, "Failed to create button window\n");
2238 ShowWindow(hwnd
, SW_SHOW
);
2243 trace("button style %08lx\n", button
[i
].style
);
2245 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
2248 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
2250 DestroyWindow(hwnd
);
2253 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
2254 0, 0, 50, 14, 0, 0, 0, NULL
);
2255 ok(hwnd
!= 0, "Failed to create button window\n");
2260 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
2261 ok_sequence(WmLButtonDownSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
2263 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
2264 ok_sequence(WmLButtonUpSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
2265 DestroyWindow(hwnd
);
2268 /************* painting message test ********************/
2270 static void dump_region(HRGN hrgn
)
2273 RGNDATA
*data
= NULL
;
2278 printf( "null region\n" );
2281 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
2282 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
2283 GetRegionData( hrgn
, size
, data
);
2284 printf("%ld rects:", data
->rdh
.nCount
);
2285 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
2286 printf( " (%ld,%ld)-(%ld,%ld)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
2288 HeapFree( GetProcessHeap(), 0, data
);
2291 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
2295 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
2296 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
2298 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
2299 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
2300 if (ret
== NULLREGION
)
2302 ok( !hrgn
, "Update region shouldn't be empty\n" );
2306 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
2308 ok( 0, "Regions are different\n" );
2309 if (winetest_debug
> 0)
2311 printf( "Update region: " );
2312 dump_region( update
);
2313 printf( "Wanted region: " );
2314 dump_region( hrgn
);
2318 GetRgnBox( update
, &r1
);
2319 GetUpdateRect( hwnd
, &r2
, FALSE
);
2320 ok( r1
.left
== r2
.left
&& r1
.top
== r2
.top
&& r1
.right
== r2
.right
&& r1
.bottom
== r2
.bottom
,
2321 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
2322 r1
.left
, r1
.top
, r1
.right
, r1
.bottom
, r2
.left
, r2
.top
, r2
.right
, r2
.bottom
);
2324 DeleteObject( tmp
);
2325 DeleteObject( update
);
2328 static const struct message WmInvalidateRgn
[] = {
2329 { WM_NCPAINT
, sent
},
2330 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2334 static const struct message WmInvalidateFull
[] = {
2335 { WM_NCPAINT
, sent
|wparam
, 1 },
2336 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2340 static const struct message WmInvalidateErase
[] = {
2341 { WM_NCPAINT
, sent
|wparam
, 1 },
2342 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2343 { WM_ERASEBKGND
, sent
},
2347 static const struct message WmInvalidatePaint
[] = {
2349 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
2350 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2354 static const struct message WmInvalidateErasePaint
[] = {
2356 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
2357 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2358 { WM_ERASEBKGND
, sent
|beginpaint
},
2362 static const struct message WmErase
[] = {
2363 { WM_ERASEBKGND
, sent
},
2367 static const struct message WmPaint
[] = {
2372 static void test_paint_messages(void)
2376 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
2377 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
2378 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2379 100, 100, 200, 200, 0, 0, 0, NULL
);
2380 ok (hwnd
!= 0, "Failed to create overlapped window\n");
2382 ShowWindow( hwnd
, SW_SHOW
);
2383 UpdateWindow( hwnd
);
2384 check_update_rgn( hwnd
, 0 );
2385 SetRectRgn( hrgn
, 10, 10, 20, 20 );
2386 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
2387 check_update_rgn( hwnd
, hrgn
);
2388 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
2389 RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
2390 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
2391 check_update_rgn( hwnd
, hrgn
);
2392 /* validate everything */
2393 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
2394 check_update_rgn( hwnd
, 0 );
2395 /* now with frame */
2396 SetRectRgn( hrgn
, -5, -5, 20, 20 );
2399 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2400 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
2402 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
2403 check_update_rgn( hwnd
, hrgn
);
2406 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
2407 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2410 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
2411 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
2413 GetClientRect( hwnd
, &rect
);
2414 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2415 check_update_rgn( hwnd
, hrgn
);
2418 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
2419 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
2422 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
2423 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", TRUE
);
2424 check_update_rgn( hwnd
, 0 );
2427 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
2428 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
2429 check_update_rgn( hwnd
, 0 );
2432 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2433 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
2434 SetRectRgn( hrgn
, 0, 0, 50, 100 );
2435 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
2436 SetRectRgn( hrgn
, 50, 0, 100, 100 );
2437 check_update_rgn( hwnd
, hrgn
);
2438 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
2439 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
2440 check_update_rgn( hwnd
, 0 );
2443 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2444 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
2445 SetRectRgn( hrgn
, 0, 0, 100, 50 );
2446 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
2447 ok_sequence( WmErase
, "Erase", FALSE
);
2448 SetRectRgn( hrgn
, 0, 50, 100, 100 );
2449 check_update_rgn( hwnd
, hrgn
);
2452 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2453 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
2454 SetRectRgn( hrgn
, 0, 0, 50, 50 );
2455 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
2456 ok_sequence( WmPaint
, "Paint", FALSE
);
2459 SetRectRgn( hrgn
, -4, -4, -2, -2 );
2460 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2461 SetRectRgn( hrgn
, -4, -4, -3, -3 );
2462 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
2463 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
2466 SetRectRgn( hrgn
, -4, -4, -2, -2 );
2467 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2468 SetRectRgn( hrgn
, -4, -4, -3, -3 );
2469 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
2470 SetRectRgn( hrgn
, 0, 0, 1, 1 );
2471 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
2472 ok_sequence( WmPaint
, "Paint", TRUE
);
2475 SetRectRgn( hrgn
, -4, -4, -1, -1 );
2476 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2477 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
2478 /* make sure no WM_PAINT was generated */
2479 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
2480 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2483 SetRectRgn( hrgn
, -4, -4, -1, -1 );
2484 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2485 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
2487 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
2489 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
2490 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
2491 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
2492 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
2493 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
2494 /* this will send WM_NCPAINT and validate the non client area */
2495 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
2496 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
2498 else DispatchMessage( &msg
);
2500 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2502 DeleteObject( hrgn
);
2503 DeleteObject( hrgn2
);
2504 DestroyWindow( hwnd
);
2508 /************* window procedures ********************/
2510 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2512 static long defwndproc_counter
= 0;
2513 static long beginpaint_counter
= 0;
2517 trace("%p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2521 case WM_WINDOWPOSCHANGING
:
2522 case WM_WINDOWPOSCHANGED
:
2524 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
2526 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2527 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2528 winpos
->hwnd
, winpos
->hwndInsertAfter
,
2529 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
2531 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2532 * in the high word for internal purposes
2534 wParam
= winpos
->flags
& 0xffff;
2539 msg
.message
= message
;
2540 msg
.flags
= sent
|wparam
|lparam
;
2541 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2542 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
2543 msg
.wParam
= wParam
;
2544 msg
.lParam
= lParam
;
2547 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
2549 HWND parent
= GetParent(hwnd
);
2551 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
2553 GetClientRect(parent
, &rc
);
2554 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
2556 trace("ptReserved = (%ld,%ld)\n"
2557 "ptMaxSize = (%ld,%ld)\n"
2558 "ptMaxPosition = (%ld,%ld)\n"
2559 "ptMinTrackSize = (%ld,%ld)\n"
2560 "ptMaxTrackSize = (%ld,%ld)\n",
2561 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
2562 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
2563 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
2564 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
2565 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
2567 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
2568 minmax
->ptMaxSize
.x
, rc
.right
);
2569 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
2570 minmax
->ptMaxSize
.y
, rc
.bottom
);
2573 if (message
== WM_PAINT
)
2576 beginpaint_counter
++;
2577 BeginPaint( hwnd
, &ps
);
2578 beginpaint_counter
--;
2579 EndPaint( hwnd
, &ps
);
2583 defwndproc_counter
++;
2584 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2585 defwndproc_counter
--;
2590 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2592 static long defwndproc_counter
= 0;
2596 trace("popup: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2598 msg
.message
= message
;
2599 msg
.flags
= sent
|wparam
|lparam
;
2600 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2601 msg
.wParam
= wParam
;
2602 msg
.lParam
= lParam
;
2605 if (message
== WM_CREATE
)
2607 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
2608 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
2611 defwndproc_counter
++;
2612 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2613 defwndproc_counter
--;
2618 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2620 static long defwndproc_counter
= 0;
2624 trace("parent: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2626 if (message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
2627 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
2628 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
2629 message
== WM_IME_SETCONTEXT
)
2631 msg
.message
= message
;
2632 msg
.flags
= sent
|parent
|wparam
|lparam
;
2633 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2634 msg
.wParam
= wParam
;
2635 msg
.lParam
= lParam
;
2639 defwndproc_counter
++;
2640 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2641 defwndproc_counter
--;
2646 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2648 static long defwndproc_counter
= 0;
2652 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2654 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
2655 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
2656 if (after_end_dialog
)
2657 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
2659 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
2661 msg
.message
= message
;
2662 msg
.flags
= sent
|wparam
|lparam
;
2663 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2664 msg
.wParam
= wParam
;
2665 msg
.lParam
= lParam
;
2668 defwndproc_counter
++;
2669 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
2670 defwndproc_counter
--;
2675 static BOOL
RegisterWindowClasses(void)
2680 cls
.lpfnWndProc
= MsgCheckProcA
;
2683 cls
.hInstance
= GetModuleHandleA(0);
2685 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
2686 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
2687 cls
.lpszMenuName
= NULL
;
2688 cls
.lpszClassName
= "TestWindowClass";
2689 if(!RegisterClassA(&cls
)) return FALSE
;
2691 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
2692 cls
.lpszClassName
= "TestPopupClass";
2693 if(!RegisterClassA(&cls
)) return FALSE
;
2695 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
2696 cls
.lpszClassName
= "TestParentClass";
2697 if(!RegisterClassA(&cls
)) return FALSE
;
2699 cls
.lpfnWndProc
= DefWindowProcA
;
2700 cls
.lpszClassName
= "SimpleWindowClass";
2701 if(!RegisterClassA(&cls
)) return FALSE
;
2703 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
2704 cls
.lpfnWndProc
= TestDlgProcA
;
2705 cls
.lpszClassName
= "TestDialogClass";
2706 if(!RegisterClassA(&cls
)) return FALSE
;
2711 static HHOOK hCBT_hook
;
2713 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
2717 trace("CBT: %d, %08x, %08lx\n", nCode
, wParam
, lParam
);
2719 if (nCode
== HCBT_SYSCOMMAND
)
2723 msg
.message
= nCode
;
2725 msg
.wParam
= wParam
;
2726 msg
.lParam
= lParam
;
2729 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
2732 /* Log also SetFocus(0) calls */
2733 if (!wParam
) wParam
= lParam
;
2735 if (GetClassNameA((HWND
)wParam
, buf
, sizeof(buf
)))
2737 if (!strcmp(buf
, "TestWindowClass") ||
2738 !strcmp(buf
, "TestParentClass") ||
2739 !strcmp(buf
, "TestPopupClass") ||
2740 !strcmp(buf
, "SimpleWindowClass") ||
2741 !strcmp(buf
, "TestDialogClass") ||
2742 !strcmp(buf
, "MDI_frame_class") ||
2743 !strcmp(buf
, "MDI_client_class") ||
2744 !strcmp(buf
, "MDI_child_class") ||
2745 !strcmp(buf
, "my_button_class") ||
2746 !strcmp(buf
, "#32770"))
2750 msg
.message
= nCode
;
2752 msg
.wParam
= wParam
;
2753 msg
.lParam
= lParam
;
2757 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
2762 if (!RegisterWindowClasses()) assert(0);
2764 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
2768 test_mdi_messages();
2769 test_button_messages();
2770 test_paint_messages();
2772 UnhookWindowsHookEx(hCBT_hook
);