2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004, 2005 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
42 static HWINEVENTHOOK hEvent_hook;
45 FIXME: add tests for these
46 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
47 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
48 WS_THICKFRAME: thick border
49 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
50 WS_BORDER (default for overlapped windows): single black border
51 none (default for child (and popup?) windows): no border
68 UINT message; /* the WM_* code */
69 msg_flags_t flags; /* message props */
70 WPARAM wParam; /* expected value of wParam */
71 LPARAM lParam; /* expected value of lParam */
74 /* Empty message sequence */
75 static const struct message WmEmptySeq[] =
79 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
80 static const struct message WmCreateOverlappedSeq[] = {
81 { HCBT_CREATEWND, hook },
82 { WM_GETMINMAXINFO, sent },
83 { WM_NCCREATE, sent },
84 { WM_NCCALCSIZE, sent|wparam, 0 },
85 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
87 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
90 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
91 * for a not visible overlapped window.
93 static const struct message WmSWP_ShowOverlappedSeq[] = {
94 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
95 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
96 { WM_NCPAINT, sent|wparam|optional, 1 },
97 { WM_GETTEXT, sent|defwinproc|optional },
98 { WM_ERASEBKGND, sent|optional },
99 { HCBT_ACTIVATE, hook },
100 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
101 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
102 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
103 { WM_ACTIVATEAPP, sent|wparam, 1 },
104 { WM_NCACTIVATE, sent|wparam, 1 },
105 { WM_GETTEXT, sent|defwinproc|optional },
106 { WM_ACTIVATE, sent|wparam, 1 },
107 { HCBT_SETFOCUS, hook },
108 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
109 { WM_IME_NOTIFY, sent|defwinproc|optional },
110 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
111 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
112 { WM_NCPAINT, sent|wparam|optional, 1 },
113 { WM_GETTEXT, sent|defwinproc|optional },
114 { WM_ERASEBKGND, sent|optional },
115 /* Win9x adds SWP_NOZORDER below */
116 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
117 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
118 { WM_NCPAINT, sent|wparam|optional, 1 },
119 { WM_ERASEBKGND, sent|optional },
122 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
123 * for a visible overlapped window.
125 static const struct message WmSWP_HideOverlappedSeq[] = {
126 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
127 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
128 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
132 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
133 * for a visible overlapped window.
135 static const struct message WmSWP_ResizeSeq[] = {
136 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE },
137 { WM_GETMINMAXINFO, sent|defwinproc },
138 { WM_NCCALCSIZE, sent|wparam, TRUE },
139 { WM_NCPAINT, sent|optional },
140 { WM_GETTEXT, sent|defwinproc|optional },
141 { WM_ERASEBKGND, sent|optional },
142 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
143 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
144 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
145 { WM_NCPAINT, sent|optional },
146 { WM_GETTEXT, sent|defwinproc|optional },
147 { WM_ERASEBKGND, sent|optional },
151 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
152 * for a visible popup window.
154 static const struct message WmSWP_ResizePopupSeq[] = {
155 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE },
156 { WM_NCCALCSIZE, sent|wparam, TRUE },
157 { WM_NCPAINT, sent|optional },
158 { WM_GETTEXT, sent|defwinproc|optional },
159 { WM_ERASEBKGND, sent|optional },
160 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
161 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
162 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
163 { WM_NCPAINT, sent|optional },
164 { WM_GETTEXT, sent|defwinproc|optional },
165 { WM_ERASEBKGND, sent|optional },
169 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
170 * for a visible overlapped window.
172 static const struct message WmSWP_MoveSeq[] = {
173 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE },
174 { WM_NCPAINT, sent|optional },
175 { WM_GETTEXT, sent|defwinproc|optional },
176 { WM_ERASEBKGND, sent|optional },
177 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE },
178 { WM_MOVE, sent|defwinproc|wparam, 0 },
182 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
183 static const struct message WmShowOverlappedSeq[] = {
184 { WM_SHOWWINDOW, sent|wparam, 1 },
185 { WM_NCPAINT, sent|wparam|optional, 1 },
186 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
187 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
188 { WM_NCPAINT, sent|wparam|optional, 1 },
189 { WM_GETTEXT, sent|defwinproc|optional },
190 { WM_ERASEBKGND, sent|optional },
191 { HCBT_ACTIVATE, hook },
192 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
193 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
194 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
195 { WM_ACTIVATEAPP, sent|wparam, 1 },
196 { WM_NCACTIVATE, sent|wparam, 1 },
197 { WM_GETTEXT, sent|defwinproc|optional },
198 { WM_ACTIVATE, sent|wparam, 1 },
199 { HCBT_SETFOCUS, hook },
200 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
201 { WM_IME_NOTIFY, sent|defwinproc|optional },
202 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
203 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
204 { WM_NCPAINT, sent|wparam|optional, 1 },
205 { WM_GETTEXT, sent|defwinproc|optional },
206 { WM_ERASEBKGND, sent|optional },
207 /* Win9x adds SWP_NOZORDER below */
208 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
209 { WM_NCCALCSIZE, sent|optional },
210 { WM_NCPAINT, sent|optional },
211 { WM_ERASEBKGND, sent|optional },
212 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
213 * messages. Does that mean that CreateWindow doesn't set initial
214 * window dimensions for overlapped windows?
221 /* ShowWindow(SW_HIDE) for a visible overlapped window */
222 static const struct message WmHideOverlappedSeq[] = {
223 { WM_SHOWWINDOW, sent|wparam, 0 },
224 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
225 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
226 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
229 { WM_NCACTIVATE, sent|wparam, 0 },
230 { WM_ACTIVATE, sent|wparam, 0 },
231 { WM_ACTIVATEAPP, sent|wparam, 0 },
232 { WM_KILLFOCUS, sent|wparam, 0 },
233 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
234 { WM_IME_NOTIFY, sent|optional|defwinproc },
237 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
238 static const struct message WmHideInvisibleOverlappedSeq[] = {
241 /* DestroyWindow for a visible overlapped window */
242 static const struct message WmDestroyOverlappedSeq[] = {
243 { HCBT_DESTROYWND, hook },
244 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
245 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
246 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
247 { WM_NCACTIVATE, sent|wparam, 0 },
248 { WM_ACTIVATE, sent|wparam, 0 },
249 { WM_ACTIVATEAPP, sent|wparam, 0 },
250 { WM_KILLFOCUS, sent|wparam, 0 },
251 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
252 { WM_IME_NOTIFY, sent|optional|defwinproc },
253 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
254 { WM_DESTROY, sent },
255 { WM_NCDESTROY, sent },
258 /* CreateWindow (for a child popup window, not initially visible) */
259 static const struct message WmCreateChildPopupSeq[] = {
260 { HCBT_CREATEWND, hook },
261 { WM_NCCREATE, sent },
262 { WM_NCCALCSIZE, sent|wparam, 0 },
264 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
269 /* CreateWindow (for a popup window, not initially visible,
270 * which sets WS_VISIBLE in WM_CREATE handler)
272 static const struct message WmCreateInvisiblePopupSeq[] = {
273 { HCBT_CREATEWND, hook },
274 { WM_NCCREATE, sent },
275 { WM_NCCALCSIZE, sent|wparam, 0 },
277 { WM_STYLECHANGING, sent },
278 { WM_STYLECHANGED, sent },
279 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
284 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
285 * for a popup window with WS_VISIBLE style set
287 static const struct message WmShowVisiblePopupSeq_2[] = {
288 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
291 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
292 * for a popup window with WS_VISIBLE style set
294 static const struct message WmShowVisiblePopupSeq_3[] = {
295 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
296 { HCBT_ACTIVATE, hook },
297 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
298 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
299 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
300 { WM_NCACTIVATE, sent|wparam, 1 },
301 { WM_ACTIVATE, sent|wparam, 1 },
302 { HCBT_SETFOCUS, hook },
303 { WM_KILLFOCUS, sent|parent },
304 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
305 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
306 { WM_IME_NOTIFY, sent|defwinproc|optional },
307 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
308 { WM_SETFOCUS, sent|defwinproc },
311 /* CreateWindow (for child window, not initially visible) */
312 static const struct message WmCreateChildSeq[] = {
313 { HCBT_CREATEWND, hook },
314 { WM_NCCREATE, sent },
315 /* child is inserted into parent's child list after WM_NCCREATE returns */
316 { WM_NCCALCSIZE, sent|wparam, 0 },
318 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
321 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
324 /* CreateWindow (for maximized child window, not initially visible) */
325 static const struct message WmCreateMaximizedChildSeq[] = {
326 { HCBT_CREATEWND, hook },
327 { WM_NCCREATE, sent },
328 { WM_NCCALCSIZE, sent|wparam, 0 },
330 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
333 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
334 { WM_GETMINMAXINFO, sent },
335 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
336 { WM_NCCALCSIZE, sent|wparam, 1 },
337 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 },
338 { WM_SIZE, sent|defwinproc },
339 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
340 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
343 /* CreateWindow (for a child window, initially visible) */
344 static const struct message WmCreateVisibleChildSeq[] = {
345 { HCBT_CREATEWND, hook },
346 { WM_NCCREATE, sent },
347 /* child is inserted into parent's child list after WM_NCCREATE returns */
348 { WM_NCCALCSIZE, sent|wparam, 0 },
349 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
351 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
354 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
355 { WM_SHOWWINDOW, sent|wparam, 1 },
356 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
357 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
358 { WM_ERASEBKGND, sent|parent|optional },
359 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
362 /* ShowWindow(SW_SHOW) for a not visible child window */
363 static const struct message WmShowChildSeq[] = {
364 { WM_SHOWWINDOW, sent|wparam, 1 },
365 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
366 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
367 { WM_ERASEBKGND, sent|parent|optional },
368 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
371 /* ShowWindow(SW_HIDE) for a visible child window */
372 static const struct message WmHideChildSeq[] = {
373 { WM_SHOWWINDOW, sent|wparam, 0 },
374 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
375 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
376 { WM_ERASEBKGND, sent|parent|optional },
377 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
380 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
381 * for a not visible child window
383 static const struct message WmShowChildSeq_2[] = {
384 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
385 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
386 { WM_CHILDACTIVATE, sent },
387 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
390 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
391 * for a not visible child window
393 static const struct message WmShowChildSeq_3[] = {
394 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
395 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
396 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
399 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
400 * for a visible child window with a caption
402 static const struct message WmShowChildSeq_4[] = {
403 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
404 { WM_CHILDACTIVATE, sent },
407 /* ShowWindow(SW_SHOW) for child with invisible parent */
408 static const struct message WmShowChildInvisibleParentSeq[] = {
409 { WM_SHOWWINDOW, sent|wparam, 1 },
412 /* ShowWindow(SW_HIDE) for child with invisible parent */
413 static const struct message WmHideChildInvisibleParentSeq[] = {
414 { WM_SHOWWINDOW, sent|wparam, 0 },
417 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
418 static const struct message WmShowChildInvisibleParentSeq_2[] = {
419 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
420 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
421 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
424 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
425 static const struct message WmHideChildInvisibleParentSeq_2[] = {
426 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
427 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
428 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
431 /* DestroyWindow for a visible child window */
432 static const struct message WmDestroyChildSeq[] = {
433 { HCBT_DESTROYWND, hook },
434 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
435 { WM_SHOWWINDOW, sent|wparam, 0 },
436 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
437 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
438 { WM_ERASEBKGND, sent|parent|optional },
439 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
440 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
441 { WM_KILLFOCUS, sent },
442 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
443 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
444 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
445 { WM_SETFOCUS, sent|parent },
446 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
447 { WM_DESTROY, sent },
448 { WM_DESTROY, sent|optional }, /* some other (IME?) window */
449 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */
450 { WM_NCDESTROY, sent },
453 /* Moving the mouse in nonclient area */
454 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
455 { WM_NCHITTEST, sent },
456 { WM_SETCURSOR, sent },
457 { WM_NCMOUSEMOVE, posted },
460 /* Moving the mouse in client area */
461 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
462 { WM_NCHITTEST, sent },
463 { WM_SETCURSOR, sent },
464 { WM_MOUSEMOVE, posted },
467 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
468 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
469 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
470 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
471 { WM_GETMINMAXINFO, sent|defwinproc },
472 { WM_ENTERSIZEMOVE, sent|defwinproc },
473 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
474 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
475 { WM_MOVE, sent|defwinproc },
476 { WM_EXITSIZEMOVE, sent|defwinproc },
479 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
480 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
481 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
482 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
483 { WM_GETMINMAXINFO, sent|defwinproc },
484 { WM_ENTERSIZEMOVE, sent|defwinproc },
485 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
486 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
487 { WM_GETMINMAXINFO, sent|defwinproc },
488 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
489 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
490 { WM_GETTEXT, sent|defwinproc },
491 { WM_ERASEBKGND, sent|defwinproc },
492 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
493 { WM_MOVE, sent|defwinproc },
494 { WM_SIZE, sent|defwinproc },
495 { WM_EXITSIZEMOVE, sent|defwinproc },
498 /* Resizing child window with MoveWindow (32) */
499 static const struct message WmResizingChildWithMoveWindowSeq[] = {
500 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
501 { WM_NCCALCSIZE, sent|wparam, 1 },
502 { WM_ERASEBKGND, sent|optional },
503 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
504 { WM_MOVE, sent|defwinproc },
505 { WM_SIZE, sent|defwinproc },
506 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
509 /* Clicking on inactive button */
510 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
511 { WM_NCHITTEST, sent },
512 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
513 { WM_MOUSEACTIVATE, sent },
514 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
515 { WM_SETCURSOR, sent },
516 { WM_SETCURSOR, sent|parent|defwinproc },
517 { WM_LBUTTONDOWN, posted },
518 { WM_KILLFOCUS, posted|parent },
519 { WM_SETFOCUS, posted },
520 { WM_CTLCOLORBTN, posted|parent },
521 { BM_SETSTATE, posted },
522 { WM_CTLCOLORBTN, posted|parent },
523 { WM_LBUTTONUP, posted },
524 { BM_SETSTATE, posted },
525 { WM_CTLCOLORBTN, posted|parent },
526 { WM_COMMAND, posted|parent },
529 /* Reparenting a button (16/32) */
530 /* The last child (button) reparented gets topmost for its new parent. */
531 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
532 { WM_SHOWWINDOW, sent|wparam, 0 },
533 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
534 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
535 { WM_ERASEBKGND, sent|parent },
536 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
537 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
538 { WM_CHILDACTIVATE, sent },
539 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
540 { WM_MOVE, sent|defwinproc },
541 { WM_SHOWWINDOW, sent|wparam, 1 },
544 /* Creation of a custom dialog (32) */
545 static const struct message WmCreateCustomDialogSeq[] = {
546 { HCBT_CREATEWND, hook },
547 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
548 { WM_GETMINMAXINFO, sent },
549 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
550 { WM_NCCREATE, sent },
551 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
552 { WM_NCCALCSIZE, sent|wparam, 0 },
553 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
554 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
556 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
557 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
558 { WM_SHOWWINDOW, sent|wparam, 1 },
559 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
560 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
561 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
562 { HCBT_ACTIVATE, hook },
563 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
565 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
567 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
568 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
570 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
572 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
573 { WM_NCACTIVATE, sent|wparam, 1 },
574 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
575 { WM_GETTEXT, sent|optional|defwinproc },
576 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
577 { WM_GETICON, sent|optional|defwinproc },
578 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
579 { WM_GETICON, sent|optional|defwinproc },
580 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
581 { WM_GETICON, sent|optional|defwinproc },
582 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
583 { WM_GETTEXT, sent|optional|defwinproc },
584 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
585 { WM_ACTIVATE, sent|wparam, 1 },
586 { WM_KILLFOCUS, sent|parent },
587 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
588 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
589 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
590 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
591 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
592 { WM_IME_NOTIFY, sent|optional|defwinproc },
593 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
594 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
595 { WM_SETFOCUS, sent },
596 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
597 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
598 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
599 { WM_NCPAINT, sent|wparam, 1 },
600 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
601 { WM_GETTEXT, sent|optional|defwinproc },
602 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
603 { WM_GETICON, sent|optional|defwinproc },
604 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
605 { WM_GETICON, sent|optional|defwinproc },
606 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
607 { WM_GETICON, sent|optional|defwinproc },
608 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
609 { WM_GETTEXT, sent|optional|defwinproc },
610 { WM_ERASEBKGND, sent },
611 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
612 { WM_CTLCOLORDLG, sent|defwinproc },
613 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
614 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
615 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
616 { WM_GETTEXT, sent|optional },
617 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
618 { WM_GETICON, sent|optional },
619 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
620 { WM_GETICON, sent|optional },
621 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
622 { WM_GETICON, sent|optional },
623 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
624 { WM_GETTEXT, sent|optional },
625 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
626 { WM_NCCALCSIZE, sent|optional },
627 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
628 { WM_NCPAINT, sent|optional },
629 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
630 { WM_GETTEXT, sent|optional|defwinproc },
631 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
632 { WM_GETICON, sent|optional|defwinproc },
633 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
634 { WM_GETICON, sent|optional|defwinproc },
635 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
636 { WM_GETICON, sent|optional|defwinproc },
637 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
638 { WM_GETTEXT, sent|optional|defwinproc },
639 { WM_ERASEBKGND, sent|optional },
640 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
641 { WM_CTLCOLORDLG, sent|optional|defwinproc },
643 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
647 /* Calling EndDialog for a custom dialog (32) */
648 static const struct message WmEndCustomDialogSeq[] = {
649 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
650 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
651 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
652 { WM_GETTEXT, sent|optional },
653 { WM_GETICON, sent|optional },
654 { WM_GETICON, sent|optional },
655 { WM_GETICON, sent|optional },
656 { HCBT_ACTIVATE, hook },
657 { WM_NCACTIVATE, sent|wparam, 0 },
658 { WM_GETTEXT, sent|optional|defwinproc },
659 { WM_GETICON, sent|optional|defwinproc },
660 { WM_GETICON, sent|optional|defwinproc },
661 { WM_GETICON, sent|optional|defwinproc },
662 { WM_GETTEXT, sent|optional|defwinproc },
663 { WM_ACTIVATE, sent|wparam, 0 },
664 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
665 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
666 { HCBT_SETFOCUS, hook },
667 { WM_KILLFOCUS, sent },
668 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
669 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
670 { WM_IME_NOTIFY, sent|optional },
671 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
672 { WM_SETFOCUS, sent|parent|defwinproc },
675 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
676 static const struct message WmShowCustomDialogSeq[] = {
677 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
678 { WM_SHOWWINDOW, sent|wparam, 1 },
679 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
680 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
681 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
682 { HCBT_ACTIVATE, hook },
683 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
685 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
686 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
688 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
689 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
690 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
691 { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
692 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
693 { WM_NCACTIVATE, sent|wparam, 1 },
694 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
695 { WM_ACTIVATE, sent|wparam, 1 },
697 { WM_KILLFOCUS, sent|parent },
698 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
699 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
700 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
701 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
702 { WM_IME_NOTIFY, sent|optional|defwinproc },
703 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
704 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
705 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
706 { WM_SETFOCUS, sent },
707 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
708 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
709 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
710 { WM_NCPAINT, sent|wparam, 1 },
711 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
712 { WM_ERASEBKGND, sent },
713 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
714 { WM_CTLCOLORDLG, sent|defwinproc },
716 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
717 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
720 /* Creation and destruction of a modal dialog (32) */
721 static const struct message WmModalDialogSeq[] = {
722 { WM_CANCELMODE, sent|parent },
723 { HCBT_SETFOCUS, hook },
724 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
725 { WM_KILLFOCUS, sent|parent },
726 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
727 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
728 { WM_ENABLE, sent|parent|wparam, 0 },
729 { HCBT_CREATEWND, hook },
730 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
731 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
732 { WM_SETFONT, sent },
733 { WM_INITDIALOG, sent },
734 { WM_CHANGEUISTATE, sent|optional },
735 { WM_SHOWWINDOW, sent },
736 { HCBT_ACTIVATE, hook },
737 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
738 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
739 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
740 { WM_NCACTIVATE, sent|wparam, 1 },
741 { WM_GETICON, sent|optional },
742 { WM_GETICON, sent|optional },
743 { WM_GETICON, sent|optional },
744 { WM_GETTEXT, sent|optional },
745 { WM_ACTIVATE, sent|wparam, 1 },
746 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
747 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
748 { WM_NCPAINT, sent },
749 { WM_GETICON, sent|optional },
750 { WM_GETICON, sent|optional },
751 { WM_GETICON, sent|optional },
752 { WM_GETTEXT, sent|optional },
753 { WM_ERASEBKGND, sent },
754 { WM_CTLCOLORDLG, sent },
755 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
756 { WM_GETICON, sent|optional },
757 { WM_GETICON, sent|optional },
758 { WM_GETICON, sent|optional },
759 { WM_GETTEXT, sent|optional },
760 { WM_NCCALCSIZE, sent|optional },
761 { WM_NCPAINT, sent|optional },
762 { WM_GETICON, sent|optional },
763 { WM_GETICON, sent|optional },
764 { WM_GETICON, sent|optional },
765 { WM_GETTEXT, sent|optional },
766 { WM_ERASEBKGND, sent|optional },
767 { WM_CTLCOLORDLG, sent|optional },
768 { WM_PAINT, sent|optional },
769 { WM_CTLCOLORBTN, sent },
770 { WM_ENTERIDLE, sent|parent|optional },
772 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
773 { WM_ENABLE, sent|parent|wparam, 1 },
774 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
775 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
776 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
777 { WM_GETICON, sent|optional },
778 { WM_GETICON, sent|optional },
779 { WM_GETICON, sent|optional },
780 { WM_GETTEXT, sent|optional },
781 { HCBT_ACTIVATE, hook },
782 { WM_NCACTIVATE, sent|wparam, 0 },
783 { WM_GETICON, sent|optional },
784 { WM_GETICON, sent|optional },
785 { WM_GETICON, sent|optional },
786 { WM_GETTEXT, sent|optional },
787 { WM_ACTIVATE, sent|wparam, 0 },
788 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
789 { WM_WINDOWPOSCHANGING, sent|optional },
790 { HCBT_SETFOCUS, hook },
791 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
792 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
793 { WM_SETFOCUS, sent|parent|defwinproc },
794 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
795 { HCBT_DESTROYWND, hook },
796 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
797 { WM_DESTROY, sent },
798 { WM_NCDESTROY, sent },
801 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
802 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
803 /* (inside dialog proc, handling WM_INITDIALOG) */
804 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
805 { WM_NCCALCSIZE, sent },
806 { WM_NCACTIVATE, sent|parent|wparam, 0 },
807 { WM_GETTEXT, sent|defwinproc },
808 { WM_ACTIVATE, sent|parent|wparam, 0 },
809 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
810 { WM_WINDOWPOSCHANGING, sent|parent },
811 { WM_NCACTIVATE, sent|wparam, 1 },
812 { WM_ACTIVATE, sent|wparam, 1 },
813 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
814 { WM_SIZE, sent|defwinproc },
815 /* (setting focus) */
816 { WM_SHOWWINDOW, sent|wparam, 1 },
817 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
818 { WM_NCPAINT, sent },
819 { WM_GETTEXT, sent|defwinproc },
820 { WM_ERASEBKGND, sent },
821 { WM_CTLCOLORDLG, sent|defwinproc },
822 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
824 /* (bunch of WM_CTLCOLOR* for each control) */
825 { WM_PAINT, sent|parent },
826 { WM_ENTERIDLE, sent|parent|wparam, 0 },
827 { WM_SETCURSOR, sent|parent },
830 /* SetMenu for NonVisible windows with size change*/
831 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
832 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
833 { WM_NCCALCSIZE, sent|wparam, 1 },
834 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
835 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW },
836 { WM_MOVE, sent|defwinproc },
837 { WM_SIZE, sent|defwinproc },
838 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
839 { WM_GETICON, sent|optional },
840 { WM_GETICON, sent|optional },
841 { WM_GETICON, sent|optional },
842 { WM_GETTEXT, sent|optional },
843 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
846 /* SetMenu for NonVisible windows with no size change */
847 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
848 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
849 { WM_NCCALCSIZE, sent|wparam, 1 },
850 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
851 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
854 /* SetMenu for Visible windows with size change */
855 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
856 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
857 { WM_NCCALCSIZE, sent|wparam, 1 },
858 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
859 { WM_NCPAINT, sent|wparam, 1 },
860 { WM_GETTEXT, sent|defwinproc|optional },
861 { WM_ERASEBKGND, sent|optional },
862 { WM_ACTIVATE, sent|optional },
863 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
864 { WM_MOVE, sent|defwinproc },
865 { WM_SIZE, sent|defwinproc },
866 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
867 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
868 { WM_NCPAINT, sent|wparam|optional, 1 },
869 { WM_ERASEBKGND, sent|optional },
872 /* SetMenu for Visible windows with no size change */
873 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
874 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
875 { WM_NCCALCSIZE, sent|wparam, 1 },
876 { WM_NCPAINT, sent|wparam, 1 },
877 { WM_GETTEXT, sent|defwinproc|optional },
878 { WM_ERASEBKGND, sent|optional },
879 { WM_ACTIVATE, sent|optional },
880 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
881 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
884 /* DrawMenuBar for a visible window */
885 static const struct message WmDrawMenuBarSeq[] =
887 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
888 { WM_NCCALCSIZE, sent|wparam, 1 },
889 { WM_NCPAINT, sent|wparam, 1 },
890 { WM_GETTEXT, sent|defwinproc|optional },
891 { WM_ERASEBKGND, sent|optional },
892 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
893 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
897 static const struct message WmSetRedrawFalseSeq[] =
899 { WM_SETREDRAW, sent|wparam, 0 },
903 static const struct message WmSetRedrawTrueSeq[] =
905 { WM_SETREDRAW, sent|wparam, 1 },
909 static const struct message WmEnableWindowSeq[] =
911 { WM_CANCELMODE, sent },
912 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
917 static const struct message WmGetScrollRangeSeq[] =
919 { SBM_GETRANGE, sent },
922 static const struct message WmGetScrollInfoSeq[] =
924 { SBM_GETSCROLLINFO, sent },
927 static const struct message WmSetScrollRangeSeq[] =
929 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
930 sends SBM_SETSCROLLINFO.
932 { SBM_SETSCROLLINFO, sent },
935 /* SetScrollRange for a window without a non-client area */
936 static const struct message WmSetScrollRangeHSeq_empty[] =
938 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 },
941 static const struct message WmSetScrollRangeVSeq_empty[] =
943 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 },
946 static const struct message WmSetScrollRangeHVSeq[] =
948 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
949 { WM_NCCALCSIZE, sent|wparam, 1 },
950 { WM_GETTEXT, sent|defwinproc|optional },
951 { WM_ERASEBKGND, sent|optional },
952 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
953 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
956 /* SetScrollRange for a window with a non-client area */
957 static const struct message WmSetScrollRangeHV_NC_Seq[] =
959 { WM_WINDOWPOSCHANGING, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
960 { WM_NCCALCSIZE, sent|wparam, 1 },
961 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
962 { WM_NCPAINT, sent|optional },
963 { WM_GETTEXT, sent|defwinproc|optional },
964 { WM_GETICON, sent|optional|defwinproc },
965 { WM_GETICON, sent|optional|defwinproc },
966 { WM_GETICON, sent|optional|defwinproc },
967 { WM_GETTEXT, sent|defwinproc|optional },
968 { WM_ERASEBKGND, sent|optional },
969 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
970 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
971 { WM_SIZE, sent|defwinproc },
972 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
973 { WM_GETTEXT, sent|optional },
974 { WM_GETICON, sent|optional },
975 { WM_GETICON, sent|optional },
976 { WM_GETICON, sent|optional },
977 { WM_GETTEXT, sent|optional },
978 { WM_GETICON, sent|optional },
979 { WM_GETICON, sent|optional },
980 { WM_GETICON, sent|optional },
981 { WM_GETTEXT, sent|optional },
982 { WM_GETICON, sent|optional },
983 { WM_GETICON, sent|optional },
984 { WM_GETICON, sent|optional },
985 { WM_GETTEXT, sent|optional },
988 /* test if we receive the right sequence of messages */
989 /* after calling ShowWindow( SW_SHOWNA) */
990 static const struct message WmSHOWNAChildInvisParInvis[] = {
991 { WM_SHOWWINDOW, sent|wparam, 1 },
994 static const struct message WmSHOWNAChildVisParInvis[] = {
995 { WM_SHOWWINDOW, sent|wparam, 1 },
998 static const struct message WmSHOWNAChildVisParVis[] = {
999 { WM_SHOWWINDOW, sent|wparam, 1 },
1000 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
1003 static const struct message WmSHOWNAChildInvisParVis[] = {
1004 { WM_SHOWWINDOW, sent|wparam, 1 },
1005 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER},
1006 { WM_ERASEBKGND, sent|optional },
1007 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1010 static const struct message WmSHOWNATopVisible[] = {
1011 { WM_SHOWWINDOW, sent|wparam, 1 },
1012 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
1015 static const struct message WmSHOWNATopInvisible[] = {
1016 { WM_SHOWWINDOW, sent|wparam, 1 },
1017 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1018 { WM_NCPAINT, sent|wparam, 1 },
1019 { WM_GETTEXT, sent|defwinproc|optional },
1020 { WM_ERASEBKGND, sent|optional },
1021 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1027 static int after_end_dialog;
1028 static int sequence_cnt, sequence_size;
1029 static struct message* sequence;
1030 static int log_all_parent_messages;
1032 static void add_message(const struct message *msg)
1037 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
1039 if (sequence_cnt == sequence_size)
1042 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
1046 sequence[sequence_cnt].message = msg->message;
1047 sequence[sequence_cnt].flags = msg->flags;
1048 sequence[sequence_cnt].wParam = msg->wParam;
1049 sequence[sequence_cnt].lParam = msg->lParam;
1054 static void flush_sequence()
1056 HeapFree(GetProcessHeap(), 0, sequence);
1058 sequence_cnt = sequence_size = 0;
1061 #define ok_sequence( exp, contx, todo) \
1062 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
1065 static void ok_sequence_(const struct message *expected, const char *context, int todo,
1066 const char *file, int line)
1068 static const struct message end_of_sequence = { 0, 0, 0, 0 };
1069 const struct message *actual;
1072 add_message(&end_of_sequence);
1076 while (expected->message && actual->message)
1078 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
1080 if (expected->message == actual->message)
1082 if (expected->flags & wparam)
1084 if (expected->wParam != actual->wParam && todo)
1088 ok_( file, line) (FALSE,
1089 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1090 context, expected->message, expected->wParam, actual->wParam);
1094 ok_( file, line) (expected->wParam == actual->wParam,
1095 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1096 context, expected->message, expected->wParam, actual->wParam);
1098 if (expected->flags & lparam)
1099 ok_( file, line) (expected->lParam == actual->lParam,
1100 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
1101 context, expected->message, expected->lParam, actual->lParam);
1102 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
1103 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
1104 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
1105 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
1106 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
1107 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
1108 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
1109 "%s: the msg 0x%04x should have been %s\n",
1110 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
1111 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
1112 "%s: the msg 0x%04x was expected in %s\n",
1113 context, expected->message, (expected->flags & parent) ? "parent" : "child");
1114 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook),
1115 "%s: the msg 0x%04x should have been sent by a hook\n",
1116 context, expected->message);
1117 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
1118 "%s: the msg 0x%04x should have been sent by a winevent hook\n",
1119 context, expected->message);
1123 /* silently drop winevent messages if there is no support for them */
1124 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))
1130 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1131 context, expected->message, actual->message);
1138 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1139 context, expected->message, actual->message);
1145 /* skip all optional trailing messages */
1146 while (expected->message && ((expected->flags & optional) ||
1147 ((expected->flags & winevent_hook) && !hEvent_hook)))
1153 if (expected->message || actual->message) {
1155 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1156 context, expected->message, actual->message);
1162 if (expected->message || actual->message)
1163 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1164 context, expected->message, actual->message);
1166 if( todo && !failcount) /* succeeded yet marked todo */
1168 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
1174 /******************************** MDI test **********************************/
1176 /* CreateWindow for MDI frame window, initially visible */
1177 static const struct message WmCreateMDIframeSeq[] = {
1178 { HCBT_CREATEWND, hook },
1179 { WM_GETMINMAXINFO, sent },
1180 { WM_NCCREATE, sent },
1181 { WM_NCCALCSIZE, sent|wparam, 0 },
1182 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1183 { WM_CREATE, sent },
1184 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1185 { WM_SHOWWINDOW, sent|wparam, 1 },
1186 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1187 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1188 { HCBT_ACTIVATE, hook },
1189 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1190 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1191 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
1192 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* Win9x */
1193 { WM_ACTIVATEAPP, sent|wparam, 1 },
1194 { WM_NCACTIVATE, sent|wparam, 1 },
1195 { WM_ACTIVATE, sent|wparam, 1 },
1196 { HCBT_SETFOCUS, hook },
1197 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1198 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1199 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
1200 /* Win9x adds SWP_NOZORDER below */
1201 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
1206 /* DestroyWindow for MDI frame window, initially visible */
1207 static const struct message WmDestroyMDIframeSeq[] = {
1208 { HCBT_DESTROYWND, hook },
1209 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1210 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1211 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1212 { WM_NCACTIVATE, sent|wparam, 0 },
1213 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
1214 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
1215 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
1216 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1217 { WM_DESTROY, sent },
1218 { WM_NCDESTROY, sent },
1221 /* CreateWindow for MDI client window, initially visible */
1222 static const struct message WmCreateMDIclientSeq[] = {
1223 { HCBT_CREATEWND, hook },
1224 { WM_NCCREATE, sent },
1225 { WM_NCCALCSIZE, sent|wparam, 0 },
1226 { WM_CREATE, sent },
1227 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1230 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
1231 { WM_SHOWWINDOW, sent|wparam, 1 },
1232 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE },
1233 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1234 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1237 /* DestroyWindow for MDI client window, initially visible */
1238 static const struct message WmDestroyMDIclientSeq[] = {
1239 { HCBT_DESTROYWND, hook },
1240 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
1241 { WM_SHOWWINDOW, sent|wparam, 0 },
1242 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1243 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1244 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1245 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1246 { WM_DESTROY, sent },
1247 { WM_NCDESTROY, sent },
1250 /* CreateWindow for MDI child window, initially visible */
1251 static const struct message WmCreateMDIchildVisibleSeq[] = {
1252 { HCBT_CREATEWND, hook },
1253 { WM_NCCREATE, sent },
1254 { WM_NCCALCSIZE, sent|wparam, 0 },
1255 { WM_CREATE, sent },
1256 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1259 /* Win2k sends wparam set to
1260 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1261 * while Win9x doesn't bother to set child window id according to
1262 * CLIENTCREATESTRUCT.idFirstChild
1264 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1265 { WM_SHOWWINDOW, sent|wparam, 1 },
1266 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1267 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1268 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1269 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1270 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1271 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1272 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1274 /* Win9x: message sequence terminates here. */
1276 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1277 { HCBT_SETFOCUS, hook }, /* in MDI client */
1278 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1279 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1280 { WM_SETFOCUS, sent }, /* in MDI client */
1281 { HCBT_SETFOCUS, hook },
1282 { WM_KILLFOCUS, sent }, /* in MDI client */
1283 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1284 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1285 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1286 { WM_SETFOCUS, sent|defwinproc },
1287 { WM_MDIACTIVATE, sent|defwinproc },
1290 /* DestroyWindow for MDI child window, initially visible */
1291 static const struct message WmDestroyMDIchildVisibleSeq[] = {
1292 { HCBT_DESTROYWND, hook },
1293 /* Win2k sends wparam set to
1294 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1295 * while Win9x doesn't bother to set child window id according to
1296 * CLIENTCREATESTRUCT.idFirstChild
1298 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1299 { WM_SHOWWINDOW, sent|wparam, 0 },
1300 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1301 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1302 { WM_ERASEBKGND, sent|parent|optional },
1303 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1305 /* { WM_DESTROY, sent }
1306 * Win9x: message sequence terminates here.
1309 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1310 { WM_KILLFOCUS, sent },
1311 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1312 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1313 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1314 { WM_SETFOCUS, sent }, /* in MDI client */
1316 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1317 { WM_KILLFOCUS, sent }, /* in MDI client */
1318 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1319 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1320 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1321 { WM_SETFOCUS, sent }, /* in MDI client */
1323 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1325 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1326 { WM_KILLFOCUS, sent },
1327 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1328 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1329 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1330 { WM_SETFOCUS, sent }, /* in MDI client */
1332 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1333 { WM_KILLFOCUS, sent }, /* in MDI client */
1334 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1335 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1336 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1337 { WM_SETFOCUS, sent }, /* in MDI client */
1339 { WM_DESTROY, sent },
1341 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1342 { WM_KILLFOCUS, sent },
1343 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1344 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1345 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1346 { WM_SETFOCUS, sent }, /* in MDI client */
1348 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1349 { WM_KILLFOCUS, sent }, /* in MDI client */
1350 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1351 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1352 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1353 { WM_SETFOCUS, sent }, /* in MDI client */
1355 { WM_NCDESTROY, sent },
1358 /* CreateWindow for MDI child window, initially invisible */
1359 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1360 { HCBT_CREATEWND, hook },
1361 { WM_NCCREATE, sent },
1362 { WM_NCCALCSIZE, sent|wparam, 0 },
1363 { WM_CREATE, sent },
1364 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1367 /* Win2k sends wparam set to
1368 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1369 * while Win9x doesn't bother to set child window id according to
1370 * CLIENTCREATESTRUCT.idFirstChild
1372 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1375 /* DestroyWindow for MDI child window, initially invisible */
1376 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1377 { HCBT_DESTROYWND, hook },
1378 /* Win2k sends wparam set to
1379 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1380 * while Win9x doesn't bother to set child window id according to
1381 * CLIENTCREATESTRUCT.idFirstChild
1383 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1384 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1385 { WM_DESTROY, sent },
1386 { WM_NCDESTROY, sent },
1389 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1390 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1391 { HCBT_CREATEWND, hook },
1392 { WM_NCCREATE, sent },
1393 { WM_NCCALCSIZE, sent|wparam, 0 },
1394 { WM_CREATE, sent },
1395 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1398 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1399 { WM_GETMINMAXINFO, sent },
1400 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1401 { WM_NCCALCSIZE, sent|wparam, 1 },
1402 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1403 { WM_SIZE, sent|defwinproc },
1405 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1406 { WM_NCCALCSIZE, sent|wparam, 1 },
1407 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1408 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1409 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1410 /* Win2k sends wparam set to
1411 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1412 * while Win9x doesn't bother to set child window id according to
1413 * CLIENTCREATESTRUCT.idFirstChild
1415 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1416 { WM_SHOWWINDOW, sent|wparam, 1 },
1417 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1418 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1419 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1420 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1421 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1422 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1423 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1425 /* Win9x: message sequence terminates here. */
1427 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1428 { HCBT_SETFOCUS, hook }, /* in MDI client */
1429 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1430 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1431 { WM_SETFOCUS, sent }, /* in MDI client */
1432 { HCBT_SETFOCUS, hook },
1433 { WM_KILLFOCUS, sent }, /* in MDI client */
1434 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1435 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1436 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1437 { WM_SETFOCUS, sent|defwinproc },
1438 { WM_MDIACTIVATE, sent|defwinproc },
1440 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1441 { WM_NCCALCSIZE, sent|wparam, 1 },
1442 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1443 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1446 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1447 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
1448 /* restore the 1st MDI child */
1449 { WM_SETREDRAW, sent|wparam, 0 },
1450 { HCBT_MINMAX, hook },
1451 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1452 { WM_NCCALCSIZE, sent|wparam, 1 },
1453 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1454 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1455 { WM_SIZE, sent|defwinproc },
1457 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1458 { WM_NCCALCSIZE, sent|wparam, 1 },
1459 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1460 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1461 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1462 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
1463 /* create the 2nd MDI child */
1464 { HCBT_CREATEWND, hook },
1465 { WM_NCCREATE, sent },
1466 { WM_NCCALCSIZE, sent|wparam, 0 },
1467 { WM_CREATE, sent },
1468 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1471 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1472 { WM_GETMINMAXINFO, sent },
1473 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1474 { WM_NCCALCSIZE, sent|wparam, 1 },
1475 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1476 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1477 { WM_SIZE, sent|defwinproc },
1479 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1480 { WM_NCCALCSIZE, sent|wparam, 1 },
1481 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1482 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1483 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1484 /* Win2k sends wparam set to
1485 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1486 * while Win9x doesn't bother to set child window id according to
1487 * CLIENTCREATESTRUCT.idFirstChild
1489 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1490 { WM_SHOWWINDOW, sent|wparam, 1 },
1491 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1492 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1493 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1494 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1495 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1496 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1498 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1499 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1501 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1503 /* Win9x: message sequence terminates here. */
1505 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1506 { HCBT_SETFOCUS, hook },
1507 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
1508 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
1509 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1510 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1511 { WM_SETFOCUS, sent }, /* in MDI client */
1512 { HCBT_SETFOCUS, hook },
1513 { WM_KILLFOCUS, sent }, /* in MDI client */
1514 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1515 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1516 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1517 { WM_SETFOCUS, sent|defwinproc },
1519 { WM_MDIACTIVATE, sent|defwinproc },
1521 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1522 { WM_NCCALCSIZE, sent|wparam, 1 },
1523 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1524 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1527 /* WM_MDICREATE MDI child window, initially visible and maximized */
1528 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
1529 { WM_MDICREATE, sent },
1530 { HCBT_CREATEWND, hook },
1531 { WM_NCCREATE, sent },
1532 { WM_NCCALCSIZE, sent|wparam, 0 },
1533 { WM_CREATE, sent },
1534 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1537 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1538 { WM_GETMINMAXINFO, sent },
1539 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1540 { WM_NCCALCSIZE, sent|wparam, 1 },
1541 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1542 { WM_SIZE, sent|defwinproc },
1545 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1546 { WM_NCCALCSIZE, sent|wparam, 1 },
1547 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1548 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1549 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1551 /* Win2k sends wparam set to
1552 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1553 * while Win9x doesn't bother to set child window id according to
1554 * CLIENTCREATESTRUCT.idFirstChild
1556 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1557 { WM_SHOWWINDOW, sent|wparam, 1 },
1558 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1560 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1562 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1563 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1564 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1566 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1567 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1569 /* Win9x: message sequence terminates here. */
1571 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1572 { HCBT_SETFOCUS, hook }, /* in MDI client */
1573 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1574 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1575 { WM_SETFOCUS, sent }, /* in MDI client */
1576 { HCBT_SETFOCUS, hook },
1577 { WM_KILLFOCUS, sent }, /* in MDI client */
1578 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1579 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1580 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1581 { WM_SETFOCUS, sent|defwinproc },
1583 { WM_MDIACTIVATE, sent|defwinproc },
1586 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1587 { WM_NCCALCSIZE, sent|wparam, 1 },
1588 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1589 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1592 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1593 { WM_NCCALCSIZE, sent|wparam, 1 },
1594 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1595 { WM_MOVE, sent|defwinproc },
1596 { WM_SIZE, sent|defwinproc },
1599 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1600 { WM_NCCALCSIZE, sent|wparam, 1 },
1601 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1605 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1606 { WM_NCCALCSIZE, sent|wparam, 1 },
1607 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1608 { WM_SIZE, sent|defwinproc },
1610 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1611 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1612 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1616 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1617 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
1618 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
1619 { HCBT_SYSCOMMAND, hook },
1620 { WM_CLOSE, sent|defwinproc },
1621 { WM_MDIDESTROY, sent }, /* in MDI client */
1623 /* bring the 1st MDI child to top */
1624 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
1625 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
1627 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1629 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
1630 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1631 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1633 /* maximize the 1st MDI child */
1634 { HCBT_MINMAX, hook },
1635 { WM_GETMINMAXINFO, sent|defwinproc },
1636 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
1637 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1638 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
1639 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1640 { WM_SIZE, sent|defwinproc },
1642 /* restore the 2nd MDI child */
1643 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
1644 { HCBT_MINMAX, hook },
1645 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOZORDER|0x8000 },
1646 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1648 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1650 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1651 { WM_SIZE, sent|defwinproc },
1653 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1655 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
1657 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1658 { WM_NCCALCSIZE, sent|wparam, 1 },
1659 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1660 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1661 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1663 /* bring the 1st MDI child to top */
1664 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1665 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1666 { HCBT_SETFOCUS, hook },
1667 { WM_KILLFOCUS, sent|defwinproc },
1668 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
1669 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1670 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1671 { WM_SETFOCUS, sent }, /* in MDI client */
1672 { HCBT_SETFOCUS, hook },
1673 { WM_KILLFOCUS, sent }, /* in MDI client */
1674 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1675 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1676 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1677 { WM_SETFOCUS, sent|defwinproc },
1678 { WM_MDIACTIVATE, sent|defwinproc },
1679 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1681 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1682 { WM_SHOWWINDOW, sent|wparam, 1 },
1683 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1684 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1685 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1686 { WM_MDIREFRESHMENU, sent },
1688 { HCBT_DESTROYWND, hook },
1689 /* Win2k sends wparam set to
1690 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1691 * while Win9x doesn't bother to set child window id according to
1692 * CLIENTCREATESTRUCT.idFirstChild
1694 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1695 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
1696 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1697 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1698 { WM_ERASEBKGND, sent|parent|optional },
1699 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1701 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1702 { WM_DESTROY, sent|defwinproc },
1703 { WM_NCDESTROY, sent|defwinproc },
1706 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1707 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
1708 { WM_MDIDESTROY, sent }, /* in MDI client */
1709 { WM_SHOWWINDOW, sent|wparam, 0 },
1710 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1711 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1712 { WM_ERASEBKGND, sent|parent|optional },
1713 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1715 { HCBT_SETFOCUS, hook },
1716 { WM_KILLFOCUS, sent },
1717 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1718 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1719 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1720 { WM_SETFOCUS, sent }, /* in MDI client */
1721 { HCBT_SETFOCUS, hook },
1722 { WM_KILLFOCUS, sent }, /* in MDI client */
1723 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1724 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1725 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1726 { WM_SETFOCUS, sent },
1729 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1730 { WM_NCCALCSIZE, sent|wparam, 1 },
1731 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1732 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1735 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1736 { WM_NCCALCSIZE, sent|wparam, 1 },
1737 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1738 { WM_MOVE, sent|defwinproc },
1739 { WM_SIZE, sent|defwinproc },
1742 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1743 { WM_NCCALCSIZE, sent|wparam, 1 },
1744 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1748 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1749 { WM_NCCALCSIZE, sent|wparam, 1 },
1750 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1751 { WM_SIZE, sent|defwinproc },
1754 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1755 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1756 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1757 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1760 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1761 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1762 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1763 { WM_MOVE, sent|defwinproc },
1764 { WM_SIZE, sent|defwinproc },
1767 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1768 { WM_NCCALCSIZE, sent|wparam, 1 },
1769 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1773 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOZORDER },
1774 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1775 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1776 { WM_SIZE, sent|defwinproc },
1777 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1778 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1779 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1780 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1781 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1782 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1785 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1786 { WM_NCCALCSIZE, sent|wparam, 1 },
1787 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1788 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1790 { WM_NCACTIVATE, sent|wparam, 0 },
1791 { WM_MDIACTIVATE, sent },
1793 { HCBT_MINMAX, hook },
1794 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
1795 { WM_NCCALCSIZE, sent|wparam, 1 },
1797 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1799 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1800 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE|0x8000 },
1801 { WM_SIZE, sent|defwinproc },
1804 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1805 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1806 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1807 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1810 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1811 { WM_NCCALCSIZE, sent|wparam, 1 },
1812 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1813 { WM_MOVE, sent|defwinproc },
1814 { WM_SIZE, sent|defwinproc },
1817 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1818 { WM_NCCALCSIZE, sent|wparam, 1 },
1819 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1821 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1822 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1823 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1825 { HCBT_SETFOCUS, hook },
1826 { WM_KILLFOCUS, sent },
1827 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1828 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1829 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1830 { WM_SETFOCUS, sent }, /* in MDI client */
1832 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
1834 { HCBT_DESTROYWND, hook },
1835 /* Win2k sends wparam set to
1836 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1837 * while Win9x doesn't bother to set child window id according to
1838 * CLIENTCREATESTRUCT.idFirstChild
1840 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1842 { WM_SHOWWINDOW, sent|wparam, 0 },
1843 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1844 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1845 { WM_ERASEBKGND, sent|parent|optional },
1846 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1848 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1849 { WM_DESTROY, sent },
1850 { WM_NCDESTROY, sent },
1853 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1854 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
1855 { HCBT_MINMAX, hook },
1856 { WM_GETMINMAXINFO, sent },
1857 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1858 { WM_NCCALCSIZE, sent|wparam, 1 },
1859 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1860 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1862 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1863 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1864 { HCBT_SETFOCUS, hook },
1865 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1866 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1867 { WM_SETFOCUS, sent }, /* in MDI client */
1868 { HCBT_SETFOCUS, hook },
1869 { WM_KILLFOCUS, sent }, /* in MDI client */
1870 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1871 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1872 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1873 { WM_SETFOCUS, sent|defwinproc },
1874 { WM_MDIACTIVATE, sent|defwinproc },
1875 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1876 { WM_SIZE, sent|defwinproc },
1878 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1879 { WM_NCCALCSIZE, sent|wparam, 1 },
1880 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1881 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1882 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1885 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1886 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
1887 { HCBT_MINMAX, hook },
1888 { WM_GETMINMAXINFO, sent },
1889 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1890 { WM_NCCALCSIZE, sent|wparam, 1 },
1891 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1892 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1893 { WM_SIZE, sent|defwinproc },
1895 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1896 { WM_NCCALCSIZE, sent|wparam, 1 },
1897 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1898 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1899 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1902 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
1903 static const struct message WmRestoreMDIchildVisibleSeq[] = {
1904 { HCBT_MINMAX, hook },
1905 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1906 { WM_NCCALCSIZE, sent|wparam, 1 },
1907 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1908 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1909 { WM_SIZE, sent|defwinproc },
1911 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1912 { WM_NCCALCSIZE, sent|wparam, 1 },
1913 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1914 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1915 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1918 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1919 static const struct message WmRestoreMDIchildInisibleSeq[] = {
1920 { HCBT_MINMAX, hook },
1921 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1922 { WM_NCCALCSIZE, sent|wparam, 1 },
1923 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1924 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1925 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1926 { WM_SIZE, sent|defwinproc },
1928 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1929 { WM_NCCALCSIZE, sent|wparam, 1 },
1930 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1931 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1932 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1936 static HWND mdi_client;
1937 static WNDPROC old_mdi_client_proc;
1939 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1943 /* do not log painting messages */
1944 if (message != WM_PAINT &&
1945 message != WM_ERASEBKGND &&
1946 message != WM_NCPAINT &&
1947 message != WM_NCHITTEST &&
1948 message != WM_GETTEXT &&
1949 message != WM_MDIGETACTIVE)
1951 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1955 case WM_WINDOWPOSCHANGING:
1956 case WM_WINDOWPOSCHANGED:
1958 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1960 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1961 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1962 winpos->hwnd, winpos->hwndInsertAfter,
1963 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1965 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1966 * in the high word for internal purposes
1968 wParam = winpos->flags & 0xffff;
1973 msg.message = message;
1974 msg.flags = sent|wparam|lparam;
1975 msg.wParam = wParam;
1976 msg.lParam = lParam;
1980 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1983 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1985 static long defwndproc_counter = 0;
1989 /* do not log painting messages */
1990 if (message != WM_PAINT &&
1991 message != WM_ERASEBKGND &&
1992 message != WM_NCPAINT &&
1993 message != WM_NCHITTEST &&
1994 message != WM_GETTEXT)
1996 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2000 case WM_WINDOWPOSCHANGING:
2001 case WM_WINDOWPOSCHANGED:
2003 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2005 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2006 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2007 winpos->hwnd, winpos->hwndInsertAfter,
2008 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2010 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2011 * in the high word for internal purposes
2013 wParam = winpos->flags & 0xffff;
2017 case WM_MDIACTIVATE:
2019 HWND active, client = GetParent(hwnd);
2021 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
2023 if (hwnd == (HWND)lParam) /* if we are being activated */
2024 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
2026 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
2031 msg.message = message;
2032 msg.flags = sent|wparam|lparam;
2033 if (defwndproc_counter) msg.flags |= defwinproc;
2034 msg.wParam = wParam;
2035 msg.lParam = lParam;
2039 defwndproc_counter++;
2040 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
2041 defwndproc_counter--;
2046 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2048 static long defwndproc_counter = 0;
2052 /* do not log painting messages */
2053 if (message != WM_PAINT &&
2054 message != WM_ERASEBKGND &&
2055 message != WM_NCPAINT &&
2056 message != WM_NCHITTEST &&
2057 message != WM_GETTEXT)
2059 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2063 case WM_WINDOWPOSCHANGING:
2064 case WM_WINDOWPOSCHANGED:
2066 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2068 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2069 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2070 winpos->hwnd, winpos->hwndInsertAfter,
2071 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2073 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2074 * in the high word for internal purposes
2076 wParam = winpos->flags & 0xffff;
2081 msg.message = message;
2082 msg.flags = sent|wparam|lparam;
2083 if (defwndproc_counter) msg.flags |= defwinproc;
2084 msg.wParam = wParam;
2085 msg.lParam = lParam;
2089 defwndproc_counter++;
2090 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
2091 defwndproc_counter--;
2096 static BOOL mdi_RegisterWindowClasses(void)
2101 cls.lpfnWndProc = mdi_frame_wnd_proc;
2104 cls.hInstance = GetModuleHandleA(0);
2106 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
2107 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2108 cls.lpszMenuName = NULL;
2109 cls.lpszClassName = "MDI_frame_class";
2110 if (!RegisterClassA(&cls)) return FALSE;
2112 cls.lpfnWndProc = mdi_child_wnd_proc;
2113 cls.lpszClassName = "MDI_child_class";
2114 if (!RegisterClassA(&cls)) return FALSE;
2116 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
2117 old_mdi_client_proc = cls.lpfnWndProc;
2118 cls.hInstance = GetModuleHandleA(0);
2119 cls.lpfnWndProc = mdi_client_hook_proc;
2120 cls.lpszClassName = "MDI_client_class";
2121 if (!RegisterClassA(&cls)) assert(0);
2126 static void test_mdi_messages(void)
2128 MDICREATESTRUCTA mdi_cs;
2129 CLIENTCREATESTRUCT client_cs;
2130 HWND mdi_frame, mdi_child, mdi_child2, active_child;
2132 HMENU hMenu = CreateMenu();
2134 assert(mdi_RegisterWindowClasses());
2138 trace("creating MDI frame window\n");
2139 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
2140 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2141 WS_MAXIMIZEBOX | WS_VISIBLE,
2142 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2143 GetDesktopWindow(), hMenu,
2144 GetModuleHandleA(0), NULL);
2146 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
2148 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2149 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
2151 trace("creating MDI client window\n");
2152 client_cs.hWindowMenu = 0;
2153 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
2154 mdi_client = CreateWindowExA(0, "MDI_client_class",
2156 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
2158 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
2160 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
2162 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2163 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
2165 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2166 ok(!active_child, "wrong active MDI child %p\n", active_child);
2167 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2172 trace("creating invisible MDI child window\n");
2173 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2175 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2176 mdi_client, 0, GetModuleHandleA(0), NULL);
2180 ShowWindow(mdi_child, SW_SHOWNORMAL);
2181 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
2183 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2184 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2186 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2187 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2189 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2190 ok(!active_child, "wrong active MDI child %p\n", active_child);
2191 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2193 ShowWindow(mdi_child, SW_HIDE);
2194 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
2197 ShowWindow(mdi_child, SW_SHOW);
2198 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
2200 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2201 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2203 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2204 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2206 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2207 ok(!active_child, "wrong active MDI child %p\n", active_child);
2208 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2210 DestroyWindow(mdi_child);
2213 trace("creating visible MDI child window\n");
2214 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2215 WS_CHILD | WS_VISIBLE,
2216 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2217 mdi_client, 0, GetModuleHandleA(0), NULL);
2219 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", TRUE);
2221 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2222 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2224 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2225 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2227 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2228 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2229 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2232 DestroyWindow(mdi_child);
2233 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2235 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2236 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2238 /* Win2k: MDI client still returns a just destroyed child as active
2239 * Win9x: MDI client returns 0
2241 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2242 ok(active_child == mdi_child || /* win2k */
2243 !active_child, /* win9x */
2244 "wrong active MDI child %p\n", active_child);
2245 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2249 trace("creating invisible MDI child window\n");
2250 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2252 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2253 mdi_client, 0, GetModuleHandleA(0), NULL);
2255 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
2257 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
2258 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
2260 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2261 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2263 /* Win2k: MDI client still returns a just destroyed child as active
2264 * Win9x: MDI client returns mdi_child2
2266 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2267 ok(active_child == mdi_child || /* win2k */
2268 active_child == mdi_child2, /* win9x */
2269 "wrong active MDI child %p\n", active_child);
2270 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2273 ShowWindow(mdi_child2, SW_MAXIMIZE);
2274 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
2276 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2277 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2279 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2280 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2281 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2284 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2285 ok(GetFocus() == mdi_child2 || /* win2k */
2286 GetFocus() == 0, /* win9x */
2287 "wrong focus window %p\n", GetFocus());
2292 ShowWindow(mdi_child2, SW_HIDE);
2293 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2295 ShowWindow(mdi_child2, SW_RESTORE);
2296 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
2299 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2300 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2302 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2303 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2304 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2310 ShowWindow(mdi_child2, SW_HIDE);
2311 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2313 ShowWindow(mdi_child2, SW_SHOW);
2314 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
2316 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2317 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2319 ShowWindow(mdi_child2, SW_MAXIMIZE);
2320 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
2322 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2323 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2325 ShowWindow(mdi_child2, SW_RESTORE);
2326 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
2328 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2329 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2334 ShowWindow(mdi_child2, SW_HIDE);
2335 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2337 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2338 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2340 DestroyWindow(mdi_child2);
2341 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
2343 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2344 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2346 /* test for maximized MDI children */
2347 trace("creating maximized visible MDI child window 1\n");
2348 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2349 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2350 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2351 mdi_client, 0, GetModuleHandleA(0), NULL);
2353 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
2354 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2356 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2357 ok(GetFocus() == mdi_child || /* win2k */
2358 GetFocus() == 0, /* win9x */
2359 "wrong focus window %p\n", GetFocus());
2361 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2362 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2363 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2366 trace("creating maximized visible MDI child window 2\n");
2367 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2368 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2369 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2370 mdi_client, 0, GetModuleHandleA(0), NULL);
2372 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2373 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2374 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2376 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2377 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2379 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2380 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2381 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2384 trace("destroying maximized visible MDI child window 2\n");
2385 DestroyWindow(mdi_child2);
2386 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2388 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2390 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2391 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2393 /* Win2k: MDI client still returns a just destroyed child as active
2394 * Win9x: MDI client returns 0
2396 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2397 ok(active_child == mdi_child2 || /* win2k */
2398 !active_child, /* win9x */
2399 "wrong active MDI child %p\n", active_child);
2402 ShowWindow(mdi_child, SW_MAXIMIZE);
2403 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2406 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2407 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2409 trace("re-creating maximized visible MDI child window 2\n");
2410 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2411 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2412 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2413 mdi_client, 0, GetModuleHandleA(0), NULL);
2415 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2416 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2417 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2419 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2420 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2422 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2423 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2424 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2427 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
2428 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
2429 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
2431 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2432 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2433 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2435 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2436 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2437 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2440 DestroyWindow(mdi_child);
2441 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2443 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2444 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2446 /* Win2k: MDI client still returns a just destroyed child as active
2447 * Win9x: MDI client returns 0
2449 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2450 ok(active_child == mdi_child || /* win2k */
2451 !active_child, /* win9x */
2452 "wrong active MDI child %p\n", active_child);
2454 /* end of test for maximized MDI children */
2456 mdi_cs.szClass = "MDI_child_Class";
2457 mdi_cs.szTitle = "MDI child";
2458 mdi_cs.hOwner = GetModuleHandleA(0);
2461 mdi_cs.cx = CW_USEDEFAULT;
2462 mdi_cs.cy = CW_USEDEFAULT;
2463 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
2465 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
2466 ok(mdi_child != 0, "MDI child creation failed\n");
2467 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
2469 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
2471 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2472 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2474 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
2475 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2476 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2478 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2479 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2480 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2483 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
2484 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
2486 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
2487 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2488 ok(!active_child, "wrong active MDI child %p\n", active_child);
2493 DestroyWindow(mdi_client);
2494 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
2496 DestroyWindow(mdi_frame);
2497 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
2499 /************************* End of MDI test **********************************/
2501 static void test_WM_SETREDRAW(HWND hwnd)
2503 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
2507 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
2508 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
2510 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
2511 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
2514 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
2515 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
2517 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2518 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
2520 /* restore original WS_VISIBLE state */
2521 SetWindowLongA(hwnd, GWL_STYLE, style);
2526 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2530 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2534 case WM_WINDOWPOSCHANGING:
2535 case WM_WINDOWPOSCHANGED:
2537 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2539 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2540 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2541 winpos->hwnd, winpos->hwndInsertAfter,
2542 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2544 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2545 * in the high word for internal purposes
2547 wParam = winpos->flags & 0xffff;
2552 msg.message = message;
2553 msg.flags = sent|wparam|lparam;
2554 msg.wParam = wParam;
2555 msg.lParam = lParam;
2558 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2559 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2563 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2565 DWORD style, exstyle;
2569 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2570 style = GetWindowLongA(hwnd, GWL_STYLE);
2571 /* do not be confused by WS_DLGFRAME set */
2572 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2574 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2575 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2577 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2578 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2579 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2580 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
2582 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2584 style = GetWindowLongA(hwnd, GWL_STYLE);
2585 if (set) ok(style & set, "style %08lx should be set\n", set);
2586 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2588 /* a subsequent call should do nothing */
2589 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2590 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2591 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2595 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2596 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax);
2597 ok( ret, "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
2598 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2599 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
2600 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
2603 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2605 DWORD style, exstyle;
2609 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2610 style = GetWindowLongA(hwnd, GWL_STYLE);
2611 /* do not be confused by WS_DLGFRAME set */
2612 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2614 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2615 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2617 si.cbSize = sizeof(si);
2618 si.fMask = SIF_RANGE;
2621 SetScrollInfo(hwnd, ctl, &si, TRUE);
2622 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2623 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
2625 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2627 style = GetWindowLongA(hwnd, GWL_STYLE);
2628 if (set) ok(style & set, "style %08lx should be set\n", set);
2629 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2631 /* a subsequent call should do nothing */
2632 SetScrollInfo(hwnd, ctl, &si, TRUE);
2633 if (style & WS_HSCROLL)
2634 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2635 else if (style & WS_VSCROLL)
2636 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2638 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2640 si.fMask = SIF_PAGE;
2642 SetScrollInfo(hwnd, ctl, &si, FALSE);
2643 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2647 SetScrollInfo(hwnd, ctl, &si, FALSE);
2648 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2650 si.fMask = SIF_RANGE;
2651 si.nMin = 0xdeadbeef;
2652 si.nMax = 0xdeadbeef;
2653 ret = GetScrollInfo(hwnd, ctl, &si);
2654 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2655 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2656 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
2657 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
2660 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2661 static void test_scroll_messages(HWND hwnd)
2669 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2670 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2671 if (sequence->message != WmGetScrollRangeSeq[0].message)
2672 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2673 /* values of min and max are undefined */
2676 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE);
2677 ok( ret, "SetScrollRange error %ld\n", GetLastError());
2678 if (sequence->message != WmSetScrollRangeSeq[0].message)
2679 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2684 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2685 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2686 if (sequence->message != WmGetScrollRangeSeq[0].message)
2687 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2688 /* values of min and max are undefined */
2691 si.cbSize = sizeof(si);
2692 si.fMask = SIF_RANGE;
2695 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2696 if (sequence->message != WmSetScrollRangeSeq[0].message)
2697 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2700 si.fMask = SIF_PAGE;
2702 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2703 if (sequence->message != WmSetScrollRangeSeq[0].message)
2704 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2709 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2710 if (sequence->message != WmSetScrollRangeSeq[0].message)
2711 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2714 si.fMask = SIF_RANGE;
2715 si.nMin = 0xdeadbeef;
2716 si.nMax = 0xdeadbeef;
2717 ret = GetScrollInfo(hwnd, SB_CTL, &si);
2718 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2719 if (sequence->message != WmGetScrollInfoSeq[0].message)
2720 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2721 /* values of min and max are undefined */
2724 /* set WS_HSCROLL */
2725 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2726 /* clear WS_HSCROLL */
2727 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2729 /* set WS_HSCROLL */
2730 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2731 /* clear WS_HSCROLL */
2732 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2734 /* set WS_VSCROLL */
2735 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2736 /* clear WS_VSCROLL */
2737 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2739 /* set WS_VSCROLL */
2740 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2741 /* clear WS_VSCROLL */
2742 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2745 static void test_showwindow(void)
2749 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2750 100, 100, 200, 200, 0, 0, 0, NULL);
2751 ok (hwnd != 0, "Failed to create overlapped window\n");
2752 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2753 0, 0, 10, 10, hwnd, 0, 0, NULL);
2754 ok (hchild != 0, "Failed to create child\n");
2757 /* ShowWindow( SW_SHOWNA) for invisible top level window */
2758 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
2759 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2760 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window.\n", TRUE);
2763 /* ShowWindow( SW_SHOWNA) for now visible top level window */
2764 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
2765 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2766 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window.\n", FALSE);
2768 /* back to invisible */
2769 ShowWindow(hchild, SW_HIDE);
2770 ShowWindow(hwnd, SW_HIDE);
2772 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
2773 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
2774 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2775 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent\n", TRUE);
2777 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
2778 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
2780 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
2781 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2782 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent\n", TRUE);
2784 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
2785 ShowWindow( hwnd, SW_SHOW);
2787 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
2788 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2789 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent\n", FALSE);
2792 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
2793 ShowWindow( hchild, SW_HIDE);
2795 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
2796 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2797 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent\n", FALSE);
2800 DestroyWindow(hchild);
2801 DestroyWindow(hwnd);
2805 /* test if we receive the right sequence of messages */
2806 static void test_messages(void)
2808 HWND hwnd, hparent, hchild;
2809 HWND hchild2, hbutton;
2815 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2816 100, 100, 200, 200, 0, 0, 0, NULL);
2817 ok (hwnd != 0, "Failed to create overlapped window\n");
2818 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2820 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2821 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
2822 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
2824 /* test WM_SETREDRAW on a not visible top level window */
2825 test_WM_SETREDRAW(hwnd);
2827 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2828 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
2829 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
2831 ok(GetActiveWindow() == hwnd, "window should be active\n");
2832 ok(GetFocus() == hwnd, "window should have input focus\n");
2833 ShowWindow(hwnd, SW_HIDE);
2834 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
2836 ShowWindow(hwnd, SW_SHOW);
2837 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
2839 ShowWindow(hwnd, SW_SHOW);
2840 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
2842 ok(GetActiveWindow() == hwnd, "window should be active\n");
2843 ok(GetFocus() == hwnd, "window should have input focus\n");
2844 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2845 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
2846 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
2848 /* test WM_SETREDRAW on a visible top level window */
2849 ShowWindow(hwnd, SW_SHOW);
2850 test_WM_SETREDRAW(hwnd);
2852 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
2853 test_scroll_messages(hwnd);
2855 /* test resizing and moving */
2856 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
2857 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE );
2858 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE );
2859 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE );
2861 /* popups don't get WM_GETMINMAXINFO */
2862 SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP );
2863 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED);
2865 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
2866 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
2868 DestroyWindow(hwnd);
2869 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
2871 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2872 100, 100, 200, 200, 0, 0, 0, NULL);
2873 ok (hparent != 0, "Failed to create parent window\n");
2876 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
2877 0, 0, 10, 10, hparent, 0, 0, NULL);
2878 ok (hchild != 0, "Failed to create child window\n");
2879 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
2880 DestroyWindow(hchild);
2883 /* visible child window with a caption */
2884 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
2885 WS_CHILD | WS_VISIBLE | WS_CAPTION,
2886 0, 0, 10, 10, hparent, 0, 0, NULL);
2887 ok (hchild != 0, "Failed to create child window\n");
2888 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
2890 trace("testing scroll APIs on a visible child window %p\n", hchild);
2891 test_scroll_messages(hchild);
2893 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2894 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
2896 DestroyWindow(hchild);
2899 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2900 0, 0, 10, 10, hparent, 0, 0, NULL);
2901 ok (hchild != 0, "Failed to create child window\n");
2902 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2904 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
2905 100, 100, 50, 50, hparent, 0, 0, NULL);
2906 ok (hchild2 != 0, "Failed to create child2 window\n");
2909 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
2910 0, 100, 50, 50, hchild, 0, 0, NULL);
2911 ok (hbutton != 0, "Failed to create button window\n");
2913 /* test WM_SETREDRAW on a not visible child window */
2914 test_WM_SETREDRAW(hchild);
2916 ShowWindow(hchild, SW_SHOW);
2917 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2919 ShowWindow(hchild, SW_HIDE);
2920 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
2922 ShowWindow(hchild, SW_SHOW);
2923 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2925 /* test WM_SETREDRAW on a visible child window */
2926 test_WM_SETREDRAW(hchild);
2928 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
2929 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
2931 ShowWindow(hchild, SW_HIDE);
2933 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2934 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
2936 ShowWindow(hchild, SW_HIDE);
2938 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2939 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
2941 /* DestroyWindow sequence below expects that a child has focus */
2945 DestroyWindow(hchild);
2946 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
2947 DestroyWindow(hchild2);
2948 DestroyWindow(hbutton);
2951 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
2952 0, 0, 100, 100, hparent, 0, 0, NULL);
2953 ok (hchild != 0, "Failed to create child popup window\n");
2954 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
2955 DestroyWindow(hchild);
2957 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
2959 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
2960 0, 0, 100, 100, hparent, 0, 0, NULL);
2961 ok (hchild != 0, "Failed to create popup window\n");
2962 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2963 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2964 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2966 ShowWindow(hchild, SW_SHOW);
2967 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2969 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2970 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2972 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2973 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
2974 DestroyWindow(hchild);
2976 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2977 * changes nothing in message sequences.
2980 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
2981 0, 0, 100, 100, hparent, 0, 0, NULL);
2982 ok (hchild != 0, "Failed to create popup window\n");
2983 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2984 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2985 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2987 ShowWindow(hchild, SW_SHOW);
2988 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2990 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2991 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2992 DestroyWindow(hchild);
2995 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
2996 0, 0, 100, 100, hparent, 0, 0, NULL);
2997 ok(hwnd != 0, "Failed to create custom dialog window\n");
2998 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
3001 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
3002 test_scroll_messages(hwnd);
3006 after_end_dialog = 1;
3007 EndDialog( hwnd, 0 );
3008 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
3010 DestroyWindow(hwnd);
3011 after_end_dialog = 0;
3013 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP,
3014 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
3015 ok(hwnd != 0, "Failed to create custom dialog window\n");
3017 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
3018 ShowWindow(hwnd, SW_SHOW);
3019 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
3020 DestroyWindow(hwnd);
3023 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
3024 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
3026 /* test showing child with hidden parent */
3027 ShowWindow( hparent, SW_HIDE );
3030 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
3031 0, 0, 10, 10, hparent, 0, 0, NULL);
3032 ok (hchild != 0, "Failed to create child window\n");
3033 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
3035 ShowWindow( hchild, SW_SHOW );
3036 ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", TRUE);
3037 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3038 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3040 ShowWindow( hchild, SW_HIDE );
3041 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", TRUE);
3042 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
3043 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3045 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3046 ok_sequence(WmShowChildInvisibleParentSeq_2, "SetWindowPos:show child with invisible parent", FALSE);
3047 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3048 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3050 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3051 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE);
3052 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
3053 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3055 DestroyWindow(hchild);
3056 DestroyWindow(hparent);
3059 /* Message sequence for SetMenu */
3060 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
3061 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
3063 hmenu = CreateMenu();
3064 ok (hmenu != 0, "Failed to create menu\n");
3065 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
3066 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3067 100, 100, 200, 200, 0, hmenu, 0, NULL);
3068 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
3069 ok (SetMenu(hwnd, 0), "SetMenu\n");
3070 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
3071 ok (SetMenu(hwnd, 0), "SetMenu\n");
3072 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
3073 ShowWindow(hwnd, SW_SHOW);
3075 ok (SetMenu(hwnd, 0), "SetMenu\n");
3076 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
3077 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
3078 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
3080 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
3081 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
3083 DestroyWindow(hwnd);
3086 /* Message sequence for EnableWindow */
3087 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3088 100, 100, 200, 200, 0, 0, 0, NULL);
3089 ok (hparent != 0, "Failed to create parent window\n");
3090 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
3091 0, 0, 10, 10, hparent, 0, 0, NULL);
3092 ok (hchild != 0, "Failed to create child window\n");
3097 EnableWindow(hparent, FALSE);
3098 ok_sequence(WmEnableWindowSeq, "EnableWindow", FALSE);
3100 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3103 /* the following test causes an exception in user.exe under win9x */
3104 if (!PostMessageW( hparent, WM_USER, 0, 0 )) return;
3105 PostMessageW( hparent, WM_USER+1, 0, 0 );
3106 /* PeekMessage(NULL) fails, but still removes the message */
3107 SetLastError(0xdeadbeef);
3108 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
3109 ok( GetLastError() == ERROR_NOACCESS, "last error is %ld\n", GetLastError() );
3110 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
3111 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
3113 DestroyWindow(hchild);
3114 DestroyWindow(hparent);
3120 /****************** button message test *************************/
3121 static const struct message WmSetFocusButtonSeq[] =
3123 { HCBT_SETFOCUS, hook },
3124 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3125 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3126 { WM_SETFOCUS, sent|wparam, 0 },
3127 { WM_CTLCOLORBTN, sent|defwinproc },
3130 static const struct message WmKillFocusButtonSeq[] =
3132 { HCBT_SETFOCUS, hook },
3133 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3134 { WM_KILLFOCUS, sent|wparam, 0 },
3135 { WM_CTLCOLORBTN, sent|defwinproc },
3136 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3139 static const struct message WmSetFocusStaticSeq[] =
3141 { HCBT_SETFOCUS, hook },
3142 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3143 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3144 { WM_SETFOCUS, sent|wparam, 0 },
3145 { WM_CTLCOLORSTATIC, sent|defwinproc },
3148 static const struct message WmKillFocusStaticSeq[] =
3150 { HCBT_SETFOCUS, hook },
3151 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3152 { WM_KILLFOCUS, sent|wparam, 0 },
3153 { WM_CTLCOLORSTATIC, sent|defwinproc },
3154 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3157 static const struct message WmLButtonDownSeq[] =
3159 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
3160 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
3161 { HCBT_SETFOCUS, hook },
3162 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
3163 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3164 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
3165 { WM_CTLCOLORBTN, sent|defwinproc },
3166 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
3167 { WM_CTLCOLORBTN, sent|defwinproc },
3168 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3171 static const struct message WmLButtonUpSeq[] =
3173 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
3174 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
3175 { WM_CTLCOLORBTN, sent|defwinproc },
3176 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3177 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
3178 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
3182 static WNDPROC old_button_proc;
3184 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3186 static long defwndproc_counter = 0;
3190 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3192 msg.message = message;
3193 msg.flags = sent|wparam|lparam;
3194 if (defwndproc_counter) msg.flags |= defwinproc;
3195 msg.wParam = wParam;
3196 msg.lParam = lParam;
3199 if (message == BM_SETSTATE)
3200 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
3202 defwndproc_counter++;
3203 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
3204 defwndproc_counter--;
3209 static void subclass_button(void)
3213 if (!GetClassInfoA(0, "button", &cls)) assert(0);
3215 old_button_proc = cls.lpfnWndProc;
3217 cls.hInstance = GetModuleHandle(0);
3218 cls.lpfnWndProc = button_hook_proc;
3219 cls.lpszClassName = "my_button_class";
3220 if (!RegisterClassA(&cls)) assert(0);
3223 static void test_button_messages(void)
3229 const struct message *setfocus;
3230 const struct message *killfocus;
3232 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3233 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3234 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
3235 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3236 { BS_CHECKBOX, DLGC_BUTTON,
3237 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3238 { BS_AUTOCHECKBOX, DLGC_BUTTON,
3239 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3240 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3241 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3242 { BS_3STATE, DLGC_BUTTON,
3243 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3244 { BS_AUTO3STATE, DLGC_BUTTON,
3245 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3246 { BS_GROUPBOX, DLGC_STATIC,
3247 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3248 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3249 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3250 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3251 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3252 { BS_OWNERDRAW, DLGC_BUTTON,
3253 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
3261 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
3263 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
3264 0, 0, 50, 14, 0, 0, 0, NULL);
3265 ok(hwnd != 0, "Failed to create button window\n");
3267 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
3268 ok(dlg_code == button[i].dlg_code, "%d: wrong dlg_code %08lx\n", i, dlg_code);
3270 ShowWindow(hwnd, SW_SHOW);
3275 trace("button style %08lx\n", button[i].style);
3277 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
3280 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
3282 DestroyWindow(hwnd);
3285 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
3286 0, 0, 50, 14, 0, 0, 0, NULL);
3287 ok(hwnd != 0, "Failed to create button window\n");
3292 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
3293 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
3295 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
3296 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONUP on a button", FALSE);
3297 DestroyWindow(hwnd);
3300 /************* painting message test ********************/
3302 static void dump_region(HRGN hrgn)
3305 RGNDATA *data = NULL;
3310 printf( "null region\n" );
3313 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
3314 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
3315 GetRegionData( hrgn, size, data );
3316 printf("%ld rects:", data->rdh.nCount );
3317 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
3318 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
3320 HeapFree( GetProcessHeap(), 0, data );
3323 static void check_update_rgn( HWND hwnd, HRGN hrgn )
3327 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
3328 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
3330 ret = GetUpdateRgn( hwnd, update, FALSE );
3331 ok( ret != ERROR, "GetUpdateRgn failed\n" );
3332 if (ret == NULLREGION)
3334 ok( !hrgn, "Update region shouldn't be empty\n" );
3338 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
3340 ok( 0, "Regions are different\n" );
3341 if (winetest_debug > 0)
3343 printf( "Update region: " );
3344 dump_region( update );
3345 printf( "Wanted region: " );
3346 dump_region( hrgn );
3350 GetRgnBox( update, &r1 );
3351 GetUpdateRect( hwnd, &r2, FALSE );
3352 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
3353 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
3354 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
3356 DeleteObject( tmp );
3357 DeleteObject( update );
3360 static const struct message WmInvalidateRgn[] = {
3361 { WM_NCPAINT, sent },
3362 { WM_GETTEXT, sent|defwinproc|optional },
3366 static const struct message WmGetUpdateRect[] = {
3367 { WM_NCPAINT, sent },
3368 { WM_GETTEXT, sent|defwinproc|optional },
3373 static const struct message WmInvalidateFull[] = {
3374 { WM_NCPAINT, sent|wparam, 1 },
3375 { WM_GETTEXT, sent|defwinproc|optional },
3379 static const struct message WmInvalidateErase[] = {
3380 { WM_NCPAINT, sent|wparam, 1 },
3381 { WM_GETTEXT, sent|defwinproc|optional },
3382 { WM_ERASEBKGND, sent },
3386 static const struct message WmInvalidatePaint[] = {
3388 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3389 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3393 static const struct message WmInvalidateErasePaint[] = {
3395 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3396 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3397 { WM_ERASEBKGND, sent|beginpaint },
3401 static const struct message WmInvalidateErasePaint2[] = {
3403 { WM_NCPAINT, sent|beginpaint },
3404 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3405 { WM_ERASEBKGND, sent|beginpaint },
3409 static const struct message WmErase[] = {
3410 { WM_ERASEBKGND, sent },
3414 static const struct message WmPaint[] = {
3419 static const struct message WmParentOnlyPaint[] = {
3420 { WM_PAINT, sent|parent },
3424 static const struct message WmInvalidateParent[] = {
3425 { WM_NCPAINT, sent|parent },
3426 { WM_GETTEXT, sent|defwinproc|parent|optional },
3427 { WM_ERASEBKGND, sent|parent },
3431 static const struct message WmInvalidateParentChild[] = {
3432 { WM_NCPAINT, sent|parent },
3433 { WM_GETTEXT, sent|defwinproc|parent|optional },
3434 { WM_ERASEBKGND, sent|parent },
3435 { WM_NCPAINT, sent },
3436 { WM_GETTEXT, sent|defwinproc|optional },
3437 { WM_ERASEBKGND, sent },
3441 static const struct message WmInvalidateParentChild2[] = {
3442 { WM_ERASEBKGND, sent|parent },
3443 { WM_NCPAINT, sent },
3444 { WM_GETTEXT, sent|defwinproc|optional },
3445 { WM_ERASEBKGND, sent },
3449 static const struct message WmParentPaint[] = {
3450 { WM_PAINT, sent|parent },
3455 static const struct message WmParentPaintNc[] = {
3456 { WM_PAINT, sent|parent },
3458 { WM_NCPAINT, sent|beginpaint },
3459 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3460 { WM_ERASEBKGND, sent|beginpaint },
3464 static const struct message WmChildPaintNc[] = {
3466 { WM_NCPAINT, sent|beginpaint },
3467 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3468 { WM_ERASEBKGND, sent|beginpaint },
3472 static const struct message WmParentErasePaint[] = {
3473 { WM_PAINT, sent|parent },
3474 { WM_NCPAINT, sent|parent|beginpaint },
3475 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3476 { WM_ERASEBKGND, sent|parent|beginpaint },
3478 { WM_NCPAINT, sent|beginpaint },
3479 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3480 { WM_ERASEBKGND, sent|beginpaint },
3484 static const struct message WmParentOnlyNcPaint[] = {
3485 { WM_PAINT, sent|parent },
3486 { WM_NCPAINT, sent|parent|beginpaint },
3487 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3491 static const struct message WmSetParentStyle[] = {
3492 { WM_STYLECHANGING, sent|parent },
3493 { WM_STYLECHANGED, sent|parent },
3497 static void test_paint_messages(void)
3502 HWND hparent, hchild;
3503 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
3504 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
3505 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3506 100, 100, 200, 200, 0, 0, 0, NULL);
3507 ok (hwnd != 0, "Failed to create overlapped window\n");
3509 ShowWindow( hwnd, SW_SHOW );
3510 UpdateWindow( hwnd );
3512 /* try to flush pending X expose events */
3513 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3514 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3516 check_update_rgn( hwnd, 0 );
3517 SetRectRgn( hrgn, 10, 10, 20, 20 );
3518 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3519 check_update_rgn( hwnd, hrgn );
3520 SetRectRgn( hrgn2, 20, 20, 30, 30 );
3521 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
3522 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
3523 check_update_rgn( hwnd, hrgn );
3524 /* validate everything */
3525 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3526 check_update_rgn( hwnd, 0 );
3527 /* now with frame */
3528 SetRectRgn( hrgn, -5, -5, 20, 20 );
3530 /* flush pending messages */
3531 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3534 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3535 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3537 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
3538 check_update_rgn( hwnd, hrgn );
3541 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3542 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3545 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3546 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
3548 GetClientRect( hwnd, &rect );
3549 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
3550 check_update_rgn( hwnd, hrgn );
3553 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
3554 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3557 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
3558 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
3559 check_update_rgn( hwnd, 0 );
3562 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
3563 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
3564 check_update_rgn( hwnd, 0 );
3567 SetRectRgn( hrgn, 0, 0, 100, 100 );
3568 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3569 SetRectRgn( hrgn, 0, 0, 50, 100 );
3570 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
3571 SetRectRgn( hrgn, 50, 0, 100, 100 );
3572 check_update_rgn( hwnd, hrgn );
3573 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3574 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
3575 check_update_rgn( hwnd, 0 );
3578 SetRectRgn( hrgn, 0, 0, 100, 100 );
3579 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3580 SetRectRgn( hrgn, 0, 0, 100, 50 );
3581 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3582 ok_sequence( WmErase, "Erase", FALSE );
3583 SetRectRgn( hrgn, 0, 50, 100, 100 );
3584 check_update_rgn( hwnd, hrgn );
3587 SetRectRgn( hrgn, 0, 0, 100, 100 );
3588 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3589 SetRectRgn( hrgn, 0, 0, 50, 50 );
3590 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
3591 ok_sequence( WmPaint, "Paint", FALSE );
3594 SetRectRgn( hrgn, -4, -4, -2, -2 );
3595 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3596 SetRectRgn( hrgn, -200, -200, -198, -198 );
3597 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
3598 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3601 SetRectRgn( hrgn, -4, -4, -2, -2 );
3602 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3603 SetRectRgn( hrgn, -4, -4, -3, -3 );
3604 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
3605 SetRectRgn( hrgn, 0, 0, 1, 1 );
3606 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
3607 ok_sequence( WmPaint, "Paint", FALSE );
3610 SetRectRgn( hrgn, -4, -4, -1, -1 );
3611 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3612 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
3613 /* make sure no WM_PAINT was generated */
3614 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3615 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3618 SetRectRgn( hrgn, -4, -4, -1, -1 );
3619 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3620 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
3622 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
3624 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
3625 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
3626 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
3627 ret = GetUpdateRect( hwnd, &rect, FALSE );
3628 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
3629 /* this will send WM_NCPAINT and validate the non client area */
3630 ret = GetUpdateRect( hwnd, &rect, TRUE );
3631 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
3633 DispatchMessage( &msg );
3635 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
3637 DestroyWindow( hwnd );
3639 /* now test with a child window */
3641 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
3642 100, 100, 200, 200, 0, 0, 0, NULL);
3643 ok (hparent != 0, "Failed to create parent window\n");
3645 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
3646 10, 10, 100, 100, hparent, 0, 0, NULL);
3647 ok (hchild != 0, "Failed to create child window\n");
3649 ShowWindow( hparent, SW_SHOW );
3650 UpdateWindow( hparent );
3651 UpdateWindow( hchild );
3652 /* try to flush pending X expose events */
3653 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3654 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3657 log_all_parent_messages++;
3659 SetRect( &rect, 0, 0, 50, 50 );
3660 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3661 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3662 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
3664 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3666 MapWindowPoints( hchild, hparent, &pt, 1 );
3667 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
3668 check_update_rgn( hchild, hrgn );
3669 SetRectRgn( hrgn, 0, 0, 50, 50 );
3670 check_update_rgn( hparent, hrgn );
3671 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3672 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
3673 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3674 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3676 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3677 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
3679 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3680 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3681 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
3682 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3683 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3685 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
3686 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3687 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
3689 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3691 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3692 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3693 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
3695 /* flush all paint messages */
3696 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3699 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
3700 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3701 SetRectRgn( hrgn, 0, 0, 50, 50 );
3702 check_update_rgn( hparent, hrgn );
3703 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3704 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3705 SetRectRgn( hrgn, 0, 0, 50, 50 );
3706 check_update_rgn( hparent, hrgn );
3708 /* flush all paint messages */
3709 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3710 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3713 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
3714 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3715 SetRectRgn( hrgn, 0, 0, 50, 50 );
3716 check_update_rgn( hparent, hrgn );
3717 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3718 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3719 SetRectRgn( hrgn2, 10, 10, 50, 50 );
3720 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
3721 check_update_rgn( hparent, hrgn );
3722 /* flush all paint messages */
3723 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3726 /* same as above but parent gets completely validated */
3727 SetRect( &rect, 20, 20, 30, 30 );
3728 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3729 SetRectRgn( hrgn, 20, 20, 30, 30 );
3730 check_update_rgn( hparent, hrgn );
3731 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3732 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3733 check_update_rgn( hparent, 0 ); /* no update region */
3734 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3735 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
3737 /* make sure RDW_VALIDATE on child doesn't have the same effect */
3739 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3740 SetRectRgn( hrgn, 20, 20, 30, 30 );
3741 check_update_rgn( hparent, hrgn );
3742 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
3743 SetRectRgn( hrgn, 20, 20, 30, 30 );
3744 check_update_rgn( hparent, hrgn );
3746 /* same as above but normal WM_PAINT doesn't validate parent */
3748 SetRect( &rect, 20, 20, 30, 30 );
3749 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3750 SetRectRgn( hrgn, 20, 20, 30, 30 );
3751 check_update_rgn( hparent, hrgn );
3752 /* no WM_PAINT in child while parent still pending */
3753 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3754 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3755 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3756 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
3759 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3760 /* no WM_PAINT in child while parent still pending */
3761 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3762 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3763 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
3764 /* now that parent is valid child should get WM_PAINT */
3765 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3766 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3767 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3768 ok_sequence( WmEmptySeq, "No other message", FALSE );
3770 /* same thing with WS_CLIPCHILDREN in parent */
3772 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3773 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3774 /* changing style invalidates non client area, but we need to invalidate something else to see it */
3775 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
3776 ok_sequence( WmEmptySeq, "No message", FALSE );
3777 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
3778 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
3781 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
3782 SetRectRgn( hrgn, 20, 20, 30, 30 );
3783 check_update_rgn( hparent, hrgn );
3784 /* no WM_PAINT in child while parent still pending */
3785 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3786 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3787 /* WM_PAINT in parent first */
3788 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3789 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
3791 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
3793 SetRect( &rect, 0, 0, 30, 30 );
3794 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
3795 SetRectRgn( hrgn, 0, 0, 30, 30 );
3796 check_update_rgn( hparent, hrgn );
3797 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3798 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
3800 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3802 SetRect( &rect, -10, 0, 30, 30 );
3803 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3804 SetRect( &rect, 0, 0, 20, 20 );
3805 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3806 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3807 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
3809 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3811 SetRect( &rect, -10, 0, 30, 30 );
3812 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3813 SetRect( &rect, 0, 0, 100, 100 );
3814 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3815 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3816 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
3817 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3818 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
3820 /* test RDW_INTERNALPAINT behavior */
3823 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
3824 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3825 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3827 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
3828 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3829 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3831 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3832 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3833 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3835 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3836 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3837 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3838 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3839 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3841 log_all_parent_messages--;
3842 DestroyWindow( hparent );
3844 DeleteObject( hrgn );
3845 DeleteObject( hrgn2 );
3854 static DWORD WINAPI thread_proc(void *param)
3857 struct wnd_event *wnd_event = (struct wnd_event *)param;
3859 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
3860 100, 100, 200, 200, 0, 0, 0, NULL);
3861 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
3863 SetEvent(wnd_event->event);
3865 while (GetMessage(&msg, 0, 0, 0))
3867 TranslateMessage(&msg);
3868 DispatchMessage(&msg);
3871 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
3876 static void test_interthread_messages(void)
3883 int len, expected_len;
3884 struct wnd_event wnd_event;
3887 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
3888 if (!wnd_event.event)
3890 trace("skipping interthread message test under win9x\n");
3894 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
3895 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
3897 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3899 CloseHandle(wnd_event.event);
3901 SetLastError(0xdeadbeef);
3902 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
3903 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
3905 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3906 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
3908 expected_len = lstrlenA("window caption text");
3909 memset(buf, 0, sizeof(buf));
3910 SetLastError(0xdeadbeef);
3911 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
3912 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
3913 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
3915 msg.hwnd = wnd_event.hwnd;
3916 msg.message = WM_GETTEXT;
3917 msg.wParam = sizeof(buf);
3918 msg.lParam = (LPARAM)buf;
3919 memset(buf, 0, sizeof(buf));
3920 SetLastError(0xdeadbeef);
3921 len = DispatchMessageA(&msg);
3922 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3923 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
3925 /* the following test causes an exception in user.exe under win9x */
3926 msg.hwnd = wnd_event.hwnd;
3927 msg.message = WM_TIMER;
3929 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3930 SetLastError(0xdeadbeef);
3931 len = DispatchMessageA(&msg);
3932 ok(!len && GetLastError() == 0xdeadbeef,
3933 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
3935 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
3936 ok( ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
3938 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3939 CloseHandle(hThread);
3941 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
3945 static const struct message WmVkN[] = {
3946 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3947 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3948 { WM_CHAR, wparam|lparam, 'n', 1 },
3949 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
3950 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3951 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3954 static const struct message WmShiftVkN[] = {
3955 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
3956 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
3957 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3958 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3959 { WM_CHAR, wparam|lparam, 'N', 1 },
3960 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
3961 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3962 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3963 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
3964 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
3967 static const struct message WmCtrlVkN[] = {
3968 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3969 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3970 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3971 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3972 { WM_CHAR, wparam|lparam, 0x000e, 1 },
3973 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3974 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3975 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3976 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3977 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3980 static const struct message WmCtrlVkN_2[] = {
3981 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3982 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3983 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3984 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3985 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3986 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3987 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3988 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3991 static const struct message WmAltVkN[] = {
3992 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3993 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3994 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3995 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3996 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
3997 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
3998 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
3999 { HCBT_SYSCOMMAND, hook },
4000 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4001 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4002 { WM_INITMENU, sent|defwinproc },
4003 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4004 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
4005 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
4006 { WM_CAPTURECHANGED, sent|defwinproc },
4007 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
4008 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4009 { WM_EXITMENULOOP, sent|defwinproc },
4010 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
4011 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
4012 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4013 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4014 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4015 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4018 static const struct message WmAltVkN_2[] = {
4019 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4020 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4021 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
4022 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
4023 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4024 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4025 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4026 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4029 static const struct message WmCtrlAltVkN[] = {
4030 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4031 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4032 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4033 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4034 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
4035 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
4036 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
4037 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4038 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4039 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4040 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4041 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4044 static const struct message WmAltPressRelease[] = {
4045 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4046 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4047 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4048 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4049 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 },
4050 { HCBT_SYSCOMMAND, hook },
4051 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4052 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4053 { WM_INITMENU, sent|defwinproc },
4054 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4055 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE) },
4056 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4058 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4059 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
4060 { WM_CAPTURECHANGED, sent|defwinproc },
4061 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) },
4062 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4063 { WM_EXITMENULOOP, sent|defwinproc },
4064 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4065 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4068 static const struct message WmAltMouseButton[] = {
4069 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4070 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4071 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
4072 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
4073 { WM_LBUTTONDOWN, wparam, MK_LBUTTON, 0 },
4074 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON, 0 },
4075 { WM_LBUTTONUP, wparam, 0, 0 },
4076 { WM_LBUTTONUP, sent|wparam, 0, 0 },
4077 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4078 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4082 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
4086 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
4088 struct message log_msg;
4090 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
4092 /* ignore some unwanted messages */
4093 if (msg.message == WM_MOUSEMOVE)
4096 log_msg.message = msg.message;
4097 log_msg.flags = wparam|lparam;
4098 log_msg.wParam = msg.wParam;
4099 log_msg.lParam = msg.lParam;
4100 add_message(&log_msg);
4102 if (!hAccel || !TranslateAccelerator(hwnd, hAccel, &msg))
4104 TranslateMessage(&msg);
4105 DispatchMessage(&msg);
4110 static void test_accelerators(void)
4115 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4116 100, 100, 200, 200, 0, 0, 0, NULL);
4122 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
4124 state = GetKeyState(VK_SHIFT);
4125 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
4126 state = GetKeyState(VK_CAPITAL);
4127 ok(state == 0, "wrong CapsLock state %04x\n", state);
4129 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
4130 assert(hAccel != 0);
4132 pump_msg_loop(hwnd, 0);
4135 trace("testing VK_N press/release\n");
4137 keybd_event('N', 0, 0, 0);
4138 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4139 pump_msg_loop(hwnd, hAccel);
4140 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4142 trace("testing Shift+VK_N press/release\n");
4144 keybd_event(VK_SHIFT, 0, 0, 0);
4145 keybd_event('N', 0, 0, 0);
4146 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4147 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4148 pump_msg_loop(hwnd, hAccel);
4149 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4151 trace("testing Ctrl+VK_N press/release\n");
4153 keybd_event(VK_CONTROL, 0, 0, 0);
4154 keybd_event('N', 0, 0, 0);
4155 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4156 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4157 pump_msg_loop(hwnd, hAccel);
4158 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
4160 trace("testing Alt+VK_N press/release\n");
4162 keybd_event(VK_MENU, 0, 0, 0);
4163 keybd_event('N', 0, 0, 0);
4164 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4165 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4166 pump_msg_loop(hwnd, hAccel);
4167 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
4169 trace("testing Ctrl+Alt+VK_N press/release\n");
4171 keybd_event(VK_CONTROL, 0, 0, 0);
4172 keybd_event(VK_MENU, 0, 0, 0);
4173 keybd_event('N', 0, 0, 0);
4174 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4175 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4176 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4177 pump_msg_loop(hwnd, hAccel);
4178 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
4180 ret = DestroyAcceleratorTable(hAccel);
4181 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4183 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
4184 assert(hAccel != 0);
4186 trace("testing VK_N press/release\n");
4188 keybd_event('N', 0, 0, 0);
4189 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4190 pump_msg_loop(hwnd, hAccel);
4191 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4193 trace("testing Shift+VK_N press/release\n");
4195 keybd_event(VK_SHIFT, 0, 0, 0);
4196 keybd_event('N', 0, 0, 0);
4197 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4198 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4199 pump_msg_loop(hwnd, hAccel);
4200 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4202 trace("testing Ctrl+VK_N press/release 2\n");
4204 keybd_event(VK_CONTROL, 0, 0, 0);
4205 keybd_event('N', 0, 0, 0);
4206 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4207 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4208 pump_msg_loop(hwnd, hAccel);
4209 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
4211 trace("testing Alt+VK_N press/release 2\n");
4213 keybd_event(VK_MENU, 0, 0, 0);
4214 keybd_event('N', 0, 0, 0);
4215 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4216 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4217 pump_msg_loop(hwnd, hAccel);
4218 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
4220 trace("testing Ctrl+Alt+VK_N press/release\n");
4222 keybd_event(VK_CONTROL, 0, 0, 0);
4223 keybd_event(VK_MENU, 0, 0, 0);
4224 keybd_event('N', 0, 0, 0);
4225 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4226 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4227 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4228 pump_msg_loop(hwnd, hAccel);
4229 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
4231 ret = DestroyAcceleratorTable(hAccel);
4232 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4234 trace("testing Alt press/release\n");
4236 keybd_event(VK_MENU, 0, 0, 0);
4237 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4238 keybd_event(VK_MENU, 0, 0, 0);
4239 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4240 pump_msg_loop(hwnd, 0);
4241 /* this test doesn't pass in Wine for managed windows */
4242 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
4244 trace("testing Alt+MouseButton press/release\n");
4245 /* first, move mouse pointer inside of the window client area */
4246 GetClientRect(hwnd, &rc);
4247 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
4248 rc.left += (rc.right - rc.left)/2;
4249 rc.top += (rc.bottom - rc.top)/2;
4250 SetCursorPos(rc.left, rc.top);
4252 pump_msg_loop(hwnd, 0);
4254 keybd_event(VK_MENU, 0, 0, 0);
4255 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
4256 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
4257 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4258 pump_msg_loop(hwnd, 0);
4259 ok_sequence(WmAltMouseButton, "Alt+MouseButton press/release", FALSE);
4261 DestroyWindow(hwnd);
4264 /************* window procedures ********************/
4266 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4268 static long defwndproc_counter = 0;
4269 static long beginpaint_counter = 0;
4273 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4277 /* test_accelerators() depends on this */
4286 case WM_WINDOWPOSCHANGING:
4287 case WM_WINDOWPOSCHANGED:
4289 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4291 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4292 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4293 winpos->hwnd, winpos->hwndInsertAfter,
4294 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4296 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4297 * in the high word for internal purposes
4299 wParam = winpos->flags & 0xffff;
4304 msg.message = message;
4305 msg.flags = sent|wparam|lparam;
4306 if (defwndproc_counter) msg.flags |= defwinproc;
4307 if (beginpaint_counter) msg.flags |= beginpaint;
4308 msg.wParam = wParam;
4309 msg.lParam = lParam;
4312 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
4314 HWND parent = GetParent(hwnd);
4316 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
4318 GetClientRect(parent, &rc);
4319 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
4321 trace("ptReserved = (%ld,%ld)\n"
4322 "ptMaxSize = (%ld,%ld)\n"
4323 "ptMaxPosition = (%ld,%ld)\n"
4324 "ptMinTrackSize = (%ld,%ld)\n"
4325 "ptMaxTrackSize = (%ld,%ld)\n",
4326 minmax->ptReserved.x, minmax->ptReserved.y,
4327 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
4328 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
4329 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
4330 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
4332 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
4333 minmax->ptMaxSize.x, rc.right);
4334 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
4335 minmax->ptMaxSize.y, rc.bottom);
4338 if (message == WM_PAINT)
4341 beginpaint_counter++;
4342 BeginPaint( hwnd, &ps );
4343 beginpaint_counter--;
4344 EndPaint( hwnd, &ps );
4348 defwndproc_counter++;
4349 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4350 defwndproc_counter--;
4355 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4357 static long defwndproc_counter = 0;
4361 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4363 msg.message = message;
4364 msg.flags = sent|wparam|lparam;
4365 if (defwndproc_counter) msg.flags |= defwinproc;
4366 msg.wParam = wParam;
4367 msg.lParam = lParam;
4370 if (message == WM_CREATE)
4372 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
4373 SetWindowLongA(hwnd, GWL_STYLE, style);
4376 defwndproc_counter++;
4377 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4378 defwndproc_counter--;
4383 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4385 static long defwndproc_counter = 0;
4386 static long beginpaint_counter = 0;
4390 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4392 if (log_all_parent_messages ||
4393 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
4394 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
4395 message == WM_ENABLE || message == WM_ENTERIDLE ||
4396 message == WM_IME_SETCONTEXT)
4398 msg.message = message;
4399 msg.flags = sent|parent|wparam|lparam;
4400 if (defwndproc_counter) msg.flags |= defwinproc;
4401 if (beginpaint_counter) msg.flags |= beginpaint;
4402 msg.wParam = wParam;
4403 msg.lParam = lParam;
4407 if (message == WM_PAINT)
4410 beginpaint_counter++;
4411 BeginPaint( hwnd, &ps );
4412 beginpaint_counter--;
4413 EndPaint( hwnd, &ps );
4417 defwndproc_counter++;
4418 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4419 defwndproc_counter--;
4424 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4426 static long defwndproc_counter = 0;
4430 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4432 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
4433 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4434 if (after_end_dialog)
4435 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
4437 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
4441 case WM_WINDOWPOSCHANGING:
4442 case WM_WINDOWPOSCHANGED:
4444 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4446 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4447 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4448 winpos->hwnd, winpos->hwndInsertAfter,
4449 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4451 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4452 * in the high word for internal purposes
4454 wParam = winpos->flags & 0xffff;
4459 msg.message = message;
4460 msg.flags = sent|wparam|lparam;
4461 if (defwndproc_counter) msg.flags |= defwinproc;
4462 msg.wParam = wParam;
4463 msg.lParam = lParam;
4466 defwndproc_counter++;
4467 ret = DefDlgProcA(hwnd, message, wParam, lParam);
4468 defwndproc_counter--;
4473 static BOOL RegisterWindowClasses(void)
4478 cls.lpfnWndProc = MsgCheckProcA;
4481 cls.hInstance = GetModuleHandleA(0);
4483 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
4484 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4485 cls.lpszMenuName = NULL;
4486 cls.lpszClassName = "TestWindowClass";
4487 if(!RegisterClassA(&cls)) return FALSE;
4489 cls.lpfnWndProc = PopupMsgCheckProcA;
4490 cls.lpszClassName = "TestPopupClass";
4491 if(!RegisterClassA(&cls)) return FALSE;
4493 cls.lpfnWndProc = ParentMsgCheckProcA;
4494 cls.lpszClassName = "TestParentClass";
4495 if(!RegisterClassA(&cls)) return FALSE;
4497 cls.lpfnWndProc = DefWindowProcA;
4498 cls.lpszClassName = "SimpleWindowClass";
4499 if(!RegisterClassA(&cls)) return FALSE;
4501 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
4503 cls.hInstance = GetModuleHandleA(0);
4504 cls.hbrBackground = 0;
4505 cls.lpfnWndProc = TestDlgProcA;
4506 cls.lpszClassName = "TestDialogClass";
4507 if(!RegisterClassA(&cls)) return FALSE;
4512 static HHOOK hCBT_hook;
4514 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
4518 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
4520 if (nCode == HCBT_SYSCOMMAND)
4524 msg.message = nCode;
4526 msg.wParam = wParam;
4527 msg.lParam = lParam;
4530 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
4533 /* Log also SetFocus(0) calls */
4534 if (!wParam) wParam = lParam;
4536 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
4538 if (!strcmp(buf, "TestWindowClass") ||
4539 !strcmp(buf, "TestParentClass") ||
4540 !strcmp(buf, "TestPopupClass") ||
4541 !strcmp(buf, "SimpleWindowClass") ||
4542 !strcmp(buf, "TestDialogClass") ||
4543 !strcmp(buf, "MDI_frame_class") ||
4544 !strcmp(buf, "MDI_client_class") ||
4545 !strcmp(buf, "MDI_child_class") ||
4546 !strcmp(buf, "my_button_class") ||
4547 !strcmp(buf, "#32770"))
4551 msg.message = nCode;
4552 msg.flags = hook|wparam|lparam;
4553 msg.wParam = wParam;
4554 msg.lParam = lParam;
4558 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
4561 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
4571 trace("WEH:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
4572 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
4574 /* ignore mouse cursor events */
4575 if (object_id == OBJID_CURSOR) return;
4577 if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf)))
4580 !strcmp(buf, "TestWindowClass") ||
4581 !strcmp(buf, "TestParentClass") ||
4582 !strcmp(buf, "TestPopupClass") ||
4583 !strcmp(buf, "SimpleWindowClass") ||
4584 !strcmp(buf, "TestDialogClass") ||
4585 !strcmp(buf, "MDI_frame_class") ||
4586 !strcmp(buf, "MDI_client_class") ||
4587 !strcmp(buf, "MDI_child_class") ||
4588 !strcmp(buf, "my_button_class") ||
4589 !strcmp(buf, "#32770"))
4593 msg.message = event;
4594 msg.flags = winevent_hook|wparam|lparam;
4595 msg.wParam = object_id;
4596 msg.lParam = child_id;
4602 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
4603 static const WCHAR wszAnsi[] = {'U',0};
4605 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4609 case CB_FINDSTRINGEXACT:
4610 trace("String: %p\n", (LPCWSTR)lParam);
4611 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
4613 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
4617 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
4620 static void test_message_conversion(void)
4622 static const WCHAR wszMsgConversionClass[] =
4623 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
4630 cls.lpfnWndProc = MsgConversionProcW;
4633 cls.hInstance = GetModuleHandleW(NULL);
4635 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
4636 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
4637 cls.lpszMenuName = NULL;
4638 cls.lpszClassName = wszMsgConversionClass;
4639 /* this call will fail on Win9x, but that doesn't matter as this test is
4640 * meaningless on those platforms */
4641 if(!RegisterClassW(&cls)) return;
4643 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
4644 100, 100, 200, 200, 0, 0, 0, NULL);
4645 ok(hwnd != NULL, "Window creation failed\n");
4649 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
4650 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4651 ok(lRes == 0, "String should have been converted\n");
4652 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4653 ok(lRes == 1, "String shouldn't have been converted\n");
4657 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
4658 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4659 ok(lRes == 1, "String shouldn't have been converted\n");
4660 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4661 ok(lRes == 1, "String shouldn't have been converted\n");
4663 /* Synchronous messages */
4665 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4666 ok(lRes == 0, "String should have been converted\n");
4667 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4668 ok(lRes == 1, "String shouldn't have been converted\n");
4670 /* Asynchronous messages */
4673 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4674 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4675 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4677 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4678 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4679 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4681 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4682 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4683 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4685 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4686 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4687 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4689 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4690 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4691 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4693 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4694 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4695 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4697 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4698 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4699 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4701 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4702 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4703 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4706 typedef struct _thread_info
4713 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
4717 #define TIMER_ID 0x19
4719 static DWORD WINAPI timer_thread_proc(LPVOID x)
4721 thread_info *info = x;
4724 r = KillTimer(info->hWnd, 0x19);
4725 ok(r,"KillTimer failed in thread\n");
4726 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
4727 ok(r,"SetTimer failed in thread\n");
4728 ok(r==TIMER_ID,"SetTimer id different\n");
4729 r = SetEvent(info->handles[0]);
4730 ok(r,"SetEvent failed in thread\n");
4734 static void test_timers(void)
4739 info.hWnd = CreateWindow ("TestWindowClass", NULL,
4740 WS_OVERLAPPEDWINDOW ,
4741 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4744 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
4745 ok(info.id, "SetTimer failed\n");
4746 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
4747 info.handles[0] = CreateEvent(NULL,0,0,NULL);
4748 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
4750 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
4752 WaitForSingleObject(info.handles[1], INFINITE);
4754 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
4756 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
4759 /* Various win events with arbitrary parameters */
4760 static const struct message WmWinEventsSeq[] = {
4761 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
4762 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4763 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
4764 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
4765 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
4766 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
4767 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
4768 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
4769 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
4770 /* our win event hook ignores OBJID_CURSOR events */
4771 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
4772 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
4773 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
4774 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
4775 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
4776 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
4777 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4778 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
4779 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
4780 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
4781 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
4782 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
4783 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
4784 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
4788 static void test_winevents(void)
4792 const struct message *events = WmWinEventsSeq;
4793 HMODULE user32 = GetModuleHandleA("user32.dll");
4794 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
4796 if (!pNotifyWinEvent) return;
4798 hwnd = CreateWindow ("TestWindowClass", NULL,
4799 WS_OVERLAPPEDWINDOW,
4800 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4806 /* Windows ignores events with hwnd == 0 */
4807 SetLastError(0xdeadbeef);
4808 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
4809 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
4810 GetLastError() == 0xdeadbeef, /* Win9x */
4811 "unexpected error %ld\n", GetLastError());
4812 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
4814 for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
4815 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
4817 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
4818 ok(DestroyWindow(hwnd), "failed to destroy window\n");
4823 HMODULE user32 = GetModuleHandleA("user32.dll");
4824 FARPROC pSetWinEventHook = 0;/*GetProcAddress(user32, "SetWinEventHook");*/
4825 FARPROC pUnhookWinEvent = 0;/*GetProcAddress(user32, "UnhookWinEvent");*/
4826 FARPROC pIsWinEventHookInstalled = GetProcAddress(user32, "IsWinEventHookInstalled");
4828 if (!RegisterWindowClasses()) assert(0);
4830 if (pSetWinEventHook)
4833 hEvent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
4834 GetModuleHandleA(0),
4836 GetCurrentProcessId(),
4838 WINEVENT_INCONTEXT);
4839 assert(hEvent_hook);
4841 if (pIsWinEventHookInstalled)
4843 for (event = EVENT_MIN; event <= EVENT_MAX; event++)
4844 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
4848 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
4852 test_mdi_messages();
4853 test_button_messages();
4854 test_paint_messages();
4855 test_interthread_messages();
4856 test_message_conversion();
4857 test_accelerators();
4861 UnhookWindowsHookEx(hCBT_hook);
4862 if (pUnhookWinEvent)
4864 ok(pUnhookWinEvent(hEvent_hook), "UnhookWinEvent error %ld\n", GetLastError());
4865 SetLastError(0xdeadbeef);
4866 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n");
4867 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
4868 GetLastError() == 0xdeadbeef, /* Win9x */
4869 "unexpected error %ld\n", GetLastError());