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 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
320 * for a visible child window with a caption
322 static const struct message WmShowChildSeq_4
[] = {
323 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
324 { WM_CHILDACTIVATE
, sent
},
327 /* ShowWindow(SW_SHOW) for child with invisible parent */
328 static const struct message WmShowChildInvisibleParentSeq
[] = {
329 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
332 /* ShowWindow(SW_HIDE) for child with invisible parent */
333 static const struct message WmHideChildInvisibleParentSeq
[] = {
334 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
337 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
338 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
339 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
},
340 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
343 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
344 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
345 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
346 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
349 /* DestroyWindow for a visible child window */
350 static const struct message WmDestroyChildSeq
[] = {
351 { HCBT_DESTROYWND
, hook
},
352 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
353 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
354 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
355 { WM_ERASEBKGND
, sent
|parent
|optional
},
356 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
357 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
358 { WM_KILLFOCUS
, sent
},
359 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
360 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
361 { WM_SETFOCUS
, sent
|parent
},
362 { WM_DESTROY
, sent
},
363 { WM_DESTROY
, sent
|optional
}, /* a bug in win2k sp4 ? */
364 { WM_NCDESTROY
, sent
},
365 { WM_NCDESTROY
, sent
|optional
}, /* a bug in win2k sp4 ? */
368 /* Moving the mouse in nonclient area */
369 static const struct message WmMouseMoveInNonClientAreaSeq
[] = { /* FIXME: add */
370 { WM_NCHITTEST
, sent
},
371 { WM_SETCURSOR
, sent
},
372 { WM_NCMOUSEMOVE
, posted
},
375 /* Moving the mouse in client area */
376 static const struct message WmMouseMoveInClientAreaSeq
[] = { /* FIXME: add */
377 { WM_NCHITTEST
, sent
},
378 { WM_SETCURSOR
, sent
},
379 { WM_MOUSEMOVE
, posted
},
382 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
383 static const struct message WmDragTitleBarSeq
[] = { /* FIXME: add */
384 { WM_NCLBUTTONDOWN
, sent
|wparam
, HTCAPTION
},
385 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_MOVE
+2 },
386 { WM_GETMINMAXINFO
, sent
|defwinproc
},
387 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
388 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
389 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
390 { WM_MOVE
, sent
|defwinproc
},
391 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
394 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
395 static const struct message WmDragThickBordersBarSeq
[] = { /* FIXME: add */
396 { WM_NCLBUTTONDOWN
, sent
|wparam
, 0xd },
397 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, 0xf004 },
398 { WM_GETMINMAXINFO
, sent
|defwinproc
},
399 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
400 { WM_SIZING
, sent
|defwinproc
|wparam
, 4}, /* one for each mouse movement */
401 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
402 { WM_GETMINMAXINFO
, sent
|defwinproc
},
403 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
404 { WM_NCPAINT
, sent
|defwinproc
|wparam
, 1 },
405 { WM_GETTEXT
, sent
|defwinproc
},
406 { WM_ERASEBKGND
, sent
|defwinproc
},
407 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
408 { WM_MOVE
, sent
|defwinproc
},
409 { WM_SIZE
, sent
|defwinproc
},
410 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
413 /* Resizing child window with MoveWindow (32) */
414 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
415 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
416 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
417 { WM_ERASEBKGND
, sent
|optional
},
418 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
419 { WM_MOVE
, sent
|defwinproc
},
420 { WM_SIZE
, sent
|defwinproc
},
423 /* Clicking on inactive button */
424 static const struct message WmClickInactiveButtonSeq
[] = { /* FIXME: add */
425 { WM_NCHITTEST
, sent
},
426 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_LBUTTONDOWN
},
427 { WM_MOUSEACTIVATE
, sent
},
428 { WM_MOUSEACTIVATE
, sent
|parent
|defwinproc
},
429 { WM_SETCURSOR
, sent
},
430 { WM_SETCURSOR
, sent
|parent
|defwinproc
},
431 { WM_LBUTTONDOWN
, posted
},
432 { WM_KILLFOCUS
, posted
|parent
},
433 { WM_SETFOCUS
, posted
},
434 { WM_CTLCOLORBTN
, posted
|parent
},
435 { BM_SETSTATE
, posted
},
436 { WM_CTLCOLORBTN
, posted
|parent
},
437 { WM_LBUTTONUP
, posted
},
438 { BM_SETSTATE
, posted
},
439 { WM_CTLCOLORBTN
, posted
|parent
},
440 { WM_COMMAND
, posted
|parent
},
443 /* Reparenting a button (16/32) */
444 /* The last child (button) reparented gets topmost for its new parent. */
445 static const struct message WmReparentButtonSeq
[] = { /* FIXME: add */
446 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
447 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
448 { WM_ERASEBKGND
, sent
|parent
},
449 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
450 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOZORDER
},
451 { WM_CHILDACTIVATE
, sent
},
452 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOZORDER
},
453 { WM_MOVE
, sent
|defwinproc
},
454 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
457 /* Creation of a custom dialog (32) */
458 static const struct message WmCreateCustomDialogSeq
[] = {
459 { HCBT_CREATEWND
, hook
},
460 { WM_GETMINMAXINFO
, sent
},
461 { WM_NCCREATE
, sent
},
462 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
464 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
465 { HCBT_ACTIVATE
, hook
},
466 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
467 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
468 { WM_NCACTIVATE
, sent
|wparam
, 1 },
469 { WM_GETTEXT
, sent
|optional
|defwinproc
},
470 { WM_GETICON
, sent
|optional
|defwinproc
},
471 { WM_GETICON
, sent
|optional
|defwinproc
},
472 { WM_GETICON
, sent
|optional
|defwinproc
},
473 { WM_GETTEXT
, sent
|optional
|defwinproc
},
474 { WM_ACTIVATE
, sent
|wparam
, 1 },
475 { WM_KILLFOCUS
, sent
|parent
},
476 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
477 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
478 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
479 { WM_SETFOCUS
, sent
},
480 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
481 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
482 { WM_NCPAINT
, sent
|wparam
, 1 },
483 { WM_GETTEXT
, sent
|optional
|defwinproc
},
484 { WM_GETICON
, sent
|optional
|defwinproc
},
485 { WM_GETICON
, sent
|optional
|defwinproc
},
486 { WM_GETICON
, sent
|optional
|defwinproc
},
487 { WM_GETTEXT
, sent
|optional
|defwinproc
},
488 { WM_ERASEBKGND
, sent
},
489 { WM_CTLCOLORDLG
, sent
|defwinproc
},
490 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
491 { WM_GETTEXT
, sent
|optional
},
492 { WM_GETICON
, sent
|optional
},
493 { WM_GETICON
, sent
|optional
},
494 { WM_GETICON
, sent
|optional
},
495 { WM_GETTEXT
, sent
|optional
},
496 { WM_NCCALCSIZE
, sent
|optional
},
497 { WM_NCPAINT
, sent
|optional
},
498 { WM_GETTEXT
, sent
|optional
|defwinproc
},
499 { WM_GETICON
, sent
|optional
|defwinproc
},
500 { WM_GETICON
, sent
|optional
|defwinproc
},
501 { WM_GETICON
, sent
|optional
|defwinproc
},
502 { WM_GETTEXT
, sent
|optional
|defwinproc
},
503 { WM_ERASEBKGND
, sent
|optional
},
504 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
509 /* Calling EndDialog for a custom dialog (32) */
510 static const struct message WmEndCustomDialogSeq
[] = {
511 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
512 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
513 { WM_GETTEXT
, sent
|optional
},
514 { WM_GETICON
, sent
|optional
},
515 { WM_GETICON
, sent
|optional
},
516 { WM_GETICON
, sent
|optional
},
517 { HCBT_ACTIVATE
, hook
},
518 { WM_NCACTIVATE
, sent
|wparam
, 0 },
519 { WM_GETTEXT
, sent
|optional
|defwinproc
},
520 { WM_GETICON
, sent
|optional
|defwinproc
},
521 { WM_GETICON
, sent
|optional
|defwinproc
},
522 { WM_GETICON
, sent
|optional
|defwinproc
},
523 { WM_GETTEXT
, sent
|optional
|defwinproc
},
524 { WM_ACTIVATE
, sent
|wparam
, 0 },
525 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, 0 },
526 { HCBT_SETFOCUS
, hook
},
527 { WM_KILLFOCUS
, sent
},
528 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
529 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
530 { WM_IME_NOTIFY
, sent
|optional
},
531 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
534 /* Creation and destruction of a modal dialog (32) */
535 static const struct message WmModalDialogSeq
[] = {
536 { WM_CANCELMODE
, sent
|parent
},
537 { HCBT_SETFOCUS
, hook
},
538 { WM_KILLFOCUS
, sent
|parent
},
539 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
540 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
541 { HCBT_CREATEWND
, hook
},
542 { WM_SETFONT
, sent
},
543 { WM_INITDIALOG
, sent
},
544 { WM_CHANGEUISTATE
, sent
|optional
},
545 { WM_SHOWWINDOW
, sent
},
546 { HCBT_ACTIVATE
, hook
},
547 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
548 { WM_NCACTIVATE
, sent
|wparam
, 1 },
549 { WM_GETICON
, sent
|optional
},
550 { WM_GETICON
, sent
|optional
},
551 { WM_GETICON
, sent
|optional
},
552 { WM_GETTEXT
, sent
|optional
},
553 { WM_ACTIVATE
, sent
|wparam
, 1 },
554 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
555 { WM_NCPAINT
, sent
},
556 { WM_GETICON
, sent
|optional
},
557 { WM_GETICON
, sent
|optional
},
558 { WM_GETICON
, sent
|optional
},
559 { WM_GETTEXT
, sent
|optional
},
560 { WM_ERASEBKGND
, sent
},
561 { WM_CTLCOLORDLG
, sent
},
562 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
563 { WM_GETICON
, sent
|optional
},
564 { WM_GETICON
, sent
|optional
},
565 { WM_GETICON
, sent
|optional
},
566 { WM_GETTEXT
, sent
|optional
},
567 { WM_NCCALCSIZE
, sent
|optional
},
568 { WM_NCPAINT
, sent
|optional
},
569 { WM_GETICON
, sent
|optional
},
570 { WM_GETICON
, sent
|optional
},
571 { WM_GETICON
, sent
|optional
},
572 { WM_GETTEXT
, sent
|optional
},
573 { WM_ERASEBKGND
, sent
|optional
},
574 { WM_CTLCOLORDLG
, sent
|optional
},
575 { WM_PAINT
, sent
|optional
},
576 { WM_CTLCOLORBTN
, sent
},
577 { WM_ENTERIDLE
, sent
|parent
|optional
},
579 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
580 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
581 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
582 { WM_GETICON
, sent
|optional
},
583 { WM_GETICON
, sent
|optional
},
584 { WM_GETICON
, sent
|optional
},
585 { WM_GETTEXT
, sent
|optional
},
586 { HCBT_ACTIVATE
, hook
},
587 { WM_NCACTIVATE
, sent
|wparam
, 0 },
588 { WM_GETICON
, sent
|optional
},
589 { WM_GETICON
, sent
|optional
},
590 { WM_GETICON
, sent
|optional
},
591 { WM_GETTEXT
, sent
|optional
},
592 { WM_ACTIVATE
, sent
|wparam
, 0 },
593 { WM_WINDOWPOSCHANGING
, sent
|optional
},
594 { HCBT_SETFOCUS
, hook
},
595 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
596 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
597 { HCBT_DESTROYWND
, hook
},
598 { WM_DESTROY
, sent
},
599 { WM_NCDESTROY
, sent
},
602 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
603 static const struct message WmCreateModalDialogResizeSeq
[] = { /* FIXME: add */
604 /* (inside dialog proc, handling WM_INITDIALOG) */
605 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
606 { WM_NCCALCSIZE
, sent
},
607 { WM_NCACTIVATE
, sent
|parent
|wparam
, 0 },
608 { WM_GETTEXT
, sent
|defwinproc
},
609 { WM_ACTIVATE
, sent
|parent
|wparam
, 0 },
610 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
611 { WM_WINDOWPOSCHANGING
, sent
|parent
},
612 { WM_NCACTIVATE
, sent
|wparam
, 1 },
613 { WM_ACTIVATE
, sent
|wparam
, 1 },
614 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
615 { WM_SIZE
, sent
|defwinproc
},
616 /* (setting focus) */
617 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
618 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
619 { WM_NCPAINT
, sent
},
620 { WM_GETTEXT
, sent
|defwinproc
},
621 { WM_ERASEBKGND
, sent
},
622 { WM_CTLCOLORDLG
, sent
|defwinproc
},
623 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
625 /* (bunch of WM_CTLCOLOR* for each control) */
626 { WM_PAINT
, sent
|parent
},
627 { WM_ENTERIDLE
, sent
|parent
|wparam
, 0 },
628 { WM_SETCURSOR
, sent
|parent
},
631 /* SetMenu for NonVisible windows with size change*/
632 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
633 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
634 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
635 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
},
636 { WM_MOVE
, sent
|defwinproc
},
637 { WM_SIZE
, sent
|defwinproc
},
638 { WM_GETICON
, sent
|optional
},
639 { WM_GETICON
, sent
|optional
},
640 { WM_GETICON
, sent
|optional
},
641 { WM_GETTEXT
, sent
|optional
},
642 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
645 /* SetMenu for NonVisible windows with no size change */
646 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
647 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
648 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
649 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
652 /* SetMenu for Visible windows with size change */
653 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
654 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
655 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
656 { WM_NCPAINT
, sent
|wparam
, 1 },
657 { WM_GETTEXT
, sent
|defwinproc
|optional
},
658 { WM_ERASEBKGND
, sent
|optional
},
659 { WM_ACTIVATE
, sent
|optional
},
660 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
661 { WM_MOVE
, sent
|defwinproc
},
662 { WM_SIZE
, sent
|defwinproc
},
663 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
664 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
665 { WM_ERASEBKGND
, sent
|optional
},
668 /* SetMenu for Visible windows with no size change */
669 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
670 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
671 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
672 { WM_NCPAINT
, sent
|wparam
, 1 },
673 { WM_GETTEXT
, sent
|defwinproc
|optional
},
674 { WM_ERASEBKGND
, sent
|optional
},
675 { WM_ACTIVATE
, sent
|optional
},
676 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
679 /* DrawMenuBar for a visible window */
680 static const struct message WmDrawMenuBarSeq
[] =
682 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
683 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
684 { WM_NCPAINT
, sent
|wparam
, 1 },
685 { WM_GETTEXT
, sent
|defwinproc
|optional
},
686 { WM_ERASEBKGND
, sent
|optional
},
687 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
691 static const struct message WmSetRedrawFalseSeq
[] =
693 { WM_SETREDRAW
, sent
|wparam
, 0 },
697 static const struct message WmSetRedrawTrueSeq
[] =
699 { WM_SETREDRAW
, sent
|wparam
, 1 },
703 static const struct message WmEnableWindowSeq
[] =
705 { WM_CANCELMODE
, sent
},
710 static const struct message WmGetScrollRangeSeq
[] =
712 { SBM_GETRANGE
, sent
},
715 static const struct message WmGetScrollInfoSeq
[] =
717 { SBM_GETSCROLLINFO
, sent
},
720 static const struct message WmSetScrollRangeSeq
[] =
722 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
723 sends SBM_SETSCROLLINFO.
725 { SBM_SETSCROLLINFO
, sent
},
728 /* SetScrollRange for a window without a non-client area */
729 static const struct message WmSetScrollRangeHVSeq
[] =
731 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
732 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
733 { WM_GETTEXT
, sent
|defwinproc
|optional
},
734 { WM_ERASEBKGND
, sent
|optional
},
735 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
738 /* SetScrollRange for a window with a non-client area */
739 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
741 { WM_WINDOWPOSCHANGING
, sent
, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
742 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
743 { WM_NCPAINT
, sent
|optional
},
744 { WM_GETTEXT
, sent
|defwinproc
|optional
},
745 { WM_GETICON
, sent
|optional
|defwinproc
},
746 { WM_GETICON
, sent
|optional
|defwinproc
},
747 { WM_GETICON
, sent
|optional
|defwinproc
},
748 { WM_GETTEXT
, sent
|defwinproc
|optional
},
749 { WM_ERASEBKGND
, sent
|optional
},
750 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
751 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
752 { WM_SIZE
, sent
|defwinproc
},
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
},
758 { WM_GETICON
, sent
|optional
},
759 { WM_GETICON
, sent
|optional
},
760 { WM_GETICON
, sent
|optional
},
761 { WM_GETTEXT
, sent
|optional
},
762 { WM_GETICON
, sent
|optional
},
763 { WM_GETICON
, sent
|optional
},
764 { WM_GETICON
, sent
|optional
},
765 { WM_GETTEXT
, sent
|optional
},
769 static int after_end_dialog
;
770 static int sequence_cnt
, sequence_size
;
771 static struct message
* sequence
;
773 static void add_message(const struct message
*msg
)
778 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof (struct message
) );
780 if (sequence_cnt
== sequence_size
)
783 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof (struct message
) );
787 sequence
[sequence_cnt
].message
= msg
->message
;
788 sequence
[sequence_cnt
].flags
= msg
->flags
;
789 sequence
[sequence_cnt
].wParam
= msg
->wParam
;
790 sequence
[sequence_cnt
].lParam
= msg
->lParam
;
795 static void flush_sequence()
797 HeapFree(GetProcessHeap(), 0, sequence
);
799 sequence_cnt
= sequence_size
= 0;
802 static void ok_sequence(const struct message
*expected
, const char *context
, int todo
)
804 static const struct message end_of_sequence
= { 0, 0, 0, 0 };
805 const struct message
*actual
;
807 add_message(&end_of_sequence
);
811 while (expected
->message
&& actual
->message
)
813 trace("expected %04x - actual %04x\n", expected
->message
, actual
->message
);
815 if (expected
->message
== actual
->message
)
817 if (expected
->flags
& wparam
)
819 if (expected
->wParam
!= actual
->wParam
&& todo
)
823 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
824 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
828 ok (expected
->wParam
== actual
->wParam
,
829 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
830 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
832 if (expected
->flags
& lparam
)
833 ok (expected
->lParam
== actual
->lParam
,
834 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
835 context
, expected
->message
, expected
->lParam
, actual
->lParam
);
836 ok ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
837 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
838 context
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
839 ok ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
840 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
841 context
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
842 ok ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
843 "%s: the msg 0x%04x should have been %s\n",
844 context
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
845 ok ((expected
->flags
& parent
) == (actual
->flags
& parent
),
846 "%s: the msg 0x%04x was expected in %s\n",
847 context
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
848 ok ((expected
->flags
& hook
) == (actual
->flags
& hook
),
849 "%s: the msg 0x%04x should have been sent by a hook\n",
850 context
, expected
->message
);
854 else if (expected
->flags
& optional
)
859 ok (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
860 context
, expected
->message
, actual
->message
);
867 ok (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
868 context
, expected
->message
, actual
->message
);
874 /* skip all optional trailing messages */
875 while (expected
->message
&& (expected
->flags
& optional
))
881 if (expected
->message
|| actual
->message
)
882 ok (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
883 context
, expected
->message
, actual
->message
);
888 if (expected
->message
|| actual
->message
)
889 ok (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
890 context
, expected
->message
, actual
->message
);
896 /******************************** MDI test **********************************/
898 /* CreateWindow for MDI frame window, initially visible */
899 static const struct message WmCreateMDIframeSeq
[] = {
900 { HCBT_CREATEWND
, hook
},
901 { WM_GETMINMAXINFO
, sent
},
902 { WM_NCCREATE
, sent
},
903 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
905 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
906 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
907 { HCBT_ACTIVATE
, hook
},
908 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
909 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
910 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* Win9x */
911 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
912 { WM_NCACTIVATE
, sent
|wparam
, 1 },
913 { WM_ACTIVATE
, sent
|wparam
, 1 },
914 { HCBT_SETFOCUS
, hook
},
915 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
916 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
917 /* Win9x adds SWP_NOZORDER below */
918 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
923 /* DestroyWindow for MDI frame window, initially visible */
924 static const struct message WmDestroyMDIframeSeq
[] = {
925 { HCBT_DESTROYWND
, hook
},
926 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
927 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
928 { WM_NCACTIVATE
, sent
|wparam
, 0 },
929 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
930 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
931 { WM_DESTROY
, sent
},
932 { WM_NCDESTROY
, sent
},
935 /* CreateWindow for MDI client window, initially visible */
936 static const struct message WmCreateMDIclientSeq
[] = {
937 { HCBT_CREATEWND
, hook
},
938 { WM_NCCREATE
, sent
},
939 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
943 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
944 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
945 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
},
946 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
949 /* DestroyWindow for MDI client window, initially visible */
950 static const struct message WmDestroyMDIclientSeq
[] = {
951 { HCBT_DESTROYWND
, hook
},
952 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
953 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
954 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
955 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
956 { WM_DESTROY
, sent
},
957 { WM_NCDESTROY
, sent
},
960 /* CreateWindow for MDI child window, initially visible */
961 static const struct message WmCreateMDIchildVisibleSeq
[] = {
962 { HCBT_CREATEWND
, hook
},
963 { WM_NCCREATE
, sent
},
964 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
968 /* Win2k sends wparam set to
969 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
970 * while Win9x doesn't bother to set child window id according to
971 * CLIENTCREATESTRUCT.idFirstChild
973 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
974 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
975 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
976 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
977 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
978 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
979 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
980 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
982 /* Win9x: message sequence terminates here. */
984 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
985 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
986 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
987 { WM_SETFOCUS
, sent
}, /* in MDI client */
988 { HCBT_SETFOCUS
, hook
},
989 { WM_KILLFOCUS
, sent
}, /* in MDI client */
990 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
991 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
992 { WM_SETFOCUS
, sent
|defwinproc
},
993 { WM_MDIACTIVATE
, sent
|defwinproc
},
996 /* DestroyWindow for MDI child window, initially visible */
997 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
998 { HCBT_DESTROYWND
, hook
},
999 /* Win2k sends wparam set to
1000 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1001 * while Win9x doesn't bother to set child window id according to
1002 * CLIENTCREATESTRUCT.idFirstChild
1004 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1005 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1006 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1007 { WM_ERASEBKGND
, sent
|parent
|optional
},
1008 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1010 /* { WM_DESTROY, sent }
1011 * Win9x: message sequence terminates here.
1014 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1015 { WM_KILLFOCUS
, sent
},
1016 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1017 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1018 { WM_SETFOCUS
, sent
}, /* in MDI client */
1020 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1021 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1022 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1023 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1024 { WM_SETFOCUS
, sent
}, /* in MDI client */
1026 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1027 { WM_KILLFOCUS
, sent
},
1028 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1029 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1030 { WM_SETFOCUS
, sent
}, /* in MDI client */
1032 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1033 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1034 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1035 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1036 { WM_SETFOCUS
, sent
}, /* in MDI client */
1038 { WM_DESTROY
, sent
},
1040 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1041 { WM_KILLFOCUS
, sent
},
1042 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1043 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1044 { WM_SETFOCUS
, sent
}, /* in MDI client */
1046 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1047 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1048 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1049 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1050 { WM_SETFOCUS
, sent
}, /* in MDI client */
1052 { WM_NCDESTROY
, sent
},
1055 /* CreateWindow for MDI child window, initially invisible */
1056 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
1057 { HCBT_CREATEWND
, hook
},
1058 { WM_NCCREATE
, sent
},
1059 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1060 { WM_CREATE
, sent
},
1063 /* Win2k sends wparam set to
1064 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1065 * while Win9x doesn't bother to set child window id according to
1066 * CLIENTCREATESTRUCT.idFirstChild
1068 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1071 /* DestroyWindow for MDI child window, initially invisible */
1072 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
1073 { HCBT_DESTROYWND
, hook
},
1074 /* Win2k sends wparam set to
1075 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1076 * while Win9x doesn't bother to set child window id according to
1077 * CLIENTCREATESTRUCT.idFirstChild
1079 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1080 { WM_DESTROY
, sent
},
1081 { WM_NCDESTROY
, sent
},
1084 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1085 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
1086 { HCBT_CREATEWND
, hook
},
1087 { WM_NCCREATE
, sent
},
1088 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1089 { WM_CREATE
, sent
},
1092 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1093 { WM_GETMINMAXINFO
, sent
},
1094 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1095 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1096 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1097 { WM_SIZE
, sent
|defwinproc
},
1099 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1100 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1101 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1102 /* Win2k sends wparam set to
1103 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1104 * while Win9x doesn't bother to set child window id according to
1105 * CLIENTCREATESTRUCT.idFirstChild
1107 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1108 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1109 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1110 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1111 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1112 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1113 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1114 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1116 /* Win9x: message sequence terminates here. */
1118 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1119 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1120 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1121 { WM_SETFOCUS
, sent
}, /* in MDI client */
1122 { HCBT_SETFOCUS
, hook
},
1123 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1124 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1125 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1126 { WM_SETFOCUS
, sent
|defwinproc
},
1127 { WM_MDIACTIVATE
, sent
|defwinproc
},
1129 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1130 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1131 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1134 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1135 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
1136 /* restore the 1st MDI child */
1137 { WM_SETREDRAW
, sent
|wparam
, 0 },
1138 { HCBT_MINMAX
, hook
},
1139 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1140 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1141 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1142 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1143 { WM_SIZE
, sent
|defwinproc
},
1145 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1146 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1147 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1148 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
1149 /* create the 2nd MDI child */
1150 { HCBT_CREATEWND
, hook
},
1151 { WM_NCCREATE
, sent
},
1152 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1153 { WM_CREATE
, sent
},
1156 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1157 { WM_GETMINMAXINFO
, sent
},
1158 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1159 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1160 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1161 { WM_SIZE
, sent
|defwinproc
},
1163 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1164 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1165 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1166 /* Win2k sends wparam set to
1167 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1168 * while Win9x doesn't bother to set child window id according to
1169 * CLIENTCREATESTRUCT.idFirstChild
1171 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1172 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1173 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1174 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1175 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1176 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1177 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1179 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1180 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1182 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1184 /* Win9x: message sequence terminates here. */
1186 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1187 { HCBT_SETFOCUS
, hook
},
1188 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
1189 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
1190 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1191 { WM_SETFOCUS
, sent
}, /* in MDI client */
1192 { HCBT_SETFOCUS
, hook
},
1193 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1194 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1195 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1196 { WM_SETFOCUS
, sent
|defwinproc
},
1198 { WM_MDIACTIVATE
, sent
|defwinproc
},
1200 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1201 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1202 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1205 /* WM_MDICREATE MDI child window, initially visible and maximized */
1206 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
1207 { WM_MDICREATE
, sent
},
1208 { HCBT_CREATEWND
, hook
},
1209 { WM_NCCREATE
, sent
},
1210 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1211 { WM_CREATE
, sent
},
1214 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1215 { WM_GETMINMAXINFO
, sent
},
1216 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1217 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1218 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1219 { WM_SIZE
, sent
|defwinproc
},
1221 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1222 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1223 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1224 /* Win2k sends wparam set to
1225 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1226 * while Win9x doesn't bother to set child window id according to
1227 * CLIENTCREATESTRUCT.idFirstChild
1229 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1230 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1231 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1232 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1233 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1234 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1235 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1236 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1238 /* Win9x: message sequence terminates here. */
1240 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1241 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1242 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1243 { WM_SETFOCUS
, sent
}, /* in MDI client */
1244 { HCBT_SETFOCUS
, hook
},
1245 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1246 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1247 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1248 { WM_SETFOCUS
, sent
|defwinproc
},
1250 { WM_MDIACTIVATE
, sent
|defwinproc
},
1253 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1254 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1255 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1258 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1259 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1260 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1261 { WM_MOVE
, sent
|defwinproc
},
1262 { WM_SIZE
, sent
|defwinproc
},
1265 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1266 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1267 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1271 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1272 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1273 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1274 { WM_SIZE
, sent
|defwinproc
},
1278 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1279 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
1280 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
1281 { HCBT_SYSCOMMAND
, hook
},
1282 { WM_CLOSE
, sent
|defwinproc
},
1283 { WM_MDIDESTROY
, sent
}, /* in MDI client */
1285 /* bring the 1st MDI child to top */
1286 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
1287 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
1288 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
1289 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1290 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1292 /* maximize the 1st MDI child */
1293 { HCBT_MINMAX
, hook
},
1294 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1295 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|0x8000 },
1296 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1297 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
1298 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1299 { WM_SIZE
, sent
|defwinproc
},
1301 /* restore the 2nd MDI child */
1302 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
1303 { HCBT_MINMAX
, hook
},
1304 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOZORDER
|0x8000 },
1305 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1306 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1307 { WM_SIZE
, sent
|defwinproc
},
1308 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
1310 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1311 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1312 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1314 /* bring the 1st MDI child to top */
1315 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1316 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1317 { HCBT_SETFOCUS
, hook
},
1318 { WM_KILLFOCUS
, sent
|defwinproc
},
1319 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
1320 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1321 { WM_SETFOCUS
, sent
}, /* in MDI client */
1322 { HCBT_SETFOCUS
, hook
},
1323 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1324 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1325 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1326 { WM_SETFOCUS
, sent
|defwinproc
},
1327 { WM_MDIACTIVATE
, sent
|defwinproc
},
1328 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1330 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1331 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1332 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1333 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1334 { WM_MDIREFRESHMENU
, sent
},
1336 { HCBT_DESTROYWND
, hook
},
1337 /* Win2k sends wparam set to
1338 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1339 * while Win9x doesn't bother to set child window id according to
1340 * CLIENTCREATESTRUCT.idFirstChild
1342 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1343 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
1344 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1345 { WM_ERASEBKGND
, sent
|parent
|optional
},
1346 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1348 { WM_DESTROY
, sent
|defwinproc
},
1349 { WM_NCDESTROY
, sent
|defwinproc
},
1352 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1353 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
1354 { WM_MDIDESTROY
, sent
}, /* in MDI client */
1355 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1356 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1357 { WM_ERASEBKGND
, sent
|parent
|optional
},
1358 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1360 { HCBT_SETFOCUS
, hook
},
1361 { WM_KILLFOCUS
, sent
},
1362 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1363 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1364 { WM_SETFOCUS
, sent
}, /* in MDI client */
1365 { HCBT_SETFOCUS
, hook
},
1366 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1367 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1368 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1369 { WM_SETFOCUS
, sent
},
1372 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1373 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1374 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1377 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1378 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1379 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1380 { WM_MOVE
, sent
|defwinproc
},
1381 { WM_SIZE
, sent
|defwinproc
},
1384 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1385 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1386 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1390 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1391 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1392 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
1393 { WM_SIZE
, sent
|defwinproc
},
1396 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1397 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1398 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1401 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1402 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1403 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1404 { WM_MOVE
, sent
|defwinproc
},
1405 { WM_SIZE
, sent
|defwinproc
},
1408 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1409 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1410 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1414 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1415 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1416 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
1417 { WM_SIZE
, sent
|defwinproc
},
1420 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1421 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1422 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1424 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1425 { WM_MDIACTIVATE
, sent
},
1427 { HCBT_MINMAX
, hook
},
1428 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|0x8000 },
1429 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1430 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1431 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
|0x8000 },
1432 { WM_SIZE
, sent
|defwinproc
},
1435 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1436 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1437 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1440 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1441 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1442 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1443 { WM_MOVE
, sent
|defwinproc
},
1444 { WM_SIZE
, sent
|defwinproc
},
1447 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1448 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1449 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1452 { HCBT_SETFOCUS
, hook
},
1453 { WM_KILLFOCUS
, sent
},
1454 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1455 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1456 { WM_SETFOCUS
, sent
}, /* in MDI client */
1458 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
1460 { HCBT_DESTROYWND
, hook
},
1461 /* Win2k sends wparam set to
1462 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1463 * while Win9x doesn't bother to set child window id according to
1464 * CLIENTCREATESTRUCT.idFirstChild
1466 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1468 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1469 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1470 { WM_ERASEBKGND
, sent
|parent
|optional
},
1471 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1473 { WM_DESTROY
, sent
},
1474 { WM_NCDESTROY
, sent
},
1477 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1478 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
1479 { HCBT_MINMAX
, hook
},
1480 { WM_GETMINMAXINFO
, sent
},
1481 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|0x8000 },
1482 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1483 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1485 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1486 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1487 { HCBT_SETFOCUS
, hook
},
1488 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1489 { WM_SETFOCUS
, sent
}, /* in MDI client */
1490 { HCBT_SETFOCUS
, hook
},
1491 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1492 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1493 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1494 { WM_SETFOCUS
, sent
|defwinproc
},
1495 { WM_MDIACTIVATE
, sent
|defwinproc
},
1496 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1497 { WM_SIZE
, sent
|defwinproc
},
1499 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1500 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1501 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1504 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1505 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
1506 { HCBT_MINMAX
, hook
},
1507 { WM_GETMINMAXINFO
, sent
},
1508 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1509 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1510 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1511 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1512 { WM_SIZE
, sent
|defwinproc
},
1514 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1515 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1516 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1519 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
1520 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
1521 { HCBT_MINMAX
, hook
},
1522 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1523 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1524 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1525 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1526 { WM_SIZE
, sent
|defwinproc
},
1528 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1529 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1530 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1533 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1534 static const struct message WmRestoreMDIchildInisibleSeq
[] = {
1535 { HCBT_MINMAX
, hook
},
1536 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|0x8000 },
1537 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1538 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1539 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1540 { WM_SIZE
, sent
|defwinproc
},
1542 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1543 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1544 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1548 static HWND mdi_client
;
1549 static WNDPROC old_mdi_client_proc
;
1551 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1555 /* do not log painting messages */
1556 if (message
!= WM_PAINT
&&
1557 message
!= WM_ERASEBKGND
&&
1558 message
!= WM_NCPAINT
&&
1559 message
!= WM_GETTEXT
&&
1560 message
!= WM_MDIGETACTIVE
)
1562 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1566 case WM_WINDOWPOSCHANGING
:
1567 case WM_WINDOWPOSCHANGED
:
1569 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1571 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1572 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1573 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1574 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1576 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1577 * in the high word for internal purposes
1579 wParam
= winpos
->flags
& 0xffff;
1584 msg
.message
= message
;
1585 msg
.flags
= sent
|wparam
|lparam
;
1586 msg
.wParam
= wParam
;
1587 msg
.lParam
= lParam
;
1591 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
1594 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1596 static long defwndproc_counter
= 0;
1600 /* do not log painting messages */
1601 if (message
!= WM_PAINT
&&
1602 message
!= WM_ERASEBKGND
&&
1603 message
!= WM_NCPAINT
&&
1604 message
!= WM_GETTEXT
)
1606 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1610 case WM_WINDOWPOSCHANGING
:
1611 case WM_WINDOWPOSCHANGED
:
1613 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1615 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1616 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1617 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1618 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1620 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1621 * in the high word for internal purposes
1623 wParam
= winpos
->flags
& 0xffff;
1627 case WM_MDIACTIVATE
:
1629 HWND active
, client
= GetParent(hwnd
);
1631 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
1633 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
1634 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
1636 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
1641 msg
.message
= message
;
1642 msg
.flags
= sent
|wparam
|lparam
;
1643 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1644 msg
.wParam
= wParam
;
1645 msg
.lParam
= lParam
;
1649 defwndproc_counter
++;
1650 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
1651 defwndproc_counter
--;
1656 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1658 static long defwndproc_counter
= 0;
1662 /* do not log painting messages */
1663 if (message
!= WM_PAINT
&&
1664 message
!= WM_ERASEBKGND
&&
1665 message
!= WM_NCPAINT
&&
1666 message
!= WM_GETTEXT
)
1668 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1672 case WM_WINDOWPOSCHANGING
:
1673 case WM_WINDOWPOSCHANGED
:
1675 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1677 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1678 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1679 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1680 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1682 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1683 * in the high word for internal purposes
1685 wParam
= winpos
->flags
& 0xffff;
1690 msg
.message
= message
;
1691 msg
.flags
= sent
|wparam
|lparam
;
1692 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1693 msg
.wParam
= wParam
;
1694 msg
.lParam
= lParam
;
1698 defwndproc_counter
++;
1699 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
1700 defwndproc_counter
--;
1705 static BOOL
mdi_RegisterWindowClasses(void)
1710 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
1713 cls
.hInstance
= GetModuleHandleA(0);
1715 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
1716 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
1717 cls
.lpszMenuName
= NULL
;
1718 cls
.lpszClassName
= "MDI_frame_class";
1719 if (!RegisterClassA(&cls
)) return FALSE
;
1721 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
1722 cls
.lpszClassName
= "MDI_child_class";
1723 if (!RegisterClassA(&cls
)) return FALSE
;
1725 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
1726 old_mdi_client_proc
= cls
.lpfnWndProc
;
1727 cls
.hInstance
= GetModuleHandleA(0);
1728 cls
.lpfnWndProc
= mdi_client_hook_proc
;
1729 cls
.lpszClassName
= "MDI_client_class";
1730 if (!RegisterClassA(&cls
)) assert(0);
1735 static void test_mdi_messages(void)
1737 MDICREATESTRUCTA mdi_cs
;
1738 CLIENTCREATESTRUCT client_cs
;
1739 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
1741 HMENU hMenu
= CreateMenu();
1743 assert(mdi_RegisterWindowClasses());
1747 trace("creating MDI frame window\n");
1748 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1749 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
1750 WS_MAXIMIZEBOX
| WS_VISIBLE
,
1751 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
1752 GetDesktopWindow(), hMenu
,
1753 GetModuleHandleA(0), NULL
);
1755 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", TRUE
);
1757 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1758 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
1760 trace("creating MDI client window\n");
1761 client_cs
.hWindowMenu
= 0;
1762 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
1763 mdi_client
= CreateWindowExA(0, "MDI_client_class",
1765 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
1767 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
1769 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
1771 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1772 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
1774 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1775 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
1776 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1781 trace("creating visible MDI child window\n");
1782 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1783 WS_CHILD
| WS_VISIBLE
,
1784 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1785 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1787 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", TRUE
);
1789 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1790 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
1792 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1793 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
1795 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1796 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
1797 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1800 DestroyWindow(mdi_child
);
1801 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
1803 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1804 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1806 /* Win2k: MDI client still returns a just destroyed child as active
1807 * Win9x: MDI client returns 0
1809 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1810 ok(active_child
== mdi_child
|| /* win2k */
1811 !active_child
, /* win9x */
1812 "wrong active MDI child %p\n", active_child
);
1813 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1817 trace("creating invisible MDI child window\n");
1818 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1820 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1821 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1823 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
1825 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
1826 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
1828 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1829 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1831 /* Win2k: MDI client still returns a just destroyed child as active
1832 * Win9x: MDI client returns mdi_child2
1834 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1835 ok(active_child
== mdi_child
|| /* win2k */
1836 active_child
== mdi_child2
, /* win9x */
1837 "wrong active MDI child %p\n", active_child
);
1838 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1841 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
1842 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE
);
1844 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1845 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
1847 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1848 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1849 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1852 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1853 ok(GetFocus() == mdi_child2
|| /* win2k */
1854 GetFocus() == 0, /* win9x */
1855 "wrong focus window %p\n", GetFocus());
1860 ShowWindow(mdi_child2
, SW_HIDE
);
1861 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
1863 ShowWindow(mdi_child2
, SW_RESTORE
);
1864 ok_sequence(WmRestoreMDIchildInisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE
);
1867 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1868 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
1870 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1871 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1872 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1878 ShowWindow(mdi_child2
, SW_HIDE
);
1879 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
1881 ShowWindow(mdi_child2
, SW_SHOW
);
1882 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", TRUE
);
1884 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1885 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1887 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
1888 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE
);
1890 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1891 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1893 ShowWindow(mdi_child2
, SW_RESTORE
);
1894 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):MDI child", TRUE
);
1896 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1897 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1902 ShowWindow(mdi_child2
, SW_HIDE
);
1903 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
1905 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1906 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1908 DestroyWindow(mdi_child2
);
1909 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", TRUE
);
1911 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1912 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1914 /* test for maximized MDI children */
1915 trace("creating maximized visible MDI child window 1\n");
1916 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1917 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1918 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1919 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1921 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
1922 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
1924 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1925 ok(GetFocus() == mdi_child
|| /* win2k */
1926 GetFocus() == 0, /* win9x */
1927 "wrong focus window %p\n", GetFocus());
1929 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1930 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
1931 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1934 trace("creating maximized visible MDI child window 2\n");
1935 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1936 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1937 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1938 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1940 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
1941 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
1942 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
1944 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1945 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
1947 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1948 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1949 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1952 trace("destroying maximized visible MDI child window 2\n");
1953 DestroyWindow(mdi_child2
);
1954 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
1956 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
1958 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1959 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1961 /* Win2k: MDI client still returns a just destroyed child as active
1962 * Win9x: MDI client returns 0
1964 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1965 ok(active_child
== mdi_child2
|| /* win2k */
1966 !active_child
, /* win9x */
1967 "wrong active MDI child %p\n", active_child
);
1970 ShowWindow(mdi_child
, SW_MAXIMIZE
);
1971 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
1974 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1975 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
1977 trace("re-creating maximized visible MDI child window 2\n");
1978 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1979 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1980 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1981 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1983 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
1984 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
1985 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
1987 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1988 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
1990 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1991 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1992 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1995 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1996 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
1997 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
1999 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
2000 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2001 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2003 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2004 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2005 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2008 DestroyWindow(mdi_child
);
2009 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
2011 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2012 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2014 /* Win2k: MDI client still returns a just destroyed child as active
2015 * Win9x: MDI client returns 0
2017 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2018 ok(active_child
== mdi_child
|| /* win2k */
2019 !active_child
, /* win9x */
2020 "wrong active MDI child %p\n", active_child
);
2022 /* end of test for maximized MDI children */
2024 mdi_cs
.szClass
= "MDI_child_Class";
2025 mdi_cs
.szTitle
= "MDI child";
2026 mdi_cs
.hOwner
= GetModuleHandleA(0);
2029 mdi_cs
.cx
= CW_USEDEFAULT
;
2030 mdi_cs
.cy
= CW_USEDEFAULT
;
2031 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
2033 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
2034 ok(mdi_child
!= 0, "MDI child creation failed\n");
2035 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
2037 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
2039 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2040 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2042 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
2043 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2044 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2046 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2047 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2048 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2051 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
2052 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
2054 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
2055 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2056 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
2061 DestroyWindow(mdi_client
);
2062 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
2064 DestroyWindow(mdi_frame
);
2065 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
2067 /************************* End of MDI test **********************************/
2069 static void test_WM_SETREDRAW(HWND hwnd
)
2071 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2075 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
2076 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
2078 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
2079 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
2082 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
2083 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
2085 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2086 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
2088 /* restore original WS_VISIBLE state */
2089 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
2094 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2098 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2100 msg
.message
= message
;
2101 msg
.flags
= sent
|wparam
|lparam
;
2102 msg
.wParam
= wParam
;
2103 msg
.lParam
= lParam
;
2106 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
2107 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
2111 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
2113 DWORD style
, exstyle
;
2116 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2117 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2118 /* do not be confused by WS_DLGFRAME set */
2119 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
2121 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
2122 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
2124 ok(SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
), "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2125 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
2126 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
2128 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", TRUE
);
2130 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2131 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
2132 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
2134 /* a subsequent call should do nothing */
2135 ok(SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
), "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2136 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2140 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2141 ok(GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
), "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2142 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2143 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
2144 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
2147 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
2149 DWORD style
, exstyle
;
2152 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2153 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2154 /* do not be confused by WS_DLGFRAME set */
2155 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
2157 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
2158 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
2160 si
.cbSize
= sizeof(si
);
2161 si
.fMask
= SIF_RANGE
;
2164 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
2165 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
2166 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
2168 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", TRUE
);
2170 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2171 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
2172 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
2174 /* a subsequent call should do nothing */
2175 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
2176 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2178 si
.fMask
= SIF_PAGE
;
2180 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
2181 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2185 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
2186 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2188 si
.fMask
= SIF_RANGE
;
2189 si
.nMin
= 0xdeadbeef;
2190 si
.nMax
= 0xdeadbeef;
2191 ok(GetScrollInfo(hwnd
, ctl
, &si
), "GetScrollInfo error %ld\n", GetLastError());
2192 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2193 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
2194 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
2197 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2198 static void test_scroll_messages(HWND hwnd
)
2205 ok(GetScrollRange(hwnd
, SB_CTL
, &min
, &max
), "GetScrollRange error %ld\n", GetLastError());
2206 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
2207 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2208 /* values of min and max are undefined */
2211 ok(SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
), "SetScrollRange error %ld\n", GetLastError());
2212 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2213 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2218 ok(GetScrollRange(hwnd
, SB_CTL
, &min
, &max
), "GetScrollRange error %ld\n", GetLastError());
2219 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
2220 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2221 /* values of min and max are undefined */
2224 si
.cbSize
= sizeof(si
);
2225 si
.fMask
= SIF_RANGE
;
2228 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2229 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2230 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2233 si
.fMask
= SIF_PAGE
;
2235 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2236 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2237 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2242 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2243 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2244 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2247 si
.fMask
= SIF_RANGE
;
2248 si
.nMin
= 0xdeadbeef;
2249 si
.nMax
= 0xdeadbeef;
2250 ok(GetScrollInfo(hwnd
, SB_CTL
, &si
), "GetScrollInfo error %ld\n", GetLastError());
2251 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
2252 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2253 /* values of min and max are undefined */
2256 /* set WS_HSCROLL */
2257 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
2258 /* clear WS_HSCROLL */
2259 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
2261 /* set WS_HSCROLL */
2262 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
2263 /* clear WS_HSCROLL */
2264 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
2266 /* set WS_VSCROLL */
2267 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
2268 /* clear WS_VSCROLL */
2269 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
2271 /* set WS_VSCROLL */
2272 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
2273 /* clear WS_VSCROLL */
2274 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
2277 /* test if we receive the right sequence of messages */
2278 static void test_messages(void)
2280 HWND hwnd
, hparent
, hchild
;
2281 HWND hchild2
, hbutton
;
2284 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2285 100, 100, 200, 200, 0, 0, 0, NULL
);
2286 ok (hwnd
!= 0, "Failed to create overlapped window\n");
2287 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
2289 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2290 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
2291 ok_sequence(WmHideInvisibleOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
2293 /* test WM_SETREDRAW on a not visible top level window */
2294 test_WM_SETREDRAW(hwnd
);
2296 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2297 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
2298 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
2300 ok(GetActiveWindow() == hwnd
, "window should be active\n");
2301 ok(GetFocus() == hwnd
, "window should have input focus\n");
2302 ShowWindow(hwnd
, SW_HIDE
);
2303 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", TRUE
);
2305 ShowWindow(hwnd
, SW_SHOW
);
2306 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
2308 ok(GetActiveWindow() == hwnd
, "window should be active\n");
2309 ok(GetFocus() == hwnd
, "window should have input focus\n");
2310 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2311 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", TRUE
);
2312 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
2314 /* test WM_SETREDRAW on a visible top level window */
2315 ShowWindow(hwnd
, SW_SHOW
);
2316 test_WM_SETREDRAW(hwnd
);
2318 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
2319 test_scroll_messages(hwnd
);
2321 DestroyWindow(hwnd
);
2322 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
2324 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
2325 100, 100, 200, 200, 0, 0, 0, NULL
);
2326 ok (hparent
!= 0, "Failed to create parent window\n");
2329 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
2330 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2331 ok (hchild
!= 0, "Failed to create child window\n");
2332 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", TRUE
);
2333 DestroyWindow(hchild
);
2336 /* visible child window with a caption */
2337 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
2338 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
2339 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2340 ok (hchild
!= 0, "Failed to create child window\n");
2341 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
2343 trace("testing scroll APIs on a visible child window %p\n", hchild
);
2344 test_scroll_messages(hchild
);
2346 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2347 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
2349 DestroyWindow(hchild
);
2352 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
2353 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2354 ok (hchild
!= 0, "Failed to create child window\n");
2355 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
2357 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
2358 100, 100, 50, 50, hparent
, 0, 0, NULL
);
2359 ok (hchild2
!= 0, "Failed to create child2 window\n");
2362 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
2363 0, 100, 50, 50, hchild
, 0, 0, NULL
);
2364 ok (hbutton
!= 0, "Failed to create button window\n");
2366 /* test WM_SETREDRAW on a not visible child window */
2367 test_WM_SETREDRAW(hchild
);
2369 ShowWindow(hchild
, SW_SHOW
);
2370 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
2372 ShowWindow(hchild
, SW_HIDE
);
2373 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
2375 ShowWindow(hchild
, SW_SHOW
);
2376 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
2378 /* test WM_SETREDRAW on a visible child window */
2379 test_WM_SETREDRAW(hchild
);
2381 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
2382 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
2384 ShowWindow(hchild
, SW_HIDE
);
2386 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2387 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
2389 ShowWindow(hchild
, SW_HIDE
);
2391 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
2392 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
2394 /* DestroyWindow sequence below expects that a child has focus */
2398 DestroyWindow(hchild
);
2399 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
2400 DestroyWindow(hchild2
);
2401 DestroyWindow(hbutton
);
2404 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
2405 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2406 ok (hchild
!= 0, "Failed to create child popup window\n");
2407 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
2408 DestroyWindow(hchild
);
2410 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
2412 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
2413 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2414 ok (hchild
!= 0, "Failed to create popup window\n");
2415 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
2416 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2417 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
2419 ShowWindow(hchild
, SW_SHOW
);
2420 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
2422 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2423 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
2425 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2426 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
2427 DestroyWindow(hchild
);
2429 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2430 * changes nothing in message sequences.
2433 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
2434 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2435 ok (hchild
!= 0, "Failed to create popup window\n");
2436 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
2437 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2438 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
2440 ShowWindow(hchild
, SW_SHOW
);
2441 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
2443 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2444 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
2445 DestroyWindow(hchild
);
2448 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
2449 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2450 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
2451 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
2453 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
2454 test_scroll_messages(hwnd
);
2457 after_end_dialog
= 1;
2458 EndDialog( hwnd
, 0 );
2459 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
2461 DestroyWindow(hwnd
);
2462 after_end_dialog
= 0;
2465 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
2466 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
2468 /* test showing child with hidden parent */
2469 ShowWindow( hparent
, SW_HIDE
);
2472 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
2473 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2474 ok (hchild
!= 0, "Failed to create child window\n");
2475 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
2477 ShowWindow( hchild
, SW_SHOW
);
2478 ok_sequence(WmShowChildInvisibleParentSeq
, "ShowWindow:show child with invisible parent", TRUE
);
2479 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2480 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2482 ShowWindow( hchild
, SW_HIDE
);
2483 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", TRUE
);
2484 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
2485 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2487 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2488 ok_sequence(WmShowChildInvisibleParentSeq_2
, "SetWindowPos:show child with invisible parent", TRUE
);
2489 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2490 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2492 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2493 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", TRUE
);
2494 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
2495 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2497 DestroyWindow(hchild
);
2498 DestroyWindow(hparent
);
2501 /* Message sequence for SetMenu */
2502 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a window without a menu\n");
2503 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
2505 hmenu
= CreateMenu();
2506 ok (hmenu
!= 0, "Failed to create menu\n");
2507 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
2508 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2509 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
2510 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
2511 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2512 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
2513 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2514 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
2515 ShowWindow(hwnd
, SW_SHOW
);
2517 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2518 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", TRUE
);
2519 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
2520 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", TRUE
);
2522 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
2523 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", TRUE
);
2525 DestroyWindow(hwnd
);
2528 /* Message sequence for EnableWindow */
2529 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
2530 100, 100, 200, 200, 0, 0, 0, NULL
);
2531 ok (hparent
!= 0, "Failed to create parent window\n");
2532 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
2533 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2534 ok (hchild
!= 0, "Failed to create child window\n");
2539 EnableWindow(hparent
, FALSE
);
2540 ok_sequence(WmEnableWindowSeq
, "EnableWindow", FALSE
);
2542 DestroyWindow(hchild
);
2543 DestroyWindow(hparent
);
2547 /****************** button message test *************************/
2548 static const struct message WmSetFocusButtonSeq
[] =
2550 { HCBT_SETFOCUS
, hook
},
2551 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2552 { WM_SETFOCUS
, sent
|wparam
, 0 },
2553 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2556 static const struct message WmKillFocusButtonSeq
[] =
2558 { HCBT_SETFOCUS
, hook
},
2559 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2560 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2561 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2564 static const struct message WmSetFocusStaticSeq
[] =
2566 { HCBT_SETFOCUS
, hook
},
2567 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2568 { WM_SETFOCUS
, sent
|wparam
, 0 },
2569 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
2572 static const struct message WmKillFocusStaticSeq
[] =
2574 { HCBT_SETFOCUS
, hook
},
2575 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2576 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
2577 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2580 static const struct message WmLButtonDownSeq
[] =
2582 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
2583 { HCBT_SETFOCUS
, hook
},
2584 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2585 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2586 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2587 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
2588 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2591 static const struct message WmLButtonUpSeq
[] =
2593 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
2594 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
2595 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2596 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
2600 static WNDPROC old_button_proc
;
2602 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2604 static long defwndproc_counter
= 0;
2608 trace("button: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2610 msg
.message
= message
;
2611 msg
.flags
= sent
|wparam
|lparam
;
2612 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2613 msg
.wParam
= wParam
;
2614 msg
.lParam
= lParam
;
2617 if (message
== BM_SETSTATE
)
2618 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
2620 defwndproc_counter
++;
2621 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
2622 defwndproc_counter
--;
2627 static void subclass_button(void)
2631 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
2633 old_button_proc
= cls
.lpfnWndProc
;
2635 cls
.hInstance
= GetModuleHandle(0);
2636 cls
.lpfnWndProc
= button_hook_proc
;
2637 cls
.lpszClassName
= "my_button_class";
2638 if (!RegisterClassA(&cls
)) assert(0);
2641 static void test_button_messages(void)
2646 const struct message
*setfocus
;
2647 const struct message
*killfocus
;
2649 { BS_PUSHBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2650 { BS_DEFPUSHBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2651 { BS_CHECKBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2652 { BS_AUTOCHECKBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2653 { BS_RADIOBUTTON
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2654 { BS_3STATE
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2655 { BS_AUTO3STATE
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2656 { BS_GROUPBOX
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2657 { BS_USERBUTTON
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2658 { BS_AUTORADIOBUTTON
, WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2659 { BS_OWNERDRAW
, WmSetFocusButtonSeq
, WmKillFocusButtonSeq
}
2666 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
2668 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
,
2669 0, 0, 50, 14, 0, 0, 0, NULL
);
2670 ok(hwnd
!= 0, "Failed to create button window\n");
2672 ShowWindow(hwnd
, SW_SHOW
);
2677 trace("button style %08lx\n", button
[i
].style
);
2679 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
2682 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
2684 DestroyWindow(hwnd
);
2687 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
2688 0, 0, 50, 14, 0, 0, 0, NULL
);
2689 ok(hwnd
!= 0, "Failed to create button window\n");
2694 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
2695 ok_sequence(WmLButtonDownSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
2697 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
2698 ok_sequence(WmLButtonUpSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
2699 DestroyWindow(hwnd
);
2702 /************* painting message test ********************/
2704 static void dump_region(HRGN hrgn
)
2707 RGNDATA
*data
= NULL
;
2712 printf( "null region\n" );
2715 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
2716 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
2717 GetRegionData( hrgn
, size
, data
);
2718 printf("%ld rects:", data
->rdh
.nCount
);
2719 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
2720 printf( " (%ld,%ld)-(%ld,%ld)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
2722 HeapFree( GetProcessHeap(), 0, data
);
2725 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
2729 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
2730 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
2732 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
2733 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
2734 if (ret
== NULLREGION
)
2736 ok( !hrgn
, "Update region shouldn't be empty\n" );
2740 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
2742 ok( 0, "Regions are different\n" );
2743 if (winetest_debug
> 0)
2745 printf( "Update region: " );
2746 dump_region( update
);
2747 printf( "Wanted region: " );
2748 dump_region( hrgn
);
2752 GetRgnBox( update
, &r1
);
2753 GetUpdateRect( hwnd
, &r2
, FALSE
);
2754 ok( r1
.left
== r2
.left
&& r1
.top
== r2
.top
&& r1
.right
== r2
.right
&& r1
.bottom
== r2
.bottom
,
2755 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
2756 r1
.left
, r1
.top
, r1
.right
, r1
.bottom
, r2
.left
, r2
.top
, r2
.right
, r2
.bottom
);
2758 DeleteObject( tmp
);
2759 DeleteObject( update
);
2762 static const struct message WmInvalidateRgn
[] = {
2763 { WM_NCPAINT
, sent
},
2764 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2768 static const struct message WmInvalidateFull
[] = {
2769 { WM_NCPAINT
, sent
|wparam
, 1 },
2770 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2774 static const struct message WmInvalidateErase
[] = {
2775 { WM_NCPAINT
, sent
|wparam
, 1 },
2776 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2777 { WM_ERASEBKGND
, sent
},
2781 static const struct message WmInvalidatePaint
[] = {
2783 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
2784 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2788 static const struct message WmInvalidateErasePaint
[] = {
2790 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
2791 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2792 { WM_ERASEBKGND
, sent
|beginpaint
},
2796 static const struct message WmErase
[] = {
2797 { WM_ERASEBKGND
, sent
},
2801 static const struct message WmPaint
[] = {
2806 static void test_paint_messages(void)
2810 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
2811 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
2812 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2813 100, 100, 200, 200, 0, 0, 0, NULL
);
2814 ok (hwnd
!= 0, "Failed to create overlapped window\n");
2816 ShowWindow( hwnd
, SW_SHOW
);
2817 UpdateWindow( hwnd
);
2818 check_update_rgn( hwnd
, 0 );
2819 SetRectRgn( hrgn
, 10, 10, 20, 20 );
2820 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
2821 check_update_rgn( hwnd
, hrgn
);
2822 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
2823 RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
2824 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
2825 check_update_rgn( hwnd
, hrgn
);
2826 /* validate everything */
2827 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
2828 check_update_rgn( hwnd
, 0 );
2829 /* now with frame */
2830 SetRectRgn( hrgn
, -5, -5, 20, 20 );
2833 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2834 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
2836 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
2837 check_update_rgn( hwnd
, hrgn
);
2840 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
2841 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2844 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
2845 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
2847 GetClientRect( hwnd
, &rect
);
2848 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2849 check_update_rgn( hwnd
, hrgn
);
2852 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
2853 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
2856 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
2857 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", TRUE
);
2858 check_update_rgn( hwnd
, 0 );
2861 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
2862 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
2863 check_update_rgn( hwnd
, 0 );
2866 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2867 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
2868 SetRectRgn( hrgn
, 0, 0, 50, 100 );
2869 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
2870 SetRectRgn( hrgn
, 50, 0, 100, 100 );
2871 check_update_rgn( hwnd
, hrgn
);
2872 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
2873 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
2874 check_update_rgn( hwnd
, 0 );
2877 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2878 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
2879 SetRectRgn( hrgn
, 0, 0, 100, 50 );
2880 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
2881 ok_sequence( WmErase
, "Erase", FALSE
);
2882 SetRectRgn( hrgn
, 0, 50, 100, 100 );
2883 check_update_rgn( hwnd
, hrgn
);
2886 SetRectRgn( hrgn
, 0, 0, 100, 100 );
2887 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
2888 SetRectRgn( hrgn
, 0, 0, 50, 50 );
2889 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
2890 ok_sequence( WmPaint
, "Paint", FALSE
);
2893 SetRectRgn( hrgn
, -4, -4, -2, -2 );
2894 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2895 SetRectRgn( hrgn
, -4, -4, -3, -3 );
2896 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
2897 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
2900 SetRectRgn( hrgn
, -4, -4, -2, -2 );
2901 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2902 SetRectRgn( hrgn
, -4, -4, -3, -3 );
2903 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
2904 SetRectRgn( hrgn
, 0, 0, 1, 1 );
2905 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
2906 ok_sequence( WmPaint
, "Paint", TRUE
);
2909 SetRectRgn( hrgn
, -4, -4, -1, -1 );
2910 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2911 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
2912 /* make sure no WM_PAINT was generated */
2913 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
2914 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2917 SetRectRgn( hrgn
, -4, -4, -1, -1 );
2918 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
2919 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
2921 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
2923 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
2924 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
2925 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
2926 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
2927 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
2928 /* this will send WM_NCPAINT and validate the non client area */
2929 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
2930 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
2932 else DispatchMessage( &msg
);
2934 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
2936 DeleteObject( hrgn
);
2937 DeleteObject( hrgn2
);
2938 DestroyWindow( hwnd
);
2947 static DWORD WINAPI
thread_proc(void *param
)
2950 struct wnd_event
*wnd_event
= (struct wnd_event
*)param
;
2952 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
2953 100, 100, 200, 200, 0, 0, 0, NULL
);
2954 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
2956 SetEvent(wnd_event
->event
);
2958 while (GetMessage(&msg
, 0, 0, 0))
2960 TranslateMessage(&msg
);
2961 DispatchMessage(&msg
);
2967 static void test_interthread_messages(void)
2974 int len
, expected_len
;
2975 struct wnd_event wnd_event
;
2977 wnd_event
.event
= CreateEventW(NULL
, 0, 0, NULL
);
2978 if (!wnd_event
.event
)
2980 trace("skipping interthread message test under win9x\n");
2984 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
2985 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
2987 ok(WaitForSingleObject(wnd_event
.event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
2989 CloseHandle(wnd_event
.event
);
2991 SetLastError(0xdeadbeef);
2992 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeded\n");
2993 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error code %ld\n", GetLastError());
2995 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
2996 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
2998 expected_len
= lstrlenA("window caption text");
2999 memset(buf
, 0, sizeof(buf
));
3000 SetLastError(0xdeadbeef);
3001 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
3002 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
3003 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
3005 msg
.hwnd
= wnd_event
.hwnd
;
3006 msg
.message
= WM_GETTEXT
;
3007 msg
.wParam
= sizeof(buf
);
3008 msg
.lParam
= (LPARAM
)buf
;
3009 memset(buf
, 0, sizeof(buf
));
3010 SetLastError(0xdeadbeef);
3011 len
= DispatchMessageA(&msg
);
3012 ok(!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3013 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len
, GetLastError());
3015 /* the following test causes an exception in user.exe under win9x */
3016 msg
.hwnd
= wnd_event
.hwnd
;
3017 msg
.message
= WM_TIMER
;
3019 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
3020 SetLastError(0xdeadbeef);
3021 len
= DispatchMessageA(&msg
);
3022 ok(!len
&& GetLastError() == 0xdeadbeef,
3023 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len
, GetLastError());
3025 ok(PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0), "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
3027 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
3028 CloseHandle(hThread
);
3032 static const struct message WmVkN
[] = {
3033 { WM_KEYDOWN
, wparam
|lparam
, VK_N
, 1 },
3034 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_N
, 1 },
3035 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
3036 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
3037 { WM_KEYUP
, wparam
|lparam
, VK_N
, 0xc0000001 },
3038 { WM_KEYUP
, sent
|wparam
|lparam
, VK_N
, 0xc0000001 },
3041 static const struct message WmShiftVkN
[] = {
3042 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
3043 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
3044 { WM_KEYDOWN
, wparam
|lparam
, VK_N
, 1 },
3045 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_N
, 1 },
3046 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
3047 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
3048 { WM_KEYUP
, wparam
|lparam
, VK_N
, 0xc0000001 },
3049 { WM_KEYUP
, sent
|wparam
|lparam
, VK_N
, 0xc0000001 },
3050 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
3051 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
3054 static const struct message WmCtrlVkN
[] = {
3055 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
3056 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
3057 { WM_KEYDOWN
, wparam
|lparam
, VK_N
, 1 },
3058 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_N
, 1 },
3059 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
3060 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
3061 { WM_KEYUP
, wparam
|lparam
, VK_N
, 0xc0000001 },
3062 { WM_KEYUP
, sent
|wparam
|lparam
, VK_N
, 0xc0000001 },
3063 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3064 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3067 static const struct message WmCtrlVkN_2
[] = {
3068 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
3069 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
3070 { WM_KEYDOWN
, wparam
|lparam
, VK_N
, 1 },
3071 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
3072 { WM_KEYUP
, wparam
|lparam
, VK_N
, 0xc0000001 },
3073 { WM_KEYUP
, sent
|wparam
|lparam
, VK_N
, 0xc0000001 },
3074 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3075 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3078 static const struct message WmAltVkN
[] = {
3079 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
3080 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
3081 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_N
, 0x20000001 },
3082 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_N
, 0x20000001 },
3083 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
3084 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
3085 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
3086 { HCBT_SYSCOMMAND
, hook
},
3087 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3088 { WM_SETCURSOR
, sent
|defwinproc
},
3089 { WM_INITMENU
, sent
|defwinproc
},
3090 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
3091 { WM_CAPTURECHANGED
, sent
|defwinproc
},
3092 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
3093 { WM_EXITMENULOOP
, sent
|defwinproc
},
3094 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
3095 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
3096 { WM_SYSKEYUP
, wparam
|lparam
, VK_N
, 0xe0000001 },
3097 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_N
, 0xe0000001 },
3098 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
3099 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
3102 static const struct message WmAltVkN_2
[] = {
3103 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
3104 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
3105 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_N
, 0x20000001 },
3106 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
3107 { WM_SYSKEYUP
, wparam
|lparam
, VK_N
, 0xe0000001 },
3108 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_N
, 0xe0000001 },
3109 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
3110 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
3113 static const struct message WmCtrlAltVkN
[] = {
3114 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
3115 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
3116 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
3117 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
3118 { WM_KEYDOWN
, wparam
|lparam
, VK_N
, 0x20000001 },
3119 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_N
, 0x20000001 },
3120 { WM_KEYUP
, wparam
|lparam
, VK_N
, 0xe0000001 },
3121 { WM_KEYUP
, sent
|wparam
|lparam
, VK_N
, 0xe0000001 },
3122 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
3123 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
3124 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3125 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3129 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
3133 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3135 struct message log_msg
;
3137 trace("accel: %p, %04x, %08x, %08lx\n", msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
3139 log_msg
.message
= msg
.message
;
3140 log_msg
.flags
= wparam
|lparam
;
3141 log_msg
.wParam
= msg
.wParam
;
3142 log_msg
.lParam
= msg
.lParam
;
3143 add_message(&log_msg
);
3145 if (!TranslateAccelerator(hwnd
, hAccel
, &msg
))
3147 TranslateMessage(&msg
);
3148 DispatchMessage(&msg
);
3153 static void test_accelerators(void)
3157 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
3158 100, 100, 200, 200, 0, 0, 0, NULL
);
3162 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
3164 state
= GetKeyState(VK_SHIFT
);
3165 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
3166 state
= GetKeyState(VK_CAPITAL
);
3167 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
3169 hAccel
= LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
3170 assert(hAccel
!= 0);
3172 trace("testing VK_N press/release\n");
3174 keybd_event(VK_N
, 0, 0, 0);
3175 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3176 pump_msg_loop(hwnd
, hAccel
);
3177 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
3179 trace("testing Shift+VK_N press/release\n");
3181 keybd_event(VK_SHIFT
, 0, 0, 0);
3182 keybd_event(VK_N
, 0, 0, 0);
3183 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3184 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
3185 pump_msg_loop(hwnd
, hAccel
);
3186 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
3188 trace("testing Ctrl+VK_N press/release\n");
3190 keybd_event(VK_CONTROL
, 0, 0, 0);
3191 keybd_event(VK_N
, 0, 0, 0);
3192 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3193 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3194 pump_msg_loop(hwnd
, hAccel
);
3195 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
3197 trace("testing Alt+VK_N press/release\n");
3199 keybd_event(VK_MENU
, 0, 0, 0);
3200 keybd_event(VK_N
, 0, 0, 0);
3201 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3202 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3203 pump_msg_loop(hwnd
, hAccel
);
3204 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
3206 trace("testing Ctrl+Alt+VK_N press/release\n");
3208 keybd_event(VK_CONTROL
, 0, 0, 0);
3209 keybd_event(VK_MENU
, 0, 0, 0);
3210 keybd_event(VK_N
, 0, 0, 0);
3211 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3212 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3213 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3214 pump_msg_loop(hwnd
, hAccel
);
3215 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
3217 ok(DestroyAcceleratorTable(hAccel
), "DestroyAcceleratorTable error %ld\n", GetLastError());
3219 hAccel
= LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
3220 assert(hAccel
!= 0);
3222 trace("testing VK_N press/release\n");
3224 keybd_event(VK_N
, 0, 0, 0);
3225 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3226 pump_msg_loop(hwnd
, hAccel
);
3227 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
3229 trace("testing Shift+VK_N press/release\n");
3231 keybd_event(VK_SHIFT
, 0, 0, 0);
3232 keybd_event(VK_N
, 0, 0, 0);
3233 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3234 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
3235 pump_msg_loop(hwnd
, hAccel
);
3236 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
3238 trace("testing Ctrl+VK_N press/release 2\n");
3240 keybd_event(VK_CONTROL
, 0, 0, 0);
3241 keybd_event(VK_N
, 0, 0, 0);
3242 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3243 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3244 pump_msg_loop(hwnd
, hAccel
);
3245 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
3247 trace("testing Alt+VK_N press/release 2\n");
3249 keybd_event(VK_MENU
, 0, 0, 0);
3250 keybd_event(VK_N
, 0, 0, 0);
3251 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3252 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3253 pump_msg_loop(hwnd
, hAccel
);
3254 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
3256 trace("testing Ctrl+Alt+VK_N press/release\n");
3258 keybd_event(VK_CONTROL
, 0, 0, 0);
3259 keybd_event(VK_MENU
, 0, 0, 0);
3260 keybd_event(VK_N
, 0, 0, 0);
3261 keybd_event(VK_N
, 0, KEYEVENTF_KEYUP
, 0);
3262 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3263 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3264 pump_msg_loop(hwnd
, hAccel
);
3265 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
3267 ok(DestroyAcceleratorTable(hAccel
), "DestroyAcceleratorTable error %ld\n", GetLastError());
3269 DestroyWindow(hwnd
);
3272 /************* window procedures ********************/
3274 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3276 static long defwndproc_counter
= 0;
3277 static long beginpaint_counter
= 0;
3281 trace("%p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3285 case WM_WINDOWPOSCHANGING
:
3286 case WM_WINDOWPOSCHANGED
:
3288 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
3290 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
3291 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
3292 winpos
->hwnd
, winpos
->hwndInsertAfter
,
3293 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
3295 /* Log only documented flags, win2k uses 0x1000 and 0x2000
3296 * in the high word for internal purposes
3298 wParam
= winpos
->flags
& 0xffff;
3303 msg
.message
= message
;
3304 msg
.flags
= sent
|wparam
|lparam
;
3305 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3306 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
3307 msg
.wParam
= wParam
;
3308 msg
.lParam
= lParam
;
3311 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
3313 HWND parent
= GetParent(hwnd
);
3315 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
3317 GetClientRect(parent
, &rc
);
3318 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
3320 trace("ptReserved = (%ld,%ld)\n"
3321 "ptMaxSize = (%ld,%ld)\n"
3322 "ptMaxPosition = (%ld,%ld)\n"
3323 "ptMinTrackSize = (%ld,%ld)\n"
3324 "ptMaxTrackSize = (%ld,%ld)\n",
3325 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
3326 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
3327 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
3328 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
3329 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
3331 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
3332 minmax
->ptMaxSize
.x
, rc
.right
);
3333 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
3334 minmax
->ptMaxSize
.y
, rc
.bottom
);
3337 if (message
== WM_PAINT
)
3340 beginpaint_counter
++;
3341 BeginPaint( hwnd
, &ps
);
3342 beginpaint_counter
--;
3343 EndPaint( hwnd
, &ps
);
3347 defwndproc_counter
++;
3348 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
3349 defwndproc_counter
--;
3354 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3356 static long defwndproc_counter
= 0;
3360 trace("popup: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3362 msg
.message
= message
;
3363 msg
.flags
= sent
|wparam
|lparam
;
3364 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3365 msg
.wParam
= wParam
;
3366 msg
.lParam
= lParam
;
3369 if (message
== WM_CREATE
)
3371 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
3372 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
3375 defwndproc_counter
++;
3376 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
3377 defwndproc_counter
--;
3382 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3384 static long defwndproc_counter
= 0;
3388 trace("parent: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3390 if (message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
3391 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
3392 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
3393 message
== WM_IME_SETCONTEXT
)
3395 msg
.message
= message
;
3396 msg
.flags
= sent
|parent
|wparam
|lparam
;
3397 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3398 msg
.wParam
= wParam
;
3399 msg
.lParam
= lParam
;
3403 defwndproc_counter
++;
3404 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
3405 defwndproc_counter
--;
3410 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3412 static long defwndproc_counter
= 0;
3416 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3418 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
3419 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
3420 if (after_end_dialog
)
3421 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
3423 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
3425 msg
.message
= message
;
3426 msg
.flags
= sent
|wparam
|lparam
;
3427 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3428 msg
.wParam
= wParam
;
3429 msg
.lParam
= lParam
;
3432 defwndproc_counter
++;
3433 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
3434 defwndproc_counter
--;
3439 static BOOL
RegisterWindowClasses(void)
3444 cls
.lpfnWndProc
= MsgCheckProcA
;
3447 cls
.hInstance
= GetModuleHandleA(0);
3449 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
3450 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
3451 cls
.lpszMenuName
= NULL
;
3452 cls
.lpszClassName
= "TestWindowClass";
3453 if(!RegisterClassA(&cls
)) return FALSE
;
3455 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
3456 cls
.lpszClassName
= "TestPopupClass";
3457 if(!RegisterClassA(&cls
)) return FALSE
;
3459 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
3460 cls
.lpszClassName
= "TestParentClass";
3461 if(!RegisterClassA(&cls
)) return FALSE
;
3463 cls
.lpfnWndProc
= DefWindowProcA
;
3464 cls
.lpszClassName
= "SimpleWindowClass";
3465 if(!RegisterClassA(&cls
)) return FALSE
;
3467 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
3468 cls
.lpfnWndProc
= TestDlgProcA
;
3469 cls
.lpszClassName
= "TestDialogClass";
3470 if(!RegisterClassA(&cls
)) return FALSE
;
3475 static HHOOK hCBT_hook
;
3477 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
3481 trace("CBT: %d, %08x, %08lx\n", nCode
, wParam
, lParam
);
3483 if (nCode
== HCBT_SYSCOMMAND
)
3487 msg
.message
= nCode
;
3489 msg
.wParam
= wParam
;
3490 msg
.lParam
= lParam
;
3493 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
3496 /* Log also SetFocus(0) calls */
3497 if (!wParam
) wParam
= lParam
;
3499 if (GetClassNameA((HWND
)wParam
, buf
, sizeof(buf
)))
3501 if (!strcmp(buf
, "TestWindowClass") ||
3502 !strcmp(buf
, "TestParentClass") ||
3503 !strcmp(buf
, "TestPopupClass") ||
3504 !strcmp(buf
, "SimpleWindowClass") ||
3505 !strcmp(buf
, "TestDialogClass") ||
3506 !strcmp(buf
, "MDI_frame_class") ||
3507 !strcmp(buf
, "MDI_client_class") ||
3508 !strcmp(buf
, "MDI_child_class") ||
3509 !strcmp(buf
, "my_button_class") ||
3510 !strcmp(buf
, "#32770"))
3514 msg
.message
= nCode
;
3516 msg
.wParam
= wParam
;
3517 msg
.lParam
= lParam
;
3521 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
3524 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
3525 static const WCHAR wszAnsi
[] = {'U',0};
3527 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3531 case CB_FINDSTRINGEXACT
:
3532 trace("String: %p\n", (LPCWSTR
)lParam
);
3533 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
3535 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
3539 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
3542 static void test_message_conversion(void)
3544 static const WCHAR wszMsgConversionClass
[] =
3545 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
3552 cls
.lpfnWndProc
= MsgConversionProcW
;
3555 cls
.hInstance
= GetModuleHandleW(NULL
);
3557 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
3558 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
3559 cls
.lpszMenuName
= NULL
;
3560 cls
.lpszClassName
= wszMsgConversionClass
;
3561 /* this call will fail on Win9x, but that doesn't matter as this test is
3562 * meaningless on those platforms */
3563 if(!RegisterClassW(&cls
)) return;
3565 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
3566 100, 100, 200, 200, 0, 0, 0, NULL
);
3567 ok(hwnd
!= NULL
, "Window creation failed\n");
3571 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
3572 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3573 ok(lRes
== 0, "String should have been converted\n");
3574 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3575 ok(lRes
== 1, "String shouldn't have been converted\n");
3579 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
3580 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3581 ok(lRes
== 1, "String shouldn't have been converted\n");
3582 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3583 ok(lRes
== 1, "String shouldn't have been converted\n");
3585 /* Synchronous messages */
3587 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3588 ok(lRes
== 0, "String should have been converted\n");
3589 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3590 ok(lRes
== 1, "String shouldn't have been converted\n");
3592 /* Asynchronous messages */
3595 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3596 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3597 "PostMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3599 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3600 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3601 "PostMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3603 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3604 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3605 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3607 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3608 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3609 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3611 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3612 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3613 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3615 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3616 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3617 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3619 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
3620 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3621 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3623 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
3624 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3625 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
3630 if (!RegisterWindowClasses()) assert(0);
3632 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
3636 test_mdi_messages();
3637 test_button_messages();
3638 test_paint_messages();
3639 test_interthread_messages();
3640 test_message_conversion();
3641 test_accelerators();
3643 UnhookWindowsHookEx(hCBT_hook
);