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
;
772 static int log_all_parent_messages
;
774 static void add_message(const struct message
*msg
)
779 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof (struct message
) );
781 if (sequence_cnt
== sequence_size
)
784 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof (struct message
) );
788 sequence
[sequence_cnt
].message
= msg
->message
;
789 sequence
[sequence_cnt
].flags
= msg
->flags
;
790 sequence
[sequence_cnt
].wParam
= msg
->wParam
;
791 sequence
[sequence_cnt
].lParam
= msg
->lParam
;
796 static void flush_sequence()
798 HeapFree(GetProcessHeap(), 0, sequence
);
800 sequence_cnt
= sequence_size
= 0;
803 #define ok_sequence( exp, contx, todo) \
804 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
807 static void ok_sequence_(const struct message
*expected
, const char *context
, int todo
,
808 const char *file
, int line
)
810 static const struct message end_of_sequence
= { 0, 0, 0, 0 };
811 const struct message
*actual
;
814 add_message(&end_of_sequence
);
818 while (expected
->message
&& actual
->message
)
820 trace_( file
, line
)("expected %04x - actual %04x\n", expected
->message
, actual
->message
);
822 if (expected
->message
== actual
->message
)
824 if (expected
->flags
& wparam
)
826 if (expected
->wParam
!= actual
->wParam
&& todo
)
830 ok_( file
, line
) (FALSE
,
831 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
832 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
836 ok_( file
, line
) (expected
->wParam
== actual
->wParam
,
837 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
838 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
840 if (expected
->flags
& lparam
)
841 ok_( file
, line
) (expected
->lParam
== actual
->lParam
,
842 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
843 context
, expected
->message
, expected
->lParam
, actual
->lParam
);
844 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
845 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
846 context
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
847 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
848 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
849 context
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
850 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
851 "%s: the msg 0x%04x should have been %s\n",
852 context
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
853 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
854 "%s: the msg 0x%04x was expected in %s\n",
855 context
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
856 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
857 "%s: the msg 0x%04x should have been sent by a hook\n",
858 context
, expected
->message
);
862 else if (expected
->flags
& optional
)
868 ok_( file
, line
) (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
869 context
, expected
->message
, actual
->message
);
876 ok_( file
, line
) (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
877 context
, expected
->message
, actual
->message
);
883 /* skip all optional trailing messages */
884 while (expected
->message
&& (expected
->flags
& optional
))
890 if (expected
->message
|| actual
->message
) {
892 ok_( file
, line
) (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
893 context
, expected
->message
, actual
->message
);
899 if (expected
->message
|| actual
->message
)
900 ok_( file
, line
) (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
901 context
, expected
->message
, actual
->message
);
903 if( todo
&& !failcount
) /* succeeded yet marked todo */
905 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
911 /******************************** MDI test **********************************/
913 /* CreateWindow for MDI frame window, initially visible */
914 static const struct message WmCreateMDIframeSeq
[] = {
915 { HCBT_CREATEWND
, hook
},
916 { WM_GETMINMAXINFO
, sent
},
917 { WM_NCCREATE
, sent
},
918 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
920 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
921 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
922 { HCBT_ACTIVATE
, hook
},
923 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
924 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
925 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* Win9x */
926 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
927 { WM_NCACTIVATE
, sent
|wparam
, 1 },
928 { WM_ACTIVATE
, sent
|wparam
, 1 },
929 { HCBT_SETFOCUS
, hook
},
930 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
931 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
932 /* Win9x adds SWP_NOZORDER below */
933 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
938 /* DestroyWindow for MDI frame window, initially visible */
939 static const struct message WmDestroyMDIframeSeq
[] = {
940 { HCBT_DESTROYWND
, hook
},
941 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
942 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
943 { WM_NCACTIVATE
, sent
|wparam
, 0 },
944 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
945 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
946 { WM_DESTROY
, sent
},
947 { WM_NCDESTROY
, sent
},
950 /* CreateWindow for MDI client window, initially visible */
951 static const struct message WmCreateMDIclientSeq
[] = {
952 { HCBT_CREATEWND
, hook
},
953 { WM_NCCREATE
, sent
},
954 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
958 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
959 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
960 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
},
961 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
964 /* DestroyWindow for MDI client window, initially visible */
965 static const struct message WmDestroyMDIclientSeq
[] = {
966 { HCBT_DESTROYWND
, hook
},
967 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
968 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
969 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
970 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
971 { WM_DESTROY
, sent
},
972 { WM_NCDESTROY
, sent
},
975 /* CreateWindow for MDI child window, initially visible */
976 static const struct message WmCreateMDIchildVisibleSeq
[] = {
977 { HCBT_CREATEWND
, hook
},
978 { WM_NCCREATE
, sent
},
979 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
983 /* Win2k sends wparam set to
984 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
985 * while Win9x doesn't bother to set child window id according to
986 * CLIENTCREATESTRUCT.idFirstChild
988 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
989 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
990 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
991 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
992 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
993 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
994 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
995 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
997 /* Win9x: message sequence terminates here. */
999 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1000 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1001 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1002 { WM_SETFOCUS
, sent
}, /* in MDI client */
1003 { HCBT_SETFOCUS
, hook
},
1004 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1005 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1006 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1007 { WM_SETFOCUS
, sent
|defwinproc
},
1008 { WM_MDIACTIVATE
, sent
|defwinproc
},
1011 /* DestroyWindow for MDI child window, initially visible */
1012 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
1013 { HCBT_DESTROYWND
, hook
},
1014 /* Win2k sends wparam set to
1015 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1016 * while Win9x doesn't bother to set child window id according to
1017 * CLIENTCREATESTRUCT.idFirstChild
1019 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1020 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1021 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1022 { WM_ERASEBKGND
, sent
|parent
|optional
},
1023 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1025 /* { WM_DESTROY, sent }
1026 * Win9x: message sequence terminates here.
1029 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1030 { WM_KILLFOCUS
, sent
},
1031 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1032 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1033 { WM_SETFOCUS
, sent
}, /* in MDI client */
1035 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1036 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1037 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1038 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1039 { WM_SETFOCUS
, sent
}, /* in MDI client */
1041 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1042 { WM_KILLFOCUS
, sent
},
1043 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1044 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1045 { WM_SETFOCUS
, sent
}, /* in MDI client */
1047 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1048 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1049 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1050 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1051 { WM_SETFOCUS
, sent
}, /* in MDI client */
1053 { WM_DESTROY
, sent
},
1055 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1056 { WM_KILLFOCUS
, sent
},
1057 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1058 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1059 { WM_SETFOCUS
, sent
}, /* in MDI client */
1061 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1062 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1063 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1064 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1065 { WM_SETFOCUS
, sent
}, /* in MDI client */
1067 { WM_NCDESTROY
, sent
},
1070 /* CreateWindow for MDI child window, initially invisible */
1071 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
1072 { HCBT_CREATEWND
, hook
},
1073 { WM_NCCREATE
, sent
},
1074 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1075 { WM_CREATE
, sent
},
1078 /* Win2k sends wparam set to
1079 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1080 * while Win9x doesn't bother to set child window id according to
1081 * CLIENTCREATESTRUCT.idFirstChild
1083 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1086 /* DestroyWindow for MDI child window, initially invisible */
1087 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
1088 { HCBT_DESTROYWND
, hook
},
1089 /* Win2k sends wparam set to
1090 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1091 * while Win9x doesn't bother to set child window id according to
1092 * CLIENTCREATESTRUCT.idFirstChild
1094 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1095 { WM_DESTROY
, sent
},
1096 { WM_NCDESTROY
, sent
},
1099 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1100 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
1101 { HCBT_CREATEWND
, hook
},
1102 { WM_NCCREATE
, sent
},
1103 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1104 { WM_CREATE
, sent
},
1107 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1108 { WM_GETMINMAXINFO
, sent
},
1109 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1110 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1111 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1112 { WM_SIZE
, sent
|defwinproc
},
1114 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1115 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1116 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1117 /* Win2k sends wparam set to
1118 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1119 * while Win9x doesn't bother to set child window id according to
1120 * CLIENTCREATESTRUCT.idFirstChild
1122 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1123 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1124 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1125 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1126 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1127 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1128 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1129 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1131 /* Win9x: message sequence terminates here. */
1133 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1134 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1135 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1136 { WM_SETFOCUS
, sent
}, /* in MDI client */
1137 { HCBT_SETFOCUS
, hook
},
1138 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1139 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1140 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1141 { WM_SETFOCUS
, sent
|defwinproc
},
1142 { WM_MDIACTIVATE
, sent
|defwinproc
},
1144 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1145 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1146 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1149 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1150 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
1151 /* restore the 1st MDI child */
1152 { WM_SETREDRAW
, sent
|wparam
, 0 },
1153 { HCBT_MINMAX
, hook
},
1154 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1155 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1156 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1157 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1158 { WM_SIZE
, sent
|defwinproc
},
1160 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1161 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1162 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1163 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
1164 /* create the 2nd MDI child */
1165 { HCBT_CREATEWND
, hook
},
1166 { WM_NCCREATE
, sent
},
1167 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1168 { WM_CREATE
, sent
},
1171 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1172 { WM_GETMINMAXINFO
, sent
},
1173 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1174 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1175 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1176 { WM_SIZE
, sent
|defwinproc
},
1178 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1179 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1180 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1181 /* Win2k sends wparam set to
1182 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1183 * while Win9x doesn't bother to set child window id according to
1184 * CLIENTCREATESTRUCT.idFirstChild
1186 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1187 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1188 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1189 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1190 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1191 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1192 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1194 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1195 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1197 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1199 /* Win9x: message sequence terminates here. */
1201 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1202 { HCBT_SETFOCUS
, hook
},
1203 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
1204 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
1205 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1206 { WM_SETFOCUS
, sent
}, /* in MDI client */
1207 { HCBT_SETFOCUS
, hook
},
1208 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1209 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1210 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1211 { WM_SETFOCUS
, sent
|defwinproc
},
1213 { WM_MDIACTIVATE
, sent
|defwinproc
},
1215 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1216 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1217 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1220 /* WM_MDICREATE MDI child window, initially visible and maximized */
1221 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
1222 { WM_MDICREATE
, sent
},
1223 { HCBT_CREATEWND
, hook
},
1224 { WM_NCCREATE
, sent
},
1225 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1226 { WM_CREATE
, sent
},
1229 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1230 { WM_GETMINMAXINFO
, sent
},
1231 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1232 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1233 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1234 { WM_SIZE
, sent
|defwinproc
},
1236 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1237 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1238 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1239 /* Win2k sends wparam set to
1240 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1241 * while Win9x doesn't bother to set child window id according to
1242 * CLIENTCREATESTRUCT.idFirstChild
1244 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1245 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1246 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1247 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1248 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1249 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1250 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1251 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1253 /* Win9x: message sequence terminates here. */
1255 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1256 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1257 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1258 { WM_SETFOCUS
, sent
}, /* in MDI client */
1259 { HCBT_SETFOCUS
, hook
},
1260 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1261 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1262 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1263 { WM_SETFOCUS
, sent
|defwinproc
},
1265 { WM_MDIACTIVATE
, sent
|defwinproc
},
1268 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1269 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1270 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1273 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1274 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1275 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1276 { WM_MOVE
, sent
|defwinproc
},
1277 { WM_SIZE
, sent
|defwinproc
},
1280 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1281 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1282 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1286 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1287 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1288 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1289 { WM_SIZE
, sent
|defwinproc
},
1293 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1294 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
1295 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
1296 { HCBT_SYSCOMMAND
, hook
},
1297 { WM_CLOSE
, sent
|defwinproc
},
1298 { WM_MDIDESTROY
, sent
}, /* in MDI client */
1300 /* bring the 1st MDI child to top */
1301 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
1302 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
1303 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
1304 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1305 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1307 /* maximize the 1st MDI child */
1308 { HCBT_MINMAX
, hook
},
1309 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1310 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|0x8000 },
1311 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1312 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
1313 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1314 { WM_SIZE
, sent
|defwinproc
},
1316 /* restore the 2nd MDI child */
1317 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
1318 { HCBT_MINMAX
, hook
},
1319 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOZORDER
|0x8000 },
1320 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1321 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1322 { WM_SIZE
, sent
|defwinproc
},
1323 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
1325 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1326 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1327 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1329 /* bring the 1st MDI child to top */
1330 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1331 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1332 { HCBT_SETFOCUS
, hook
},
1333 { WM_KILLFOCUS
, sent
|defwinproc
},
1334 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
1335 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1336 { WM_SETFOCUS
, sent
}, /* in MDI client */
1337 { HCBT_SETFOCUS
, hook
},
1338 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1339 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1340 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1341 { WM_SETFOCUS
, sent
|defwinproc
},
1342 { WM_MDIACTIVATE
, sent
|defwinproc
},
1343 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1345 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1346 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1347 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1348 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1349 { WM_MDIREFRESHMENU
, sent
},
1351 { HCBT_DESTROYWND
, hook
},
1352 /* Win2k sends wparam set to
1353 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1354 * while Win9x doesn't bother to set child window id according to
1355 * CLIENTCREATESTRUCT.idFirstChild
1357 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1358 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
1359 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1360 { WM_ERASEBKGND
, sent
|parent
|optional
},
1361 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1363 { WM_DESTROY
, sent
|defwinproc
},
1364 { WM_NCDESTROY
, sent
|defwinproc
},
1367 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1368 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
1369 { WM_MDIDESTROY
, sent
}, /* in MDI client */
1370 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1371 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1372 { WM_ERASEBKGND
, sent
|parent
|optional
},
1373 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1375 { HCBT_SETFOCUS
, hook
},
1376 { WM_KILLFOCUS
, sent
},
1377 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1378 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1379 { WM_SETFOCUS
, sent
}, /* in MDI client */
1380 { HCBT_SETFOCUS
, hook
},
1381 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1382 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1383 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1384 { WM_SETFOCUS
, sent
},
1387 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1388 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1389 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1392 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1393 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1394 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1395 { WM_MOVE
, sent
|defwinproc
},
1396 { WM_SIZE
, sent
|defwinproc
},
1399 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1400 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1401 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1405 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1406 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1407 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
1408 { WM_SIZE
, sent
|defwinproc
},
1411 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1412 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1413 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1416 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1417 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1418 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1419 { WM_MOVE
, sent
|defwinproc
},
1420 { WM_SIZE
, sent
|defwinproc
},
1423 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1424 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1425 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1429 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1430 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1431 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
1432 { WM_SIZE
, sent
|defwinproc
},
1435 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1436 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1437 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1439 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1440 { WM_MDIACTIVATE
, sent
},
1442 { HCBT_MINMAX
, hook
},
1443 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|0x8000 },
1444 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1445 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1446 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
|0x8000 },
1447 { WM_SIZE
, sent
|defwinproc
},
1450 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1451 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1452 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1455 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1456 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1457 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1458 { WM_MOVE
, sent
|defwinproc
},
1459 { WM_SIZE
, sent
|defwinproc
},
1462 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1463 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1464 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1467 { HCBT_SETFOCUS
, hook
},
1468 { WM_KILLFOCUS
, sent
},
1469 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1470 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1471 { WM_SETFOCUS
, sent
}, /* in MDI client */
1473 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
1475 { HCBT_DESTROYWND
, hook
},
1476 /* Win2k sends wparam set to
1477 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1478 * while Win9x doesn't bother to set child window id according to
1479 * CLIENTCREATESTRUCT.idFirstChild
1481 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1483 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1484 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1485 { WM_ERASEBKGND
, sent
|parent
|optional
},
1486 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1488 { WM_DESTROY
, sent
},
1489 { WM_NCDESTROY
, sent
},
1492 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1493 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
1494 { HCBT_MINMAX
, hook
},
1495 { WM_GETMINMAXINFO
, sent
},
1496 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|0x8000 },
1497 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1498 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1500 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1501 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1502 { HCBT_SETFOCUS
, hook
},
1503 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1504 { WM_SETFOCUS
, sent
}, /* in MDI client */
1505 { HCBT_SETFOCUS
, hook
},
1506 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1507 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1508 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1509 { WM_SETFOCUS
, sent
|defwinproc
},
1510 { WM_MDIACTIVATE
, sent
|defwinproc
},
1511 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|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_MAXIMIZE) for a visible MDI child window */
1520 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
1521 { HCBT_MINMAX
, hook
},
1522 { WM_GETMINMAXINFO
, sent
},
1523 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1524 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1525 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1526 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1527 { WM_SIZE
, sent
|defwinproc
},
1529 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1530 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1531 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1534 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
1535 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
1536 { HCBT_MINMAX
, hook
},
1537 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1538 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1539 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1540 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1541 { WM_SIZE
, sent
|defwinproc
},
1543 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1544 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1545 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1548 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1549 static const struct message WmRestoreMDIchildInisibleSeq
[] = {
1550 { HCBT_MINMAX
, hook
},
1551 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|0x8000 },
1552 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1553 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1554 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1555 { WM_SIZE
, sent
|defwinproc
},
1557 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1558 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1559 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1563 static HWND mdi_client
;
1564 static WNDPROC old_mdi_client_proc
;
1566 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1570 /* do not log painting messages */
1571 if (message
!= WM_PAINT
&&
1572 message
!= WM_ERASEBKGND
&&
1573 message
!= WM_NCPAINT
&&
1574 message
!= WM_GETTEXT
&&
1575 message
!= WM_MDIGETACTIVE
)
1577 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1581 case WM_WINDOWPOSCHANGING
:
1582 case WM_WINDOWPOSCHANGED
:
1584 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1586 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1587 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1588 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1589 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1591 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1592 * in the high word for internal purposes
1594 wParam
= winpos
->flags
& 0xffff;
1599 msg
.message
= message
;
1600 msg
.flags
= sent
|wparam
|lparam
;
1601 msg
.wParam
= wParam
;
1602 msg
.lParam
= lParam
;
1606 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
1609 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1611 static long defwndproc_counter
= 0;
1615 /* do not log painting messages */
1616 if (message
!= WM_PAINT
&&
1617 message
!= WM_ERASEBKGND
&&
1618 message
!= WM_NCPAINT
&&
1619 message
!= WM_GETTEXT
)
1621 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1625 case WM_WINDOWPOSCHANGING
:
1626 case WM_WINDOWPOSCHANGED
:
1628 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1630 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1631 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1632 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1633 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1635 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1636 * in the high word for internal purposes
1638 wParam
= winpos
->flags
& 0xffff;
1642 case WM_MDIACTIVATE
:
1644 HWND active
, client
= GetParent(hwnd
);
1646 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
1648 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
1649 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
1651 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
1656 msg
.message
= message
;
1657 msg
.flags
= sent
|wparam
|lparam
;
1658 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1659 msg
.wParam
= wParam
;
1660 msg
.lParam
= lParam
;
1664 defwndproc_counter
++;
1665 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
1666 defwndproc_counter
--;
1671 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1673 static long defwndproc_counter
= 0;
1677 /* do not log painting messages */
1678 if (message
!= WM_PAINT
&&
1679 message
!= WM_ERASEBKGND
&&
1680 message
!= WM_NCPAINT
&&
1681 message
!= WM_GETTEXT
)
1683 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
1687 case WM_WINDOWPOSCHANGING
:
1688 case WM_WINDOWPOSCHANGED
:
1690 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
1692 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1693 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1694 winpos
->hwnd
, winpos
->hwndInsertAfter
,
1695 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
1697 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1698 * in the high word for internal purposes
1700 wParam
= winpos
->flags
& 0xffff;
1705 msg
.message
= message
;
1706 msg
.flags
= sent
|wparam
|lparam
;
1707 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
1708 msg
.wParam
= wParam
;
1709 msg
.lParam
= lParam
;
1713 defwndproc_counter
++;
1714 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
1715 defwndproc_counter
--;
1720 static BOOL
mdi_RegisterWindowClasses(void)
1725 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
1728 cls
.hInstance
= GetModuleHandleA(0);
1730 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
1731 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
1732 cls
.lpszMenuName
= NULL
;
1733 cls
.lpszClassName
= "MDI_frame_class";
1734 if (!RegisterClassA(&cls
)) return FALSE
;
1736 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
1737 cls
.lpszClassName
= "MDI_child_class";
1738 if (!RegisterClassA(&cls
)) return FALSE
;
1740 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
1741 old_mdi_client_proc
= cls
.lpfnWndProc
;
1742 cls
.hInstance
= GetModuleHandleA(0);
1743 cls
.lpfnWndProc
= mdi_client_hook_proc
;
1744 cls
.lpszClassName
= "MDI_client_class";
1745 if (!RegisterClassA(&cls
)) assert(0);
1750 static void test_mdi_messages(void)
1752 MDICREATESTRUCTA mdi_cs
;
1753 CLIENTCREATESTRUCT client_cs
;
1754 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
1756 HMENU hMenu
= CreateMenu();
1758 assert(mdi_RegisterWindowClasses());
1762 trace("creating MDI frame window\n");
1763 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1764 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
1765 WS_MAXIMIZEBOX
| WS_VISIBLE
,
1766 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
1767 GetDesktopWindow(), hMenu
,
1768 GetModuleHandleA(0), NULL
);
1770 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", TRUE
);
1772 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1773 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
1775 trace("creating MDI client window\n");
1776 client_cs
.hWindowMenu
= 0;
1777 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
1778 mdi_client
= CreateWindowExA(0, "MDI_client_class",
1780 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
1782 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
1784 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
1786 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1787 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
1789 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1790 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
1791 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1796 trace("creating invisible MDI child window\n");
1797 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1799 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1800 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1804 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
1805 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
1807 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1808 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
1810 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1811 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1813 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1814 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
1815 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1817 ShowWindow(mdi_child
, SW_HIDE
);
1818 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
1821 ShowWindow(mdi_child
, SW_SHOW
);
1822 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
1824 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1825 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
1827 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1828 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1830 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1831 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
1832 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1834 DestroyWindow(mdi_child
);
1837 trace("creating visible MDI child window\n");
1838 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1839 WS_CHILD
| WS_VISIBLE
,
1840 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1841 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1843 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", TRUE
);
1845 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1846 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
1848 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1849 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
1851 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1852 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
1853 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1856 DestroyWindow(mdi_child
);
1857 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
1859 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1860 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1862 /* Win2k: MDI client still returns a just destroyed child as active
1863 * Win9x: MDI client returns 0
1865 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1866 ok(active_child
== mdi_child
|| /* win2k */
1867 !active_child
, /* win9x */
1868 "wrong active MDI child %p\n", active_child
);
1869 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1873 trace("creating invisible MDI child window\n");
1874 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1876 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1877 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1879 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
1881 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
1882 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
1884 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1885 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1887 /* Win2k: MDI client still returns a just destroyed child as active
1888 * Win9x: MDI client returns mdi_child2
1890 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1891 ok(active_child
== mdi_child
|| /* win2k */
1892 active_child
== mdi_child2
, /* win9x */
1893 "wrong active MDI child %p\n", active_child
);
1894 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1897 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
1898 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE
);
1900 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1901 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
1903 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1904 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1905 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1908 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1909 ok(GetFocus() == mdi_child2
|| /* win2k */
1910 GetFocus() == 0, /* win9x */
1911 "wrong focus window %p\n", GetFocus());
1916 ShowWindow(mdi_child2
, SW_HIDE
);
1917 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
1919 ShowWindow(mdi_child2
, SW_RESTORE
);
1920 ok_sequence(WmRestoreMDIchildInisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE
);
1923 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
1924 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
1926 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1927 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
1928 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
1934 ShowWindow(mdi_child2
, SW_HIDE
);
1935 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
1937 ShowWindow(mdi_child2
, SW_SHOW
);
1938 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
1940 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1941 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1943 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
1944 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE
);
1946 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1947 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1949 ShowWindow(mdi_child2
, SW_RESTORE
);
1950 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):MDI child", TRUE
);
1952 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1953 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1958 ShowWindow(mdi_child2
, SW_HIDE
);
1959 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
1961 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1962 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1964 DestroyWindow(mdi_child2
);
1965 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
1967 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1968 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1970 /* test for maximized MDI children */
1971 trace("creating maximized visible MDI child window 1\n");
1972 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1973 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1974 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1975 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1977 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
1978 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
1980 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
1981 ok(GetFocus() == mdi_child
|| /* win2k */
1982 GetFocus() == 0, /* win9x */
1983 "wrong focus window %p\n", GetFocus());
1985 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
1986 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
1987 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
1990 trace("creating maximized visible MDI child window 2\n");
1991 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
1992 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
1993 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
1994 mdi_client
, 0, GetModuleHandleA(0), NULL
);
1996 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
1997 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
1998 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
2000 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2001 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
2003 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2004 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
2005 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2008 trace("destroying maximized visible MDI child window 2\n");
2009 DestroyWindow(mdi_child2
);
2010 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
2012 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
2014 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2015 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2017 /* Win2k: MDI client still returns a just destroyed child as active
2018 * Win9x: MDI client returns 0
2020 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2021 ok(active_child
== mdi_child2
|| /* win2k */
2022 !active_child
, /* win9x */
2023 "wrong active MDI child %p\n", active_child
);
2026 ShowWindow(mdi_child
, SW_MAXIMIZE
);
2027 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
2030 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2031 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2033 trace("re-creating maximized visible MDI child window 2\n");
2034 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
2035 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
2036 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
2037 mdi_client
, 0, GetModuleHandleA(0), NULL
);
2039 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
2040 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
2041 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
2043 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2044 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
2046 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2047 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
2048 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2051 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
2052 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
2053 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
2055 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
2056 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2057 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2059 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2060 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2061 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2064 DestroyWindow(mdi_child
);
2065 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
2067 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2068 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2070 /* Win2k: MDI client still returns a just destroyed child as active
2071 * Win9x: MDI client returns 0
2073 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2074 ok(active_child
== mdi_child
|| /* win2k */
2075 !active_child
, /* win9x */
2076 "wrong active MDI child %p\n", active_child
);
2078 /* end of test for maximized MDI children */
2080 mdi_cs
.szClass
= "MDI_child_Class";
2081 mdi_cs
.szTitle
= "MDI child";
2082 mdi_cs
.hOwner
= GetModuleHandleA(0);
2085 mdi_cs
.cx
= CW_USEDEFAULT
;
2086 mdi_cs
.cy
= CW_USEDEFAULT
;
2087 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
2089 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
2090 ok(mdi_child
!= 0, "MDI child creation failed\n");
2091 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
2093 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
2095 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2096 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2098 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
2099 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2100 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2102 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2103 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2104 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2107 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
2108 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
2110 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
2111 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2112 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
2117 DestroyWindow(mdi_client
);
2118 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
2120 DestroyWindow(mdi_frame
);
2121 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
2123 /************************* End of MDI test **********************************/
2125 static void test_WM_SETREDRAW(HWND hwnd
)
2127 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2131 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
2132 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
2134 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
2135 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
2138 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
2139 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
2141 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2142 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
2144 /* restore original WS_VISIBLE state */
2145 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
2150 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2154 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2156 msg
.message
= message
;
2157 msg
.flags
= sent
|wparam
|lparam
;
2158 msg
.wParam
= wParam
;
2159 msg
.lParam
= lParam
;
2162 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
2163 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
2167 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
2169 DWORD style
, exstyle
;
2173 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2174 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2175 /* do not be confused by WS_DLGFRAME set */
2176 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
2178 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
2179 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
2181 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
2182 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2183 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
2184 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
2186 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2188 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2189 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
2190 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
2192 /* a subsequent call should do nothing */
2193 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
2194 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2195 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2199 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2200 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
2201 ok( ret
, "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2202 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2203 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
2204 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
2207 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
2209 DWORD style
, exstyle
;
2213 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2214 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2215 /* do not be confused by WS_DLGFRAME set */
2216 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
2218 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
2219 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
2221 si
.cbSize
= sizeof(si
);
2222 si
.fMask
= SIF_RANGE
;
2225 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
2226 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
2227 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
2229 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2231 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2232 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
2233 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
2235 /* a subsequent call should do nothing */
2236 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
2237 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2239 si
.fMask
= SIF_PAGE
;
2241 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
2242 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2246 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
2247 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2249 si
.fMask
= SIF_RANGE
;
2250 si
.nMin
= 0xdeadbeef;
2251 si
.nMax
= 0xdeadbeef;
2252 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
2253 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
2254 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2255 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
2256 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
2259 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2260 static void test_scroll_messages(HWND hwnd
)
2268 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
2269 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
2270 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
2271 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2272 /* values of min and max are undefined */
2275 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
2276 ok( ret
, "SetScrollRange error %ld\n", GetLastError());
2277 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2278 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2283 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
2284 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
2285 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
2286 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2287 /* values of min and max are undefined */
2290 si
.cbSize
= sizeof(si
);
2291 si
.fMask
= SIF_RANGE
;
2294 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2295 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2296 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2299 si
.fMask
= SIF_PAGE
;
2301 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2302 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2303 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2308 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2309 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2310 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2313 si
.fMask
= SIF_RANGE
;
2314 si
.nMin
= 0xdeadbeef;
2315 si
.nMax
= 0xdeadbeef;
2316 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
2317 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
2318 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
2319 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2320 /* values of min and max are undefined */
2323 /* set WS_HSCROLL */
2324 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
2325 /* clear WS_HSCROLL */
2326 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
2328 /* set WS_HSCROLL */
2329 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
2330 /* clear WS_HSCROLL */
2331 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
2333 /* set WS_VSCROLL */
2334 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
2335 /* clear WS_VSCROLL */
2336 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
2338 /* set WS_VSCROLL */
2339 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
2340 /* clear WS_VSCROLL */
2341 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
2344 /* test if we receive the right sequence of messages */
2345 static void test_messages(void)
2347 HWND hwnd
, hparent
, hchild
;
2348 HWND hchild2
, hbutton
;
2352 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2353 100, 100, 200, 200, 0, 0, 0, NULL
);
2354 ok (hwnd
!= 0, "Failed to create overlapped window\n");
2355 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
2357 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2358 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
2359 ok_sequence(WmHideInvisibleOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
2361 /* test WM_SETREDRAW on a not visible top level window */
2362 test_WM_SETREDRAW(hwnd
);
2364 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2365 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
2366 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
2368 ok(GetActiveWindow() == hwnd
, "window should be active\n");
2369 ok(GetFocus() == hwnd
, "window should have input focus\n");
2370 ShowWindow(hwnd
, SW_HIDE
);
2371 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", TRUE
);
2373 ShowWindow(hwnd
, SW_SHOW
);
2374 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
2376 ok(GetActiveWindow() == hwnd
, "window should be active\n");
2377 ok(GetFocus() == hwnd
, "window should have input focus\n");
2378 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2379 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
2380 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
2382 /* test WM_SETREDRAW on a visible top level window */
2383 ShowWindow(hwnd
, SW_SHOW
);
2384 test_WM_SETREDRAW(hwnd
);
2386 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
2387 test_scroll_messages(hwnd
);
2389 DestroyWindow(hwnd
);
2390 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
2392 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
2393 100, 100, 200, 200, 0, 0, 0, NULL
);
2394 ok (hparent
!= 0, "Failed to create parent window\n");
2397 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
2398 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2399 ok (hchild
!= 0, "Failed to create child window\n");
2400 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", TRUE
);
2401 DestroyWindow(hchild
);
2404 /* visible child window with a caption */
2405 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
2406 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
2407 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2408 ok (hchild
!= 0, "Failed to create child window\n");
2409 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
2411 trace("testing scroll APIs on a visible child window %p\n", hchild
);
2412 test_scroll_messages(hchild
);
2414 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2415 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
2417 DestroyWindow(hchild
);
2420 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
2421 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2422 ok (hchild
!= 0, "Failed to create child window\n");
2423 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
2425 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
2426 100, 100, 50, 50, hparent
, 0, 0, NULL
);
2427 ok (hchild2
!= 0, "Failed to create child2 window\n");
2430 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
2431 0, 100, 50, 50, hchild
, 0, 0, NULL
);
2432 ok (hbutton
!= 0, "Failed to create button window\n");
2434 /* test WM_SETREDRAW on a not visible child window */
2435 test_WM_SETREDRAW(hchild
);
2437 ShowWindow(hchild
, SW_SHOW
);
2438 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
2440 ShowWindow(hchild
, SW_HIDE
);
2441 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
2443 ShowWindow(hchild
, SW_SHOW
);
2444 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
2446 /* test WM_SETREDRAW on a visible child window */
2447 test_WM_SETREDRAW(hchild
);
2449 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
2450 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
2452 ShowWindow(hchild
, SW_HIDE
);
2454 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2455 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
2457 ShowWindow(hchild
, SW_HIDE
);
2459 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
2460 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
2462 /* DestroyWindow sequence below expects that a child has focus */
2466 DestroyWindow(hchild
);
2467 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
2468 DestroyWindow(hchild2
);
2469 DestroyWindow(hbutton
);
2472 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
2473 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2474 ok (hchild
!= 0, "Failed to create child popup window\n");
2475 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
2476 DestroyWindow(hchild
);
2478 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
2480 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
2481 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2482 ok (hchild
!= 0, "Failed to create popup window\n");
2483 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
2484 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2485 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
2487 ShowWindow(hchild
, SW_SHOW
);
2488 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
2490 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2491 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
2493 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2494 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
2495 DestroyWindow(hchild
);
2497 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2498 * changes nothing in message sequences.
2501 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
2502 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2503 ok (hchild
!= 0, "Failed to create popup window\n");
2504 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
2505 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2506 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
2508 ShowWindow(hchild
, SW_SHOW
);
2509 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
2511 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2512 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
2513 DestroyWindow(hchild
);
2516 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
2517 0, 0, 100, 100, hparent
, 0, 0, NULL
);
2518 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
2519 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
2521 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
2522 test_scroll_messages(hwnd
);
2525 after_end_dialog
= 1;
2526 EndDialog( hwnd
, 0 );
2527 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
2529 DestroyWindow(hwnd
);
2530 after_end_dialog
= 0;
2533 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
2534 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
2536 /* test showing child with hidden parent */
2537 ShowWindow( hparent
, SW_HIDE
);
2540 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
2541 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2542 ok (hchild
!= 0, "Failed to create child window\n");
2543 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
2545 ShowWindow( hchild
, SW_SHOW
);
2546 ok_sequence(WmShowChildInvisibleParentSeq
, "ShowWindow:show child with invisible parent", TRUE
);
2547 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2548 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2550 ShowWindow( hchild
, SW_HIDE
);
2551 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", TRUE
);
2552 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
2553 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2555 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2556 ok_sequence(WmShowChildInvisibleParentSeq_2
, "SetWindowPos:show child with invisible parent", TRUE
);
2557 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2558 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2560 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
2561 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", TRUE
);
2562 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
2563 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
2565 DestroyWindow(hchild
);
2566 DestroyWindow(hparent
);
2569 /* Message sequence for SetMenu */
2570 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a window without a menu\n");
2571 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
2573 hmenu
= CreateMenu();
2574 ok (hmenu
!= 0, "Failed to create menu\n");
2575 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
2576 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2577 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
2578 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
2579 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2580 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
2581 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2582 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
2583 ShowWindow(hwnd
, SW_SHOW
);
2585 ok (SetMenu(hwnd
, 0), "SetMenu\n");
2586 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", TRUE
);
2587 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
2588 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", TRUE
);
2590 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
2591 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", TRUE
);
2593 DestroyWindow(hwnd
);
2596 /* Message sequence for EnableWindow */
2597 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
2598 100, 100, 200, 200, 0, 0, 0, NULL
);
2599 ok (hparent
!= 0, "Failed to create parent window\n");
2600 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
2601 0, 0, 10, 10, hparent
, 0, 0, NULL
);
2602 ok (hchild
!= 0, "Failed to create child window\n");
2607 EnableWindow(hparent
, FALSE
);
2608 ok_sequence(WmEnableWindowSeq
, "EnableWindow", FALSE
);
2610 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
2612 PostMessage( hparent
, WM_USER
, 0, 0 );
2613 PostMessage( hparent
, WM_USER
+1, 0, 0 );
2614 /* PeekMessage(NULL) fails, but still removes the message */
2615 SetLastError(0xdeadbeef);
2616 ok( !PeekMessage( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
2617 ok( GetLastError() == ERROR_NOACCESS
, "last error is %ld\n", GetLastError() );
2618 ok( PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
2619 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
2621 DestroyWindow(hchild
);
2622 DestroyWindow(hparent
);
2626 /****************** button message test *************************/
2627 static const struct message WmSetFocusButtonSeq
[] =
2629 { HCBT_SETFOCUS
, hook
},
2630 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2631 { WM_SETFOCUS
, sent
|wparam
, 0 },
2632 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2635 static const struct message WmKillFocusButtonSeq
[] =
2637 { HCBT_SETFOCUS
, hook
},
2638 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2639 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2640 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2643 static const struct message WmSetFocusStaticSeq
[] =
2645 { HCBT_SETFOCUS
, hook
},
2646 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2647 { WM_SETFOCUS
, sent
|wparam
, 0 },
2648 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
2651 static const struct message WmKillFocusStaticSeq
[] =
2653 { HCBT_SETFOCUS
, hook
},
2654 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2655 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
2656 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2659 static const struct message WmLButtonDownSeq
[] =
2661 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
2662 { HCBT_SETFOCUS
, hook
},
2663 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2664 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2665 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2666 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
2667 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2670 static const struct message WmLButtonUpSeq
[] =
2672 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
2673 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
2674 { WM_CTLCOLORBTN
, sent
|defwinproc
},
2675 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
2679 static WNDPROC old_button_proc
;
2681 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2683 static long defwndproc_counter
= 0;
2687 trace("button: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2689 msg
.message
= message
;
2690 msg
.flags
= sent
|wparam
|lparam
;
2691 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2692 msg
.wParam
= wParam
;
2693 msg
.lParam
= lParam
;
2696 if (message
== BM_SETSTATE
)
2697 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
2699 defwndproc_counter
++;
2700 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
2701 defwndproc_counter
--;
2706 static void subclass_button(void)
2710 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
2712 old_button_proc
= cls
.lpfnWndProc
;
2714 cls
.hInstance
= GetModuleHandle(0);
2715 cls
.lpfnWndProc
= button_hook_proc
;
2716 cls
.lpszClassName
= "my_button_class";
2717 if (!RegisterClassA(&cls
)) assert(0);
2720 static void test_button_messages(void)
2726 const struct message
*setfocus
;
2727 const struct message
*killfocus
;
2729 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
2730 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2731 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
2732 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2733 { BS_CHECKBOX
, DLGC_BUTTON
,
2734 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2735 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
2736 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2737 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
2738 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2739 { BS_3STATE
, DLGC_BUTTON
,
2740 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2741 { BS_AUTO3STATE
, DLGC_BUTTON
,
2742 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2743 { BS_GROUPBOX
, DLGC_STATIC
,
2744 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2745 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
2746 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
2747 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
2748 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
2749 { BS_OWNERDRAW
, DLGC_BUTTON
,
2750 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
}
2758 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
2760 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
,
2761 0, 0, 50, 14, 0, 0, 0, NULL
);
2762 ok(hwnd
!= 0, "Failed to create button window\n");
2764 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
2765 ok(dlg_code
== button
[i
].dlg_code
, "%d: wrong dlg_code %08lx\n", i
, dlg_code
);
2767 ShowWindow(hwnd
, SW_SHOW
);
2772 trace("button style %08lx\n", button
[i
].style
);
2774 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
2777 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
2779 DestroyWindow(hwnd
);
2782 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON
| WS_POPUP
| WS_VISIBLE
,
2783 0, 0, 50, 14, 0, 0, 0, NULL
);
2784 ok(hwnd
!= 0, "Failed to create button window\n");
2789 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
2790 ok_sequence(WmLButtonDownSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
2792 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
2793 ok_sequence(WmLButtonUpSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
2794 DestroyWindow(hwnd
);
2797 /************* painting message test ********************/
2799 static void dump_region(HRGN hrgn
)
2802 RGNDATA
*data
= NULL
;
2807 printf( "null region\n" );
2810 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
2811 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
2812 GetRegionData( hrgn
, size
, data
);
2813 printf("%ld rects:", data
->rdh
.nCount
);
2814 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
2815 printf( " (%ld,%ld)-(%ld,%ld)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
2817 HeapFree( GetProcessHeap(), 0, data
);
2820 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
2824 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
2825 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
2827 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
2828 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
2829 if (ret
== NULLREGION
)
2831 ok( !hrgn
, "Update region shouldn't be empty\n" );
2835 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
2837 ok( 0, "Regions are different\n" );
2838 if (winetest_debug
> 0)
2840 printf( "Update region: " );
2841 dump_region( update
);
2842 printf( "Wanted region: " );
2843 dump_region( hrgn
);
2847 GetRgnBox( update
, &r1
);
2848 GetUpdateRect( hwnd
, &r2
, FALSE
);
2849 ok( r1
.left
== r2
.left
&& r1
.top
== r2
.top
&& r1
.right
== r2
.right
&& r1
.bottom
== r2
.bottom
,
2850 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
2851 r1
.left
, r1
.top
, r1
.right
, r1
.bottom
, r2
.left
, r2
.top
, r2
.right
, r2
.bottom
);
2853 DeleteObject( tmp
);
2854 DeleteObject( update
);
2857 static const struct message WmInvalidateRgn
[] = {
2858 { WM_NCPAINT
, sent
},
2859 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2863 static const struct message WmGetUpdateRect
[] = {
2864 { WM_NCPAINT
, sent
},
2865 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2870 static const struct message WmInvalidateFull
[] = {
2871 { WM_NCPAINT
, sent
|wparam
, 1 },
2872 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2876 static const struct message WmInvalidateErase
[] = {
2877 { WM_NCPAINT
, sent
|wparam
, 1 },
2878 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2879 { WM_ERASEBKGND
, sent
},
2883 static const struct message WmInvalidatePaint
[] = {
2885 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
2886 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2890 static const struct message WmInvalidateErasePaint
[] = {
2892 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
2893 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2894 { WM_ERASEBKGND
, sent
|beginpaint
},
2898 static const struct message WmInvalidateErasePaint2
[] = {
2900 { WM_NCPAINT
, sent
|beginpaint
},
2901 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2902 { WM_ERASEBKGND
, sent
|beginpaint
},
2906 static const struct message WmErase
[] = {
2907 { WM_ERASEBKGND
, sent
},
2911 static const struct message WmPaint
[] = {
2916 static const struct message WmParentOnlyPaint
[] = {
2917 { WM_PAINT
, sent
|parent
},
2921 static const struct message WmInvalidateParent
[] = {
2922 { WM_NCPAINT
, sent
|parent
},
2923 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
2924 { WM_ERASEBKGND
, sent
|parent
},
2928 static const struct message WmInvalidateParentChild
[] = {
2929 { WM_NCPAINT
, sent
|parent
},
2930 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
2931 { WM_ERASEBKGND
, sent
|parent
},
2932 { WM_NCPAINT
, sent
},
2933 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2934 { WM_ERASEBKGND
, sent
},
2938 static const struct message WmInvalidateParentChild2
[] = {
2939 { WM_ERASEBKGND
, sent
|parent
},
2940 { WM_NCPAINT
, sent
},
2941 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2942 { WM_ERASEBKGND
, sent
},
2946 static const struct message WmParentPaint
[] = {
2947 { WM_PAINT
, sent
|parent
},
2952 static const struct message WmParentPaintNc
[] = {
2953 { WM_PAINT
, sent
|parent
},
2955 { WM_NCPAINT
, sent
|beginpaint
},
2956 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2957 { WM_ERASEBKGND
, sent
|beginpaint
},
2961 static const struct message WmChildPaintNc
[] = {
2963 { WM_NCPAINT
, sent
|beginpaint
},
2964 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2965 { WM_ERASEBKGND
, sent
|beginpaint
},
2969 static const struct message WmParentErasePaint
[] = {
2970 { WM_PAINT
, sent
|parent
},
2971 { WM_NCPAINT
, sent
|parent
|beginpaint
},
2972 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
2973 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
2975 { WM_NCPAINT
, sent
|beginpaint
},
2976 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
2977 { WM_ERASEBKGND
, sent
|beginpaint
},
2981 static const struct message WmParentOnlyNcPaint
[] = {
2982 { WM_PAINT
, sent
|parent
},
2983 { WM_NCPAINT
, sent
|parent
|beginpaint
},
2984 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
2988 static const struct message WmSetParentStyle
[] = {
2989 { WM_STYLECHANGING
, sent
|parent
},
2990 { WM_STYLECHANGED
, sent
|parent
},
2994 static void test_paint_messages(void)
2999 HWND hparent
, hchild
;
3000 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
3001 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
3002 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
3003 100, 100, 200, 200, 0, 0, 0, NULL
);
3004 ok (hwnd
!= 0, "Failed to create overlapped window\n");
3006 ShowWindow( hwnd
, SW_SHOW
);
3007 UpdateWindow( hwnd
);
3009 /* try to flush pending X expose events */
3010 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
3011 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3013 check_update_rgn( hwnd
, 0 );
3014 SetRectRgn( hrgn
, 10, 10, 20, 20 );
3015 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
3016 check_update_rgn( hwnd
, hrgn
);
3017 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
3018 RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
3019 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
3020 check_update_rgn( hwnd
, hrgn
);
3021 /* validate everything */
3022 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
3023 check_update_rgn( hwnd
, 0 );
3024 /* now with frame */
3025 SetRectRgn( hrgn
, -5, -5, 20, 20 );
3027 /* flush pending messages */
3028 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3031 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3032 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
3034 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
3035 check_update_rgn( hwnd
, hrgn
);
3038 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
3039 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
3042 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
3043 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
3045 GetClientRect( hwnd
, &rect
);
3046 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
3047 check_update_rgn( hwnd
, hrgn
);
3050 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
3051 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
3054 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
3055 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
3056 check_update_rgn( hwnd
, 0 );
3059 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
3060 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
3061 check_update_rgn( hwnd
, 0 );
3064 SetRectRgn( hrgn
, 0, 0, 100, 100 );
3065 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
3066 SetRectRgn( hrgn
, 0, 0, 50, 100 );
3067 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
3068 SetRectRgn( hrgn
, 50, 0, 100, 100 );
3069 check_update_rgn( hwnd
, hrgn
);
3070 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
3071 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
3072 check_update_rgn( hwnd
, 0 );
3075 SetRectRgn( hrgn
, 0, 0, 100, 100 );
3076 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
3077 SetRectRgn( hrgn
, 0, 0, 100, 50 );
3078 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
3079 ok_sequence( WmErase
, "Erase", FALSE
);
3080 SetRectRgn( hrgn
, 0, 50, 100, 100 );
3081 check_update_rgn( hwnd
, hrgn
);
3084 SetRectRgn( hrgn
, 0, 0, 100, 100 );
3085 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
3086 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3087 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
3088 ok_sequence( WmPaint
, "Paint", FALSE
);
3091 SetRectRgn( hrgn
, -4, -4, -2, -2 );
3092 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3093 SetRectRgn( hrgn
, -200, -200, -198, -198 );
3094 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
3095 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
3098 SetRectRgn( hrgn
, -4, -4, -2, -2 );
3099 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3100 SetRectRgn( hrgn
, -4, -4, -3, -3 );
3101 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
3102 SetRectRgn( hrgn
, 0, 0, 1, 1 );
3103 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
3104 ok_sequence( WmPaint
, "Paint", FALSE
);
3107 SetRectRgn( hrgn
, -4, -4, -1, -1 );
3108 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3109 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
3110 /* make sure no WM_PAINT was generated */
3111 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3112 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
3115 SetRectRgn( hrgn
, -4, -4, -1, -1 );
3116 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3117 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
3119 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
3121 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
3122 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
3123 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
3124 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
3125 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
3126 /* this will send WM_NCPAINT and validate the non client area */
3127 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
3128 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
3130 DispatchMessage( &msg
);
3132 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
3134 DestroyWindow( hwnd
);
3136 /* now test with a child window */
3138 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
3139 100, 100, 200, 200, 0, 0, 0, NULL
);
3140 ok (hparent
!= 0, "Failed to create parent window\n");
3142 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
3143 10, 10, 100, 100, hparent
, 0, 0, NULL
);
3144 ok (hchild
!= 0, "Failed to create child window\n");
3146 ShowWindow( hparent
, SW_SHOW
);
3147 UpdateWindow( hparent
);
3148 UpdateWindow( hchild
);
3149 /* try to flush pending X expose events */
3150 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
3151 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3154 log_all_parent_messages
++;
3156 SetRect( &rect
, 0, 0, 50, 50 );
3157 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3158 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
3159 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
3161 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3163 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
3164 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
3165 check_update_rgn( hchild
, hrgn
);
3166 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3167 check_update_rgn( hparent
, hrgn
);
3168 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3169 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
3170 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
3171 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
3173 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3174 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
3176 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
3177 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3178 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
3179 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
3180 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
3182 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
3183 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
3184 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
3186 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
3188 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
3189 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3190 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
3192 /* flush all paint messages */
3193 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3196 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
3197 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
3198 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3199 check_update_rgn( hparent
, hrgn
);
3200 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
3201 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3202 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3203 check_update_rgn( hparent
, hrgn
);
3205 /* flush all paint messages */
3206 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3207 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
3210 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
3211 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3212 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3213 check_update_rgn( hparent
, hrgn
);
3214 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
3215 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3216 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
3217 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
3218 check_update_rgn( hparent
, hrgn
);
3219 /* flush all paint messages */
3220 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3223 /* same as above but parent gets completely validated */
3224 SetRect( &rect
, 20, 20, 30, 30 );
3225 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3226 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3227 check_update_rgn( hparent
, hrgn
);
3228 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
3229 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3230 check_update_rgn( hparent
, 0 ); /* no update region */
3231 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3232 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
3234 /* make sure RDW_VALIDATE on child doesn't have the same effect */
3236 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3237 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3238 check_update_rgn( hparent
, hrgn
);
3239 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
3240 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3241 check_update_rgn( hparent
, hrgn
);
3243 /* same as above but normal WM_PAINT doesn't validate parent */
3245 SetRect( &rect
, 20, 20, 30, 30 );
3246 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3247 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3248 check_update_rgn( hparent
, hrgn
);
3249 /* no WM_PAINT in child while parent still pending */
3250 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3251 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
3252 while (PeekMessage( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3253 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
3256 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3257 /* no WM_PAINT in child while parent still pending */
3258 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3259 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
3260 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
3261 /* now that parent is valid child should get WM_PAINT */
3262 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3263 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3264 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3265 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
3267 /* same thing with WS_CLIPCHILDREN in parent */
3269 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
3270 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
3271 /* changing style invalidates non client area, but we need to invalidate something else to see it */
3272 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
3273 ok_sequence( WmEmptySeq
, "No message", FALSE
);
3274 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
3275 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
3278 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
3279 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3280 check_update_rgn( hparent
, hrgn
);
3281 /* no WM_PAINT in child while parent still pending */
3282 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3283 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
3284 /* WM_PAINT in parent first */
3285 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3286 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
3288 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
3290 SetRect( &rect
, 0, 0, 30, 30 );
3291 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
3292 SetRectRgn( hrgn
, 0, 0, 30, 30 );
3293 check_update_rgn( hparent
, hrgn
);
3294 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3295 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
3297 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3299 SetRect( &rect
, -10, 0, 30, 30 );
3300 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
3301 SetRect( &rect
, 0, 0, 20, 20 );
3302 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
3303 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
3304 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
3306 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3308 SetRect( &rect
, -10, 0, 30, 30 );
3309 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
3310 SetRect( &rect
, 0, 0, 100, 100 );
3311 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
3312 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
3313 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
3314 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3315 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
3317 /* test RDW_INTERNALPAINT behavior */
3320 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
3321 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3322 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
3324 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
3325 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3326 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
3328 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
3329 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3330 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
3332 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
3333 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
3334 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
3335 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3336 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
3338 log_all_parent_messages
--;
3339 DestroyWindow( hparent
);
3341 DeleteObject( hrgn
);
3342 DeleteObject( hrgn2
);
3351 static DWORD WINAPI
thread_proc(void *param
)
3354 struct wnd_event
*wnd_event
= (struct wnd_event
*)param
;
3356 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
3357 100, 100, 200, 200, 0, 0, 0, NULL
);
3358 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
3360 SetEvent(wnd_event
->event
);
3362 while (GetMessage(&msg
, 0, 0, 0))
3364 TranslateMessage(&msg
);
3365 DispatchMessage(&msg
);
3371 static void test_interthread_messages(void)
3378 int len
, expected_len
;
3379 struct wnd_event wnd_event
;
3382 wnd_event
.event
= CreateEventW(NULL
, 0, 0, NULL
);
3383 if (!wnd_event
.event
)
3385 trace("skipping interthread message test under win9x\n");
3389 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
3390 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
3392 ok(WaitForSingleObject(wnd_event
.event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
3394 CloseHandle(wnd_event
.event
);
3396 SetLastError(0xdeadbeef);
3397 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeded\n");
3398 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error code %ld\n", GetLastError());
3400 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
3401 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
3403 expected_len
= lstrlenA("window caption text");
3404 memset(buf
, 0, sizeof(buf
));
3405 SetLastError(0xdeadbeef);
3406 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
3407 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
3408 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
3410 msg
.hwnd
= wnd_event
.hwnd
;
3411 msg
.message
= WM_GETTEXT
;
3412 msg
.wParam
= sizeof(buf
);
3413 msg
.lParam
= (LPARAM
)buf
;
3414 memset(buf
, 0, sizeof(buf
));
3415 SetLastError(0xdeadbeef);
3416 len
= DispatchMessageA(&msg
);
3417 ok(!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
3418 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len
, GetLastError());
3420 /* the following test causes an exception in user.exe under win9x */
3421 msg
.hwnd
= wnd_event
.hwnd
;
3422 msg
.message
= WM_TIMER
;
3424 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
3425 SetLastError(0xdeadbeef);
3426 len
= DispatchMessageA(&msg
);
3427 ok(!len
&& GetLastError() == 0xdeadbeef,
3428 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len
, GetLastError());
3430 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
3431 ok( ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
3433 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
3434 CloseHandle(hThread
);
3438 static const struct message WmVkN
[] = {
3439 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
3440 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
3441 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
3442 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
3443 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
3444 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
3447 static const struct message WmShiftVkN
[] = {
3448 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
3449 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
3450 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
3451 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
3452 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
3453 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
3454 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
3455 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
3456 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
3457 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
3460 static const struct message WmCtrlVkN
[] = {
3461 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
3462 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
3463 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
3464 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
3465 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
3466 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
3467 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
3468 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
3469 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3470 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3473 static const struct message WmCtrlVkN_2
[] = {
3474 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
3475 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
3476 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
3477 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
3478 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
3479 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
3480 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3481 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3484 static const struct message WmAltVkN
[] = {
3485 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
3486 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
3487 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
3488 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
3489 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
3490 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
3491 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
3492 { HCBT_SYSCOMMAND
, hook
},
3493 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3494 { WM_SETCURSOR
, sent
|defwinproc
},
3495 { WM_INITMENU
, sent
|defwinproc
},
3496 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
3497 { WM_CAPTURECHANGED
, sent
|defwinproc
},
3498 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
3499 { WM_EXITMENULOOP
, sent
|defwinproc
},
3500 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
3501 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
3502 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
3503 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
3504 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
3505 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
3508 static const struct message WmAltVkN_2
[] = {
3509 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
3510 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
3511 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
3512 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
3513 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
3514 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
3515 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
3516 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
3519 static const struct message WmCtrlAltVkN
[] = {
3520 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
3521 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
3522 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
3523 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
3524 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
3525 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
3526 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
3527 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
3528 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
3529 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
3530 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3531 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
3535 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
3539 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3541 struct message log_msg
;
3543 trace("accel: %p, %04x, %08x, %08lx\n", msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
3545 log_msg
.message
= msg
.message
;
3546 log_msg
.flags
= wparam
|lparam
;
3547 log_msg
.wParam
= msg
.wParam
;
3548 log_msg
.lParam
= msg
.lParam
;
3549 add_message(&log_msg
);
3551 if (!TranslateAccelerator(hwnd
, hAccel
, &msg
))
3553 TranslateMessage(&msg
);
3554 DispatchMessage(&msg
);
3559 static void test_accelerators(void)
3563 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
3564 100, 100, 200, 200, 0, 0, 0, NULL
);
3569 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
3571 state
= GetKeyState(VK_SHIFT
);
3572 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
3573 state
= GetKeyState(VK_CAPITAL
);
3574 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
3576 hAccel
= LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
3577 assert(hAccel
!= 0);
3579 trace("testing VK_N press/release\n");
3581 keybd_event('N', 0, 0, 0);
3582 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3583 pump_msg_loop(hwnd
, hAccel
);
3584 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
3586 trace("testing Shift+VK_N press/release\n");
3588 keybd_event(VK_SHIFT
, 0, 0, 0);
3589 keybd_event('N', 0, 0, 0);
3590 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3591 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
3592 pump_msg_loop(hwnd
, hAccel
);
3593 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
3595 trace("testing Ctrl+VK_N press/release\n");
3597 keybd_event(VK_CONTROL
, 0, 0, 0);
3598 keybd_event('N', 0, 0, 0);
3599 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3600 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3601 pump_msg_loop(hwnd
, hAccel
);
3602 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
3604 trace("testing Alt+VK_N press/release\n");
3606 keybd_event(VK_MENU
, 0, 0, 0);
3607 keybd_event('N', 0, 0, 0);
3608 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3609 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3610 pump_msg_loop(hwnd
, hAccel
);
3611 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
3613 trace("testing Ctrl+Alt+VK_N press/release\n");
3615 keybd_event(VK_CONTROL
, 0, 0, 0);
3616 keybd_event(VK_MENU
, 0, 0, 0);
3617 keybd_event('N', 0, 0, 0);
3618 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3619 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3620 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3621 pump_msg_loop(hwnd
, hAccel
);
3622 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
3624 ret
= DestroyAcceleratorTable(hAccel
);
3625 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
3627 hAccel
= LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
3628 assert(hAccel
!= 0);
3630 trace("testing VK_N press/release\n");
3632 keybd_event('N', 0, 0, 0);
3633 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3634 pump_msg_loop(hwnd
, hAccel
);
3635 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
3637 trace("testing Shift+VK_N press/release\n");
3639 keybd_event(VK_SHIFT
, 0, 0, 0);
3640 keybd_event('N', 0, 0, 0);
3641 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3642 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
3643 pump_msg_loop(hwnd
, hAccel
);
3644 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
3646 trace("testing Ctrl+VK_N press/release 2\n");
3648 keybd_event(VK_CONTROL
, 0, 0, 0);
3649 keybd_event('N', 0, 0, 0);
3650 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3651 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3652 pump_msg_loop(hwnd
, hAccel
);
3653 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
3655 trace("testing Alt+VK_N press/release 2\n");
3657 keybd_event(VK_MENU
, 0, 0, 0);
3658 keybd_event('N', 0, 0, 0);
3659 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3660 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3661 pump_msg_loop(hwnd
, hAccel
);
3662 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
3664 trace("testing Ctrl+Alt+VK_N press/release\n");
3666 keybd_event(VK_CONTROL
, 0, 0, 0);
3667 keybd_event(VK_MENU
, 0, 0, 0);
3668 keybd_event('N', 0, 0, 0);
3669 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
3670 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
3671 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
3672 pump_msg_loop(hwnd
, hAccel
);
3673 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
3675 ret
= DestroyAcceleratorTable(hAccel
);
3676 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
3678 DestroyWindow(hwnd
);
3681 /************* window procedures ********************/
3683 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3685 static long defwndproc_counter
= 0;
3686 static long beginpaint_counter
= 0;
3690 trace("%p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3694 case WM_WINDOWPOSCHANGING
:
3695 case WM_WINDOWPOSCHANGED
:
3697 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
3699 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
3700 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
3701 winpos
->hwnd
, winpos
->hwndInsertAfter
,
3702 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
3704 /* Log only documented flags, win2k uses 0x1000 and 0x2000
3705 * in the high word for internal purposes
3707 wParam
= winpos
->flags
& 0xffff;
3712 msg
.message
= message
;
3713 msg
.flags
= sent
|wparam
|lparam
;
3714 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3715 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
3716 msg
.wParam
= wParam
;
3717 msg
.lParam
= lParam
;
3720 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
3722 HWND parent
= GetParent(hwnd
);
3724 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
3726 GetClientRect(parent
, &rc
);
3727 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
3729 trace("ptReserved = (%ld,%ld)\n"
3730 "ptMaxSize = (%ld,%ld)\n"
3731 "ptMaxPosition = (%ld,%ld)\n"
3732 "ptMinTrackSize = (%ld,%ld)\n"
3733 "ptMaxTrackSize = (%ld,%ld)\n",
3734 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
3735 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
3736 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
3737 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
3738 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
3740 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
3741 minmax
->ptMaxSize
.x
, rc
.right
);
3742 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
3743 minmax
->ptMaxSize
.y
, rc
.bottom
);
3746 if (message
== WM_PAINT
)
3749 beginpaint_counter
++;
3750 BeginPaint( hwnd
, &ps
);
3751 beginpaint_counter
--;
3752 EndPaint( hwnd
, &ps
);
3756 defwndproc_counter
++;
3757 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
3758 defwndproc_counter
--;
3763 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3765 static long defwndproc_counter
= 0;
3769 trace("popup: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3771 msg
.message
= message
;
3772 msg
.flags
= sent
|wparam
|lparam
;
3773 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3774 msg
.wParam
= wParam
;
3775 msg
.lParam
= lParam
;
3778 if (message
== WM_CREATE
)
3780 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
3781 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
3784 defwndproc_counter
++;
3785 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
3786 defwndproc_counter
--;
3791 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3793 static long defwndproc_counter
= 0;
3794 static long beginpaint_counter
= 0;
3798 trace("parent: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3800 if (log_all_parent_messages
||
3801 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
3802 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
3803 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
3804 message
== WM_IME_SETCONTEXT
)
3806 msg
.message
= message
;
3807 msg
.flags
= sent
|parent
|wparam
|lparam
;
3808 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3809 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
3810 msg
.wParam
= wParam
;
3811 msg
.lParam
= lParam
;
3815 if (message
== WM_PAINT
)
3818 beginpaint_counter
++;
3819 BeginPaint( hwnd
, &ps
);
3820 beginpaint_counter
--;
3821 EndPaint( hwnd
, &ps
);
3825 defwndproc_counter
++;
3826 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
3827 defwndproc_counter
--;
3832 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3834 static long defwndproc_counter
= 0;
3838 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3840 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
3841 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
3842 if (after_end_dialog
)
3843 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
3845 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
3847 msg
.message
= message
;
3848 msg
.flags
= sent
|wparam
|lparam
;
3849 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3850 msg
.wParam
= wParam
;
3851 msg
.lParam
= lParam
;
3854 defwndproc_counter
++;
3855 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
3856 defwndproc_counter
--;
3861 static BOOL
RegisterWindowClasses(void)
3866 cls
.lpfnWndProc
= MsgCheckProcA
;
3869 cls
.hInstance
= GetModuleHandleA(0);
3871 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
3872 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
3873 cls
.lpszMenuName
= NULL
;
3874 cls
.lpszClassName
= "TestWindowClass";
3875 if(!RegisterClassA(&cls
)) return FALSE
;
3877 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
3878 cls
.lpszClassName
= "TestPopupClass";
3879 if(!RegisterClassA(&cls
)) return FALSE
;
3881 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
3882 cls
.lpszClassName
= "TestParentClass";
3883 if(!RegisterClassA(&cls
)) return FALSE
;
3885 cls
.lpfnWndProc
= DefWindowProcA
;
3886 cls
.lpszClassName
= "SimpleWindowClass";
3887 if(!RegisterClassA(&cls
)) return FALSE
;
3889 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
3890 cls
.lpfnWndProc
= TestDlgProcA
;
3891 cls
.lpszClassName
= "TestDialogClass";
3892 if(!RegisterClassA(&cls
)) return FALSE
;
3897 static HHOOK hCBT_hook
;
3899 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
3903 trace("CBT: %d, %08x, %08lx\n", nCode
, wParam
, lParam
);
3905 if (nCode
== HCBT_SYSCOMMAND
)
3909 msg
.message
= nCode
;
3911 msg
.wParam
= wParam
;
3912 msg
.lParam
= lParam
;
3915 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
3918 /* Log also SetFocus(0) calls */
3919 if (!wParam
) wParam
= lParam
;
3921 if (GetClassNameA((HWND
)wParam
, buf
, sizeof(buf
)))
3923 if (!strcmp(buf
, "TestWindowClass") ||
3924 !strcmp(buf
, "TestParentClass") ||
3925 !strcmp(buf
, "TestPopupClass") ||
3926 !strcmp(buf
, "SimpleWindowClass") ||
3927 !strcmp(buf
, "TestDialogClass") ||
3928 !strcmp(buf
, "MDI_frame_class") ||
3929 !strcmp(buf
, "MDI_client_class") ||
3930 !strcmp(buf
, "MDI_child_class") ||
3931 !strcmp(buf
, "my_button_class") ||
3932 !strcmp(buf
, "#32770"))
3936 msg
.message
= nCode
;
3938 msg
.wParam
= wParam
;
3939 msg
.lParam
= lParam
;
3943 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
3946 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
3947 static const WCHAR wszAnsi
[] = {'U',0};
3949 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3953 case CB_FINDSTRINGEXACT
:
3954 trace("String: %p\n", (LPCWSTR
)lParam
);
3955 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
3957 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
3961 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
3964 static void test_message_conversion(void)
3966 static const WCHAR wszMsgConversionClass
[] =
3967 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
3974 cls
.lpfnWndProc
= MsgConversionProcW
;
3977 cls
.hInstance
= GetModuleHandleW(NULL
);
3979 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
3980 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
3981 cls
.lpszMenuName
= NULL
;
3982 cls
.lpszClassName
= wszMsgConversionClass
;
3983 /* this call will fail on Win9x, but that doesn't matter as this test is
3984 * meaningless on those platforms */
3985 if(!RegisterClassW(&cls
)) return;
3987 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
3988 100, 100, 200, 200, 0, 0, 0, NULL
);
3989 ok(hwnd
!= NULL
, "Window creation failed\n");
3993 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
3994 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3995 ok(lRes
== 0, "String should have been converted\n");
3996 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
3997 ok(lRes
== 1, "String shouldn't have been converted\n");
4001 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
4002 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4003 ok(lRes
== 1, "String shouldn't have been converted\n");
4004 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4005 ok(lRes
== 1, "String shouldn't have been converted\n");
4007 /* Synchronous messages */
4009 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4010 ok(lRes
== 0, "String should have been converted\n");
4011 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4012 ok(lRes
== 1, "String shouldn't have been converted\n");
4014 /* Asynchronous messages */
4017 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4018 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4019 "PostMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4021 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4022 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4023 "PostMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4025 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4026 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4027 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4029 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4030 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4031 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4033 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4034 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4035 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4037 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
4038 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4039 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4041 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
4042 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4043 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4045 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
4046 ok(lRes
== 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4047 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
4050 typedef struct _thread_info
4057 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT id
, DWORD dwTime
)
4061 #define TIMER_ID 0x19
4063 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
4065 thread_info
*info
= x
;
4068 r
= KillTimer(info
->hWnd
, 0x19);
4069 ok(r
,"KillTimer failed in thread\n");
4070 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
4071 ok(r
,"SetTimer failed in thread\n");
4072 ok(r
==TIMER_ID
,"SetTimer id different\n");
4073 r
= SetEvent(info
->handles
[0]);
4074 ok(r
,"SetEvent failed in thread\n");
4078 static void test_timers(void)
4083 info
.hWnd
= CreateWindow ("TestWindowClass", NULL
,
4084 WS_OVERLAPPEDWINDOW
,
4085 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
4088 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
4089 ok(info
.id
, "SetTimer failed\n");
4090 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
4091 info
.handles
[0] = CreateEvent(NULL
,0,0,NULL
);
4092 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
4094 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
4096 WaitForSingleObject(info
.handles
[1], INFINITE
);
4098 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
4100 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
4105 if (!RegisterWindowClasses()) assert(0);
4107 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
4111 test_mdi_messages();
4112 test_button_messages();
4113 test_paint_messages();
4114 test_interthread_messages();
4115 test_message_conversion();
4116 test_accelerators();
4119 UnhookWindowsHookEx(hCBT_hook
);