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 #define WND_PARENT_ID 1
43 #define WND_POPUP_ID 2
44 #define WND_CHILD_ID 3
46 static BOOL test_DestroyWindow_flag;
47 static HWINEVENTHOOK hEvent_hook;
49 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
52 FIXME: add tests for these
53 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
54 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
55 WS_THICKFRAME: thick border
56 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
57 WS_BORDER (default for overlapped windows): single black border
58 none (default for child (and popup?) windows): no border
75 UINT message; /* the WM_* code */
76 msg_flags_t flags; /* message props */
77 WPARAM wParam; /* expected value of wParam */
78 LPARAM lParam; /* expected value of lParam */
81 /* Empty message sequence */
82 static const struct message WmEmptySeq[] =
86 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
87 static const struct message WmCreateOverlappedSeq[] = {
88 { HCBT_CREATEWND, hook },
89 { WM_GETMINMAXINFO, sent },
90 { WM_NCCREATE, sent },
91 { WM_NCCALCSIZE, sent|wparam, 0 },
92 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
94 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
97 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
98 * for a not visible overlapped window.
100 static const struct message WmSWP_ShowOverlappedSeq[] = {
101 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
102 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
103 { WM_NCPAINT, sent|wparam|optional, 1 },
104 { WM_GETTEXT, sent|defwinproc|optional },
105 { WM_ERASEBKGND, sent|optional },
106 { HCBT_ACTIVATE, hook },
107 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
108 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
109 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
110 { WM_ACTIVATEAPP, sent|wparam, 1 },
111 { WM_NCACTIVATE, sent|wparam, 1 },
112 { WM_GETTEXT, sent|defwinproc|optional },
113 { WM_ACTIVATE, sent|wparam, 1 },
114 { HCBT_SETFOCUS, hook },
115 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
116 { WM_IME_NOTIFY, sent|defwinproc|optional },
117 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
118 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
119 { WM_NCPAINT, sent|wparam|optional, 1 },
120 { WM_GETTEXT, sent|defwinproc|optional },
121 { WM_ERASEBKGND, sent|optional },
122 /* Win9x adds SWP_NOZORDER below */
123 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
124 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
125 { WM_NCPAINT, sent|wparam|optional, 1 },
126 { WM_ERASEBKGND, sent|optional },
129 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
130 * for a visible overlapped window.
132 static const struct message WmSWP_HideOverlappedSeq[] = {
133 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
134 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
135 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
139 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
140 * for a visible overlapped window.
142 static const struct message WmSWP_ResizeSeq[] = {
143 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE },
144 { WM_GETMINMAXINFO, sent|defwinproc },
145 { WM_NCCALCSIZE, sent|wparam, TRUE },
146 { WM_NCPAINT, sent|optional },
147 { WM_GETTEXT, sent|defwinproc|optional },
148 { WM_ERASEBKGND, sent|optional },
149 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
150 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
151 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
152 { WM_NCPAINT, sent|optional },
153 { WM_GETTEXT, sent|defwinproc|optional },
154 { WM_ERASEBKGND, sent|optional },
155 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
159 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
160 * for a visible popup window.
162 static const struct message WmSWP_ResizePopupSeq[] = {
163 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE },
164 { WM_NCCALCSIZE, sent|wparam, TRUE },
165 { WM_NCPAINT, sent|optional },
166 { WM_GETTEXT, sent|defwinproc|optional },
167 { WM_ERASEBKGND, sent|optional },
168 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
169 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
170 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
171 { WM_NCPAINT, sent|optional },
172 { WM_GETTEXT, sent|defwinproc|optional },
173 { WM_ERASEBKGND, sent|optional },
174 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
178 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
179 * for a visible overlapped window.
181 static const struct message WmSWP_MoveSeq[] = {
182 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE },
183 { WM_NCPAINT, sent|optional },
184 { WM_GETTEXT, sent|defwinproc|optional },
185 { WM_ERASEBKGND, sent|optional },
186 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE },
187 { WM_MOVE, sent|defwinproc|wparam, 0 },
188 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
192 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
193 static const struct message WmShowOverlappedSeq[] = {
194 { WM_SHOWWINDOW, sent|wparam, 1 },
195 { WM_NCPAINT, sent|wparam|optional, 1 },
196 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
197 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
198 { WM_NCPAINT, sent|wparam|optional, 1 },
199 { WM_GETTEXT, sent|defwinproc|optional },
200 { WM_ERASEBKGND, sent|optional },
201 { HCBT_ACTIVATE, hook },
202 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
203 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
204 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
205 { WM_ACTIVATEAPP, sent|wparam, 1 },
206 { WM_NCACTIVATE, sent|wparam, 1 },
207 { WM_GETTEXT, sent|defwinproc|optional },
208 { WM_ACTIVATE, sent|wparam, 1 },
209 { HCBT_SETFOCUS, hook },
210 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
211 { WM_IME_NOTIFY, sent|defwinproc|optional },
212 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
213 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
214 { WM_NCPAINT, sent|wparam|optional, 1 },
215 { WM_GETTEXT, sent|defwinproc|optional },
216 { WM_ERASEBKGND, sent|optional },
217 /* Win9x adds SWP_NOZORDER below */
218 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
219 { WM_NCCALCSIZE, sent|optional },
220 { WM_NCPAINT, sent|optional },
221 { WM_ERASEBKGND, sent|optional },
222 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
223 * messages. Does that mean that CreateWindow doesn't set initial
224 * window dimensions for overlapped windows?
231 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
232 static const struct message WmShowMaxOverlappedSeq[] = {
233 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
234 { WM_GETMINMAXINFO, sent },
235 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
236 { WM_GETMINMAXINFO, sent|defwinproc },
237 { WM_NCCALCSIZE, sent|wparam, TRUE },
238 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
239 { HCBT_ACTIVATE, hook },
240 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
241 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
242 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
243 { WM_ACTIVATEAPP, sent|wparam, 1 },
244 { WM_NCACTIVATE, sent|wparam, 1 },
245 { WM_GETICON, sent|optional },
246 { WM_GETICON, sent|optional },
247 { WM_GETICON, sent|optional },
248 { WM_GETTEXT, sent|defwinproc|optional },
249 { WM_ACTIVATE, sent|wparam, 1 },
250 { HCBT_SETFOCUS, hook },
251 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
252 { WM_IME_NOTIFY, sent|defwinproc|optional },
253 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
254 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
255 { WM_NCPAINT, sent|wparam|optional, 1 },
256 { WM_GETTEXT, sent|defwinproc|optional },
257 { WM_ERASEBKGND, sent|optional },
258 /* Win9x adds SWP_NOZORDER below */
259 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
260 { WM_MOVE, sent|defwinproc },
261 { WM_SIZE, sent|defwinproc },
262 { WM_NCCALCSIZE, sent|optional },
263 { WM_NCPAINT, sent|optional },
264 { WM_ERASEBKGND, sent|optional },
265 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
266 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
269 /* ShowWindow(SW_HIDE) for a visible overlapped window */
270 static const struct message WmHideOverlappedSeq[] = {
271 { WM_SHOWWINDOW, sent|wparam, 0 },
272 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
273 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
274 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
277 { WM_NCACTIVATE, sent|wparam, 0 },
278 { WM_ACTIVATE, sent|wparam, 0 },
279 { WM_ACTIVATEAPP, sent|wparam, 0 },
280 { WM_KILLFOCUS, sent|wparam, 0 },
281 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
282 { WM_IME_NOTIFY, sent|optional|defwinproc },
285 /* DestroyWindow for a visible overlapped window */
286 static const struct message WmDestroyOverlappedSeq[] = {
287 { HCBT_DESTROYWND, hook },
288 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
289 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
290 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
291 { WM_NCACTIVATE, sent|wparam, 0 },
292 { WM_ACTIVATE, sent|wparam, 0 },
293 { WM_ACTIVATEAPP, sent|wparam, 0 },
294 { WM_KILLFOCUS, sent|wparam, 0 },
295 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
296 { WM_IME_NOTIFY, sent|optional|defwinproc },
297 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
298 { WM_DESTROY, sent },
299 { WM_NCDESTROY, sent },
302 /* CreateWindow (for a child popup window, not initially visible) */
303 static const struct message WmCreateChildPopupSeq[] = {
304 { HCBT_CREATEWND, hook },
305 { WM_NCCREATE, sent },
306 { WM_NCCALCSIZE, sent|wparam, 0 },
308 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
313 /* CreateWindow (for a popup window, not initially visible,
314 * which sets WS_VISIBLE in WM_CREATE handler)
316 static const struct message WmCreateInvisiblePopupSeq[] = {
317 { HCBT_CREATEWND, hook },
318 { WM_NCCREATE, sent },
319 { WM_NCCALCSIZE, sent|wparam, 0 },
321 { WM_STYLECHANGING, sent },
322 { WM_STYLECHANGED, sent },
323 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
328 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
329 * for a popup window with WS_VISIBLE style set
331 static const struct message WmShowVisiblePopupSeq_2[] = {
332 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
335 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
336 * for a popup window with WS_VISIBLE style set
338 static const struct message WmShowVisiblePopupSeq_3[] = {
339 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
340 { HCBT_ACTIVATE, hook },
341 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
342 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
343 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
344 { WM_NCACTIVATE, sent|wparam, 1 },
345 { WM_ACTIVATE, sent|wparam, 1 },
346 { HCBT_SETFOCUS, hook },
347 { WM_KILLFOCUS, sent|parent },
348 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
349 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
350 { WM_IME_NOTIFY, sent|defwinproc|optional },
351 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
352 { WM_SETFOCUS, sent|defwinproc },
355 /* CreateWindow (for child window, not initially visible) */
356 static const struct message WmCreateChildSeq[] = {
357 { HCBT_CREATEWND, hook },
358 { WM_NCCREATE, sent },
359 /* child is inserted into parent's child list after WM_NCCREATE returns */
360 { WM_NCCALCSIZE, sent|wparam, 0 },
362 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
365 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
368 /* CreateWindow (for maximized child window, not initially visible) */
369 static const struct message WmCreateMaximizedChildSeq[] = {
370 { HCBT_CREATEWND, hook },
371 { WM_NCCREATE, sent },
372 { WM_NCCALCSIZE, sent|wparam, 0 },
374 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
377 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
378 { WM_GETMINMAXINFO, sent },
379 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
380 { WM_NCCALCSIZE, sent|wparam, 1 },
381 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 },
382 { WM_SIZE, sent|defwinproc },
383 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
384 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
387 /* CreateWindow (for a child window, initially visible) */
388 static const struct message WmCreateVisibleChildSeq[] = {
389 { HCBT_CREATEWND, hook },
390 { WM_NCCREATE, sent },
391 /* child is inserted into parent's child list after WM_NCCREATE returns */
392 { WM_NCCALCSIZE, sent|wparam, 0 },
393 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
395 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
398 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
399 { WM_SHOWWINDOW, sent|wparam, 1 },
400 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
401 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
402 { WM_ERASEBKGND, sent|parent|optional },
403 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
404 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */
407 /* ShowWindow(SW_SHOW) for a not visible child window */
408 static const struct message WmShowChildSeq[] = {
409 { WM_SHOWWINDOW, sent|wparam, 1 },
410 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
411 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
412 { WM_ERASEBKGND, sent|parent|optional },
413 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
416 /* ShowWindow(SW_HIDE) for a visible child window */
417 static const struct message WmHideChildSeq[] = {
418 { WM_SHOWWINDOW, sent|wparam, 0 },
419 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
420 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
421 { WM_ERASEBKGND, sent|parent|optional },
422 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
425 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
426 * for a not visible child window
428 static const struct message WmShowChildSeq_2[] = {
429 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
430 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
431 { WM_CHILDACTIVATE, sent },
432 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
435 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
436 * for a not visible child window
438 static const struct message WmShowChildSeq_3[] = {
439 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
440 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
441 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
444 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
445 * for a visible child window with a caption
447 static const struct message WmShowChildSeq_4[] = {
448 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
449 { WM_CHILDACTIVATE, sent },
452 /* ShowWindow(SW_SHOW) for child with invisible parent */
453 static const struct message WmShowChildInvisibleParentSeq[] = {
454 { WM_SHOWWINDOW, sent|wparam, 1 },
457 /* ShowWindow(SW_HIDE) for child with invisible parent */
458 static const struct message WmHideChildInvisibleParentSeq[] = {
459 { WM_SHOWWINDOW, sent|wparam, 0 },
462 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
463 static const struct message WmShowChildInvisibleParentSeq_2[] = {
464 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
465 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
466 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
469 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
470 static const struct message WmHideChildInvisibleParentSeq_2[] = {
471 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
472 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
473 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
476 /* DestroyWindow for a visible child window */
477 static const struct message WmDestroyChildSeq[] = {
478 { HCBT_DESTROYWND, hook },
479 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
480 { WM_SHOWWINDOW, sent|wparam, 0 },
481 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
482 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
483 { WM_ERASEBKGND, sent|parent|optional },
484 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
485 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
486 { WM_KILLFOCUS, sent },
487 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
488 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
489 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
490 { WM_SETFOCUS, sent|parent },
491 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
492 { WM_DESTROY, sent },
493 { WM_DESTROY, sent|optional }, /* some other (IME?) window */
494 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */
495 { WM_NCDESTROY, sent },
498 /* Moving the mouse in nonclient area */
499 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
500 { WM_NCHITTEST, sent },
501 { WM_SETCURSOR, sent },
502 { WM_NCMOUSEMOVE, posted },
505 /* Moving the mouse in client area */
506 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
507 { WM_NCHITTEST, sent },
508 { WM_SETCURSOR, sent },
509 { WM_MOUSEMOVE, posted },
512 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
513 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
514 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
515 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
516 { WM_GETMINMAXINFO, sent|defwinproc },
517 { WM_ENTERSIZEMOVE, sent|defwinproc },
518 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
519 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
520 { WM_MOVE, sent|defwinproc },
521 { WM_EXITSIZEMOVE, sent|defwinproc },
524 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
525 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
526 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
527 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
528 { WM_GETMINMAXINFO, sent|defwinproc },
529 { WM_ENTERSIZEMOVE, sent|defwinproc },
530 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
531 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
532 { WM_GETMINMAXINFO, sent|defwinproc },
533 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
534 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
535 { WM_GETTEXT, sent|defwinproc },
536 { WM_ERASEBKGND, sent|defwinproc },
537 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
538 { WM_MOVE, sent|defwinproc },
539 { WM_SIZE, sent|defwinproc },
540 { WM_EXITSIZEMOVE, sent|defwinproc },
543 /* Resizing child window with MoveWindow (32) */
544 static const struct message WmResizingChildWithMoveWindowSeq[] = {
545 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
546 { WM_NCCALCSIZE, sent|wparam, 1 },
547 { WM_ERASEBKGND, sent|optional },
548 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
549 { WM_MOVE, sent|defwinproc },
550 { WM_SIZE, sent|defwinproc },
551 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
554 /* Clicking on inactive button */
555 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
556 { WM_NCHITTEST, sent },
557 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
558 { WM_MOUSEACTIVATE, sent },
559 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
560 { WM_SETCURSOR, sent },
561 { WM_SETCURSOR, sent|parent|defwinproc },
562 { WM_LBUTTONDOWN, posted },
563 { WM_KILLFOCUS, posted|parent },
564 { WM_SETFOCUS, posted },
565 { WM_CTLCOLORBTN, posted|parent },
566 { BM_SETSTATE, posted },
567 { WM_CTLCOLORBTN, posted|parent },
568 { WM_LBUTTONUP, posted },
569 { BM_SETSTATE, posted },
570 { WM_CTLCOLORBTN, posted|parent },
571 { WM_COMMAND, posted|parent },
574 /* Reparenting a button (16/32) */
575 /* The last child (button) reparented gets topmost for its new parent. */
576 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
577 { WM_SHOWWINDOW, sent|wparam, 0 },
578 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
579 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
580 { WM_ERASEBKGND, sent|parent },
581 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
582 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
583 { WM_CHILDACTIVATE, sent },
584 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
585 { WM_MOVE, sent|defwinproc },
586 { WM_SHOWWINDOW, sent|wparam, 1 },
589 /* Creation of a custom dialog (32) */
590 static const struct message WmCreateCustomDialogSeq[] = {
591 { HCBT_CREATEWND, hook },
592 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
593 { WM_GETMINMAXINFO, sent },
594 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
595 { WM_NCCREATE, sent },
596 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
597 { WM_NCCALCSIZE, sent|wparam, 0 },
598 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
599 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
601 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
602 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
603 { WM_SHOWWINDOW, sent|wparam, 1 },
604 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
605 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
606 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
607 { HCBT_ACTIVATE, hook },
608 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
610 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
612 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
613 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
615 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
617 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
618 { WM_NCACTIVATE, sent|wparam, 1 },
619 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
620 { WM_GETTEXT, sent|optional|defwinproc },
621 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
622 { WM_GETICON, sent|optional|defwinproc },
623 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
624 { WM_GETICON, sent|optional|defwinproc },
625 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
626 { WM_GETICON, sent|optional|defwinproc },
627 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
628 { WM_GETTEXT, sent|optional|defwinproc },
629 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
630 { WM_ACTIVATE, sent|wparam, 1 },
631 { WM_KILLFOCUS, sent|parent },
632 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
633 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
634 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
635 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
636 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
637 { WM_IME_NOTIFY, sent|optional|defwinproc },
638 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
639 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
640 { WM_SETFOCUS, sent },
641 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
642 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
643 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
644 { WM_NCPAINT, sent|wparam, 1 },
645 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
646 { WM_GETTEXT, sent|optional|defwinproc },
647 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
648 { WM_GETICON, sent|optional|defwinproc },
649 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
650 { WM_GETICON, sent|optional|defwinproc },
651 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
652 { WM_GETICON, sent|optional|defwinproc },
653 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
654 { WM_GETTEXT, sent|optional|defwinproc },
655 { WM_ERASEBKGND, sent },
656 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
657 { WM_CTLCOLORDLG, sent|defwinproc },
658 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
659 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
660 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
661 { WM_GETTEXT, sent|optional },
662 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
663 { WM_GETICON, sent|optional },
664 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
665 { WM_GETICON, sent|optional },
666 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
667 { WM_GETICON, sent|optional },
668 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
669 { WM_GETTEXT, sent|optional },
670 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
671 { WM_NCCALCSIZE, sent|optional },
672 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
673 { WM_NCPAINT, sent|optional },
674 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
675 { WM_GETTEXT, sent|optional|defwinproc },
676 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
677 { WM_GETICON, sent|optional|defwinproc },
678 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
679 { WM_GETICON, sent|optional|defwinproc },
680 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
681 { WM_GETICON, sent|optional|defwinproc },
682 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
683 { WM_GETTEXT, sent|optional|defwinproc },
684 { WM_ERASEBKGND, sent|optional },
685 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
686 { WM_CTLCOLORDLG, sent|optional|defwinproc },
688 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
692 /* Calling EndDialog for a custom dialog (32) */
693 static const struct message WmEndCustomDialogSeq[] = {
694 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
695 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
696 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
697 { WM_GETTEXT, sent|optional },
698 { WM_GETICON, sent|optional },
699 { WM_GETICON, sent|optional },
700 { WM_GETICON, sent|optional },
701 { HCBT_ACTIVATE, hook },
702 { WM_NCACTIVATE, sent|wparam, 0 },
703 { WM_GETTEXT, sent|optional|defwinproc },
704 { WM_GETICON, sent|optional|defwinproc },
705 { WM_GETICON, sent|optional|defwinproc },
706 { WM_GETICON, sent|optional|defwinproc },
707 { WM_GETTEXT, sent|optional|defwinproc },
708 { WM_ACTIVATE, sent|wparam, 0 },
709 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
710 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
711 { HCBT_SETFOCUS, hook },
712 { WM_KILLFOCUS, sent },
713 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
714 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
715 { WM_IME_NOTIFY, sent|optional },
716 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
717 { WM_SETFOCUS, sent|parent|defwinproc },
720 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
721 static const struct message WmShowCustomDialogSeq[] = {
722 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
723 { WM_SHOWWINDOW, sent|wparam, 1 },
724 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
725 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
726 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
727 { HCBT_ACTIVATE, hook },
728 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
730 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
731 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
733 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
734 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
735 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
736 { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
737 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
738 { WM_NCACTIVATE, sent|wparam, 1 },
739 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
740 { WM_ACTIVATE, sent|wparam, 1 },
742 { WM_KILLFOCUS, sent|parent },
743 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
744 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
745 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
746 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
747 { WM_IME_NOTIFY, sent|optional|defwinproc },
748 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
749 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
750 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
751 { WM_SETFOCUS, sent },
752 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
753 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
754 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
755 { WM_NCPAINT, sent|wparam, 1 },
756 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
757 { WM_ERASEBKGND, sent },
758 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
759 { WM_CTLCOLORDLG, sent|defwinproc },
761 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
762 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
765 /* Creation and destruction of a modal dialog (32) */
766 static const struct message WmModalDialogSeq[] = {
767 { WM_CANCELMODE, sent|parent },
768 { HCBT_SETFOCUS, hook },
769 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
770 { WM_KILLFOCUS, sent|parent },
771 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
772 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
773 { WM_ENABLE, sent|parent|wparam, 0 },
774 { HCBT_CREATEWND, hook },
775 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
776 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
777 { WM_SETFONT, sent },
778 { WM_INITDIALOG, sent },
779 { WM_CHANGEUISTATE, sent|optional },
780 { WM_SHOWWINDOW, sent },
781 { HCBT_ACTIVATE, hook },
782 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
783 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
784 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
785 { WM_NCACTIVATE, sent|wparam, 1 },
786 { WM_GETICON, sent|optional },
787 { WM_GETICON, sent|optional },
788 { WM_GETICON, sent|optional },
789 { WM_GETTEXT, sent|optional },
790 { WM_ACTIVATE, sent|wparam, 1 },
791 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
792 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
793 { WM_NCPAINT, sent },
794 { WM_GETICON, sent|optional },
795 { WM_GETICON, sent|optional },
796 { WM_GETICON, sent|optional },
797 { WM_GETTEXT, sent|optional },
798 { WM_ERASEBKGND, sent },
799 { WM_CTLCOLORDLG, sent },
800 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
801 { WM_GETICON, sent|optional },
802 { WM_GETICON, sent|optional },
803 { WM_GETICON, sent|optional },
804 { WM_GETTEXT, sent|optional },
805 { WM_NCCALCSIZE, sent|optional },
806 { WM_NCPAINT, sent|optional },
807 { WM_GETICON, sent|optional },
808 { WM_GETICON, sent|optional },
809 { WM_GETICON, sent|optional },
810 { WM_GETTEXT, sent|optional },
811 { WM_ERASEBKGND, sent|optional },
812 { WM_CTLCOLORDLG, sent|optional },
813 { WM_PAINT, sent|optional },
814 { WM_CTLCOLORBTN, sent },
815 { WM_ENTERIDLE, sent|parent|optional },
816 { WM_ENTERIDLE, sent|parent|optional },
817 { WM_ENTERIDLE, sent|parent|optional },
818 { WM_ENTERIDLE, sent|parent|optional },
819 { WM_ENTERIDLE, sent|parent|optional },
820 { WM_ENTERIDLE, sent|parent|optional },
821 { WM_ENTERIDLE, sent|parent|optional },
822 { WM_ENTERIDLE, sent|parent|optional },
823 { WM_ENTERIDLE, sent|parent|optional },
824 { WM_ENTERIDLE, sent|parent|optional },
825 { WM_ENTERIDLE, sent|parent|optional },
826 { WM_ENTERIDLE, sent|parent|optional },
827 { WM_ENTERIDLE, sent|parent|optional },
828 { WM_ENTERIDLE, sent|parent|optional },
829 { WM_ENTERIDLE, sent|parent|optional },
830 { WM_ENTERIDLE, sent|parent|optional },
831 { WM_ENTERIDLE, sent|parent|optional },
832 { WM_ENTERIDLE, sent|parent|optional },
833 { WM_ENTERIDLE, sent|parent|optional },
834 { WM_ENTERIDLE, sent|parent|optional },
835 { WM_GETICON, sent|parent|optional },
836 { WM_GETICON, sent|parent|optional },
837 { WM_GETICON, sent|parent|optional },
839 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
840 { WM_ENABLE, sent|parent|wparam, 1 },
841 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
842 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
843 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
844 { WM_GETICON, sent|optional },
845 { WM_GETICON, sent|optional },
846 { WM_GETICON, sent|optional },
847 { WM_GETTEXT, sent|optional },
848 { HCBT_ACTIVATE, hook },
849 { WM_NCACTIVATE, sent|wparam, 0 },
850 { WM_GETICON, sent|optional },
851 { WM_GETICON, sent|optional },
852 { WM_GETICON, sent|optional },
853 { WM_GETTEXT, sent|optional },
854 { WM_ACTIVATE, sent|wparam, 0 },
855 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
856 { WM_WINDOWPOSCHANGING, sent|optional },
857 { HCBT_SETFOCUS, hook },
858 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
859 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
860 { WM_SETFOCUS, sent|parent|defwinproc },
861 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
862 { HCBT_DESTROYWND, hook },
863 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
864 { WM_DESTROY, sent },
865 { WM_NCDESTROY, sent },
868 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
869 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
870 /* (inside dialog proc, handling WM_INITDIALOG) */
871 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
872 { WM_NCCALCSIZE, sent },
873 { WM_NCACTIVATE, sent|parent|wparam, 0 },
874 { WM_GETTEXT, sent|defwinproc },
875 { WM_ACTIVATE, sent|parent|wparam, 0 },
876 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
877 { WM_WINDOWPOSCHANGING, sent|parent },
878 { WM_NCACTIVATE, sent|wparam, 1 },
879 { WM_ACTIVATE, sent|wparam, 1 },
880 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
881 { WM_SIZE, sent|defwinproc },
882 /* (setting focus) */
883 { WM_SHOWWINDOW, sent|wparam, 1 },
884 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
885 { WM_NCPAINT, sent },
886 { WM_GETTEXT, sent|defwinproc },
887 { WM_ERASEBKGND, sent },
888 { WM_CTLCOLORDLG, sent|defwinproc },
889 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
891 /* (bunch of WM_CTLCOLOR* for each control) */
892 { WM_PAINT, sent|parent },
893 { WM_ENTERIDLE, sent|parent|wparam, 0 },
894 { WM_SETCURSOR, sent|parent },
897 /* SetMenu for NonVisible windows with size change*/
898 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
899 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
900 { WM_NCCALCSIZE, sent|wparam, 1 },
901 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
902 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW },
903 { WM_MOVE, sent|defwinproc },
904 { WM_SIZE, sent|defwinproc },
905 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
906 { WM_GETICON, sent|optional },
907 { WM_GETICON, sent|optional },
908 { WM_GETICON, sent|optional },
909 { WM_GETTEXT, sent|optional },
910 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
913 /* SetMenu for NonVisible windows with no size change */
914 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
915 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
916 { WM_NCCALCSIZE, sent|wparam, 1 },
917 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
918 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
921 /* SetMenu for Visible windows with size change */
922 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
923 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
924 { WM_NCCALCSIZE, sent|wparam, 1 },
925 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
926 { WM_NCPAINT, sent|wparam, 1 },
927 { WM_GETTEXT, sent|defwinproc|optional },
928 { WM_ERASEBKGND, sent|optional },
929 { WM_ACTIVATE, sent|optional },
930 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
931 { WM_MOVE, sent|defwinproc },
932 { WM_SIZE, sent|defwinproc },
933 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
934 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
935 { WM_NCPAINT, sent|wparam|optional, 1 },
936 { WM_ERASEBKGND, sent|optional },
939 /* SetMenu for Visible windows with no size change */
940 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
941 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
942 { WM_NCCALCSIZE, sent|wparam, 1 },
943 { WM_NCPAINT, sent|wparam, 1 },
944 { WM_GETTEXT, sent|defwinproc|optional },
945 { WM_ERASEBKGND, sent|optional },
946 { WM_ACTIVATE, sent|optional },
947 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
948 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
951 /* DrawMenuBar for a visible window */
952 static const struct message WmDrawMenuBarSeq[] =
954 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
955 { WM_NCCALCSIZE, sent|wparam, 1 },
956 { WM_NCPAINT, sent|wparam, 1 },
957 { WM_GETTEXT, sent|defwinproc|optional },
958 { WM_ERASEBKGND, sent|optional },
959 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
960 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
964 static const struct message WmSetRedrawFalseSeq[] =
966 { WM_SETREDRAW, sent|wparam, 0 },
970 static const struct message WmSetRedrawTrueSeq[] =
972 { WM_SETREDRAW, sent|wparam, 1 },
976 static const struct message WmEnableWindowSeq_1[] =
978 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 },
979 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
980 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 },
984 static const struct message WmEnableWindowSeq_2[] =
986 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
987 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 },
991 static const struct message WmGetScrollRangeSeq[] =
993 { SBM_GETRANGE, sent },
996 static const struct message WmGetScrollInfoSeq[] =
998 { SBM_GETSCROLLINFO, sent },
1001 static const struct message WmSetScrollRangeSeq[] =
1003 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1004 sends SBM_SETSCROLLINFO.
1006 { SBM_SETSCROLLINFO, sent },
1009 /* SetScrollRange for a window without a non-client area */
1010 static const struct message WmSetScrollRangeHSeq_empty[] =
1012 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 },
1015 static const struct message WmSetScrollRangeVSeq_empty[] =
1017 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 },
1020 static const struct message WmSetScrollRangeHVSeq[] =
1022 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
1023 { WM_NCCALCSIZE, sent|wparam, 1 },
1024 { WM_GETTEXT, sent|defwinproc|optional },
1025 { WM_ERASEBKGND, sent|optional },
1026 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1027 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1030 /* SetScrollRange for a window with a non-client area */
1031 static const struct message WmSetScrollRangeHV_NC_Seq[] =
1033 { WM_WINDOWPOSCHANGING, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
1034 { WM_NCCALCSIZE, sent|wparam, 1 },
1035 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1036 { WM_NCPAINT, sent|optional },
1037 { WM_GETTEXT, sent|defwinproc|optional },
1038 { WM_GETICON, sent|optional|defwinproc },
1039 { WM_GETICON, sent|optional|defwinproc },
1040 { WM_GETICON, sent|optional|defwinproc },
1041 { WM_GETTEXT, sent|defwinproc|optional },
1042 { WM_ERASEBKGND, sent|optional },
1043 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
1044 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
1045 { WM_SIZE, sent|defwinproc },
1046 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1047 { WM_GETTEXT, sent|optional },
1048 { WM_GETICON, sent|optional },
1049 { WM_GETICON, sent|optional },
1050 { WM_GETICON, sent|optional },
1051 { WM_GETTEXT, sent|optional },
1052 { WM_GETICON, sent|optional },
1053 { WM_GETICON, sent|optional },
1054 { WM_GETICON, sent|optional },
1055 { WM_GETTEXT, sent|optional },
1056 { WM_GETICON, sent|optional },
1057 { WM_GETICON, sent|optional },
1058 { WM_GETICON, sent|optional },
1059 { WM_GETTEXT, sent|optional },
1062 /* test if we receive the right sequence of messages */
1063 /* after calling ShowWindow( SW_SHOWNA) */
1064 static const struct message WmSHOWNAChildInvisParInvis[] = {
1065 { WM_SHOWWINDOW, sent|wparam, 1 },
1068 static const struct message WmSHOWNAChildVisParInvis[] = {
1069 { WM_SHOWWINDOW, sent|wparam, 1 },
1072 static const struct message WmSHOWNAChildVisParVis[] = {
1073 { WM_SHOWWINDOW, sent|wparam, 1 },
1074 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
1077 static const struct message WmSHOWNAChildInvisParVis[] = {
1078 { WM_SHOWWINDOW, sent|wparam, 1 },
1079 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER},
1080 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1081 { WM_ERASEBKGND, sent|optional },
1082 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1085 static const struct message WmSHOWNATopVisible[] = {
1086 { WM_SHOWWINDOW, sent|wparam, 1 },
1087 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
1090 static const struct message WmSHOWNATopInvisible[] = {
1091 { WM_SHOWWINDOW, sent|wparam, 1 },
1092 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1093 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1094 { WM_NCPAINT, sent|wparam, 1 },
1095 { WM_GETICON, sent|optional },
1096 { WM_GETICON, sent|optional },
1097 { WM_GETICON, sent|optional },
1098 { WM_GETTEXT, sent|defwinproc|optional },
1099 { WM_ERASEBKGND, sent|optional },
1100 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1101 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
1102 { WM_NCPAINT, sent|wparam|optional, 1 },
1103 { WM_ERASEBKGND, sent|optional },
1109 static int after_end_dialog;
1110 static int sequence_cnt, sequence_size;
1111 static struct message* sequence;
1112 static int log_all_parent_messages;
1114 static void add_message(const struct message *msg)
1119 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
1121 if (sequence_cnt == sequence_size)
1124 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
1128 sequence[sequence_cnt].message = msg->message;
1129 sequence[sequence_cnt].flags = msg->flags;
1130 sequence[sequence_cnt].wParam = msg->wParam;
1131 sequence[sequence_cnt].lParam = msg->lParam;
1136 static void flush_sequence(void)
1138 HeapFree(GetProcessHeap(), 0, sequence);
1140 sequence_cnt = sequence_size = 0;
1143 #define ok_sequence( exp, contx, todo) \
1144 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
1147 static void ok_sequence_(const struct message *expected, const char *context, int todo,
1148 const char *file, int line)
1150 static const struct message end_of_sequence = { 0, 0, 0, 0 };
1151 const struct message *actual;
1154 add_message(&end_of_sequence);
1158 while (expected->message && actual->message)
1160 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
1162 if (expected->message == actual->message)
1164 if (expected->flags & wparam)
1166 if (expected->wParam != actual->wParam && todo)
1170 ok_( file, line) (FALSE,
1171 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1172 context, expected->message, expected->wParam, actual->wParam);
1176 ok_( file, line) (expected->wParam == actual->wParam,
1177 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1178 context, expected->message, expected->wParam, actual->wParam);
1180 if (expected->flags & lparam)
1181 ok_( file, line) (expected->lParam == actual->lParam,
1182 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
1183 context, expected->message, expected->lParam, actual->lParam);
1184 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
1185 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
1186 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
1187 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
1188 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
1189 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
1190 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
1191 "%s: the msg 0x%04x should have been %s\n",
1192 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
1193 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
1194 "%s: the msg 0x%04x was expected in %s\n",
1195 context, expected->message, (expected->flags & parent) ? "parent" : "child");
1196 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook),
1197 "%s: the msg 0x%04x should have been sent by a hook\n",
1198 context, expected->message);
1199 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
1200 "%s: the msg 0x%04x should have been sent by a winevent hook\n",
1201 context, expected->message);
1205 /* silently drop winevent messages if there is no support for them */
1206 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))
1212 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1213 context, expected->message, actual->message);
1220 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1221 context, expected->message, actual->message);
1227 /* skip all optional trailing messages */
1228 while (expected->message && ((expected->flags & optional) ||
1229 ((expected->flags & winevent_hook) && !hEvent_hook)))
1235 if (expected->message || actual->message) {
1237 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1238 context, expected->message, actual->message);
1244 if (expected->message || actual->message)
1245 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1246 context, expected->message, actual->message);
1248 if( todo && !failcount) /* succeeded yet marked todo */
1250 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
1256 /******************************** MDI test **********************************/
1258 /* CreateWindow for MDI frame window, initially visible */
1259 static const struct message WmCreateMDIframeSeq[] = {
1260 { HCBT_CREATEWND, hook },
1261 { WM_GETMINMAXINFO, sent },
1262 { WM_NCCREATE, sent },
1263 { WM_NCCALCSIZE, sent|wparam, 0 },
1264 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1265 { WM_CREATE, sent },
1266 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1267 { WM_SHOWWINDOW, sent|wparam, 1 },
1268 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1269 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1270 { HCBT_ACTIVATE, hook },
1271 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1272 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1273 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
1274 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* Win9x */
1275 { WM_ACTIVATEAPP, sent|wparam, 1 },
1276 { WM_NCACTIVATE, sent|wparam, 1 },
1277 { WM_GETTEXT, sent|defwinproc|optional },
1278 { WM_GETICON, sent|defwinproc|optional },
1279 { WM_GETICON, sent|defwinproc|optional },
1280 { WM_ACTIVATE, sent|wparam, 1 },
1281 { HCBT_SETFOCUS, hook },
1282 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1283 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1284 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
1285 /* Win9x adds SWP_NOZORDER below */
1286 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
1291 /* DestroyWindow for MDI frame window, initially visible */
1292 static const struct message WmDestroyMDIframeSeq[] = {
1293 { HCBT_DESTROYWND, hook },
1294 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1295 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1296 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1297 { WM_NCACTIVATE, sent|wparam, 0 },
1298 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
1299 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
1300 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
1301 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1302 { WM_DESTROY, sent },
1303 { WM_NCDESTROY, sent },
1306 /* CreateWindow for MDI client window, initially visible */
1307 static const struct message WmCreateMDIclientSeq[] = {
1308 { HCBT_CREATEWND, hook },
1309 { WM_NCCREATE, sent },
1310 { WM_NCCALCSIZE, sent|wparam, 0 },
1311 { WM_CREATE, sent },
1312 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1315 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
1316 { WM_SHOWWINDOW, sent|wparam, 1 },
1317 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE },
1318 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1319 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1322 /* DestroyWindow for MDI client window, initially visible */
1323 static const struct message WmDestroyMDIclientSeq[] = {
1324 { HCBT_DESTROYWND, hook },
1325 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
1326 { WM_SHOWWINDOW, sent|wparam, 0 },
1327 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1328 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1329 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1330 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1331 { WM_DESTROY, sent },
1332 { WM_NCDESTROY, sent },
1335 /* CreateWindow for MDI child window, initially visible */
1336 static const struct message WmCreateMDIchildVisibleSeq[] = {
1337 { HCBT_CREATEWND, hook },
1338 { WM_NCCREATE, sent },
1339 { WM_NCCALCSIZE, sent|wparam, 0 },
1340 { WM_CREATE, sent },
1341 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1344 /* Win2k sends wparam set to
1345 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1346 * while Win9x doesn't bother to set child window id according to
1347 * CLIENTCREATESTRUCT.idFirstChild
1349 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1350 { WM_SHOWWINDOW, sent|wparam, 1 },
1351 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1352 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1353 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1354 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1355 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1356 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1357 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1359 /* Win9x: message sequence terminates here. */
1361 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1362 { HCBT_SETFOCUS, hook }, /* in MDI client */
1363 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1364 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1365 { WM_SETFOCUS, sent }, /* in MDI client */
1366 { HCBT_SETFOCUS, hook },
1367 { WM_KILLFOCUS, sent }, /* in MDI client */
1368 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1369 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1370 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1371 { WM_SETFOCUS, sent|defwinproc },
1372 { WM_MDIACTIVATE, sent|defwinproc },
1375 /* DestroyWindow for MDI child window, initially visible */
1376 static const struct message WmDestroyMDIchildVisibleSeq[] = {
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 { WM_SHOWWINDOW, sent|wparam, 0 },
1385 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1386 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1387 { WM_ERASEBKGND, sent|parent|optional },
1388 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1390 /* { WM_DESTROY, sent }
1391 * Win9x: message sequence terminates here.
1394 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1395 { WM_KILLFOCUS, sent },
1396 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1397 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1398 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1399 { WM_SETFOCUS, sent }, /* in MDI client */
1401 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1402 { WM_KILLFOCUS, sent }, /* in MDI client */
1403 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1404 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1405 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1406 { WM_SETFOCUS, sent }, /* in MDI client */
1408 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1410 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1411 { WM_KILLFOCUS, sent },
1412 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1413 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1414 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1415 { WM_SETFOCUS, sent }, /* in MDI client */
1417 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1418 { WM_KILLFOCUS, sent }, /* in MDI client */
1419 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1420 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1421 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1422 { WM_SETFOCUS, sent }, /* in MDI client */
1424 { WM_DESTROY, sent },
1426 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1427 { WM_KILLFOCUS, sent },
1428 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
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 */
1433 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1434 { WM_KILLFOCUS, sent }, /* in MDI client */
1435 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1436 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1437 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1438 { WM_SETFOCUS, sent }, /* in MDI client */
1440 { WM_NCDESTROY, sent },
1443 /* CreateWindow for MDI child window, initially invisible */
1444 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1445 { HCBT_CREATEWND, hook },
1446 { WM_NCCREATE, sent },
1447 { WM_NCCALCSIZE, sent|wparam, 0 },
1448 { WM_CREATE, sent },
1449 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1452 /* Win2k sends wparam set to
1453 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1454 * while Win9x doesn't bother to set child window id according to
1455 * CLIENTCREATESTRUCT.idFirstChild
1457 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1460 /* DestroyWindow for MDI child window, initially invisible */
1461 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1462 { HCBT_DESTROYWND, hook },
1463 /* Win2k sends wparam set to
1464 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1465 * while Win9x doesn't bother to set child window id according to
1466 * CLIENTCREATESTRUCT.idFirstChild
1468 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1469 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1470 { WM_DESTROY, sent },
1471 { WM_NCDESTROY, sent },
1474 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1475 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1476 { HCBT_CREATEWND, hook },
1477 { WM_NCCREATE, sent },
1478 { WM_NCCALCSIZE, sent|wparam, 0 },
1479 { WM_CREATE, sent },
1480 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1483 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1484 { WM_GETMINMAXINFO, sent },
1485 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1486 { WM_NCCALCSIZE, sent|wparam, 1 },
1487 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1488 { WM_SIZE, sent|defwinproc },
1490 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1491 { WM_NCCALCSIZE, sent|wparam, 1 },
1492 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1493 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1494 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1495 /* Win2k sends wparam set to
1496 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1497 * while Win9x doesn't bother to set child window id according to
1498 * CLIENTCREATESTRUCT.idFirstChild
1500 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1501 { WM_SHOWWINDOW, sent|wparam, 1 },
1502 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1503 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1504 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1505 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1506 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1507 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1508 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1510 /* Win9x: message sequence terminates here. */
1512 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1513 { HCBT_SETFOCUS, hook }, /* in MDI client */
1514 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1515 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1516 { WM_SETFOCUS, sent }, /* in MDI client */
1517 { HCBT_SETFOCUS, hook },
1518 { WM_KILLFOCUS, sent }, /* in MDI client */
1519 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1520 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1521 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1522 { WM_SETFOCUS, sent|defwinproc },
1523 { WM_MDIACTIVATE, sent|defwinproc },
1525 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1526 { WM_NCCALCSIZE, sent|wparam, 1 },
1527 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1528 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1531 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1532 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
1533 /* restore the 1st MDI child */
1534 { WM_SETREDRAW, sent|wparam, 0 },
1535 { HCBT_MINMAX, hook },
1536 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1537 { WM_NCCALCSIZE, sent|wparam, 1 },
1538 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1539 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1540 { WM_SIZE, sent|defwinproc },
1542 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1543 { WM_NCCALCSIZE, sent|wparam, 1 },
1544 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1545 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1546 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1547 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
1548 /* create the 2nd MDI child */
1549 { HCBT_CREATEWND, hook },
1550 { WM_NCCREATE, sent },
1551 { WM_NCCALCSIZE, sent|wparam, 0 },
1552 { WM_CREATE, sent },
1553 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1556 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1557 { WM_GETMINMAXINFO, sent },
1558 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1559 { WM_NCCALCSIZE, sent|wparam, 1 },
1560 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1561 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1562 { WM_SIZE, sent|defwinproc },
1564 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1565 { WM_NCCALCSIZE, sent|wparam, 1 },
1566 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1567 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1568 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1569 /* Win2k sends wparam set to
1570 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1571 * while Win9x doesn't bother to set child window id according to
1572 * CLIENTCREATESTRUCT.idFirstChild
1574 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1575 { WM_SHOWWINDOW, sent|wparam, 1 },
1576 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1577 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1578 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1579 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1580 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1581 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1583 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1584 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1586 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1588 /* Win9x: message sequence terminates here. */
1590 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1591 { HCBT_SETFOCUS, hook },
1592 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
1593 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
1594 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1595 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1596 { WM_SETFOCUS, sent }, /* in MDI client */
1597 { HCBT_SETFOCUS, hook },
1598 { WM_KILLFOCUS, sent }, /* in MDI client */
1599 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1600 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1601 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1602 { WM_SETFOCUS, sent|defwinproc },
1604 { WM_MDIACTIVATE, sent|defwinproc },
1606 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1607 { WM_NCCALCSIZE, sent|wparam, 1 },
1608 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1609 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1612 /* WM_MDICREATE MDI child window, initially visible and maximized */
1613 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
1614 { WM_MDICREATE, sent },
1615 { HCBT_CREATEWND, hook },
1616 { WM_NCCREATE, sent },
1617 { WM_NCCALCSIZE, sent|wparam, 0 },
1618 { WM_CREATE, sent },
1619 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1622 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1623 { WM_GETMINMAXINFO, sent },
1624 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1625 { WM_NCCALCSIZE, sent|wparam, 1 },
1626 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1627 { WM_SIZE, sent|defwinproc },
1630 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1631 { WM_NCCALCSIZE, sent|wparam, 1 },
1632 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1633 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1634 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1636 /* Win2k sends wparam set to
1637 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1638 * while Win9x doesn't bother to set child window id according to
1639 * CLIENTCREATESTRUCT.idFirstChild
1641 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1642 { WM_SHOWWINDOW, sent|wparam, 1 },
1643 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1645 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1647 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1648 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1649 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1651 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1652 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1654 /* Win9x: message sequence terminates here. */
1656 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1657 { HCBT_SETFOCUS, hook }, /* in MDI client */
1658 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1659 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1660 { WM_SETFOCUS, sent }, /* in MDI client */
1661 { HCBT_SETFOCUS, hook },
1662 { WM_KILLFOCUS, sent }, /* in MDI client */
1663 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1664 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1665 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1666 { WM_SETFOCUS, sent|defwinproc },
1668 { WM_MDIACTIVATE, sent|defwinproc },
1671 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1672 { WM_NCCALCSIZE, sent|wparam, 1 },
1673 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1674 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1677 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1678 { WM_NCCALCSIZE, sent|wparam, 1 },
1679 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1680 { WM_MOVE, sent|defwinproc },
1681 { WM_SIZE, sent|defwinproc },
1684 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1685 { WM_NCCALCSIZE, sent|wparam, 1 },
1686 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1690 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1691 { WM_NCCALCSIZE, sent|wparam, 1 },
1692 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1693 { WM_SIZE, sent|defwinproc },
1695 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1696 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1697 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1701 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1702 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
1703 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
1704 { HCBT_SYSCOMMAND, hook },
1705 { WM_CLOSE, sent|defwinproc },
1706 { WM_MDIDESTROY, sent }, /* in MDI client */
1708 /* bring the 1st MDI child to top */
1709 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
1710 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
1712 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1714 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
1715 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1716 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1718 /* maximize the 1st MDI child */
1719 { HCBT_MINMAX, hook },
1720 { WM_GETMINMAXINFO, sent|defwinproc },
1721 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
1722 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1723 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
1724 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1725 { WM_SIZE, sent|defwinproc },
1727 /* restore the 2nd MDI child */
1728 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
1729 { HCBT_MINMAX, hook },
1730 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOZORDER|0x8000 },
1731 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1733 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1735 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1736 { WM_SIZE, sent|defwinproc },
1738 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1740 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
1742 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1743 { WM_NCCALCSIZE, sent|wparam, 1 },
1744 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1745 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1746 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1748 /* bring the 1st MDI child to top */
1749 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1750 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1751 { HCBT_SETFOCUS, hook },
1752 { WM_KILLFOCUS, sent|defwinproc },
1753 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
1754 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1755 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1756 { WM_SETFOCUS, sent }, /* in MDI client */
1757 { HCBT_SETFOCUS, hook },
1758 { WM_KILLFOCUS, sent }, /* in MDI client */
1759 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1760 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1761 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1762 { WM_SETFOCUS, sent|defwinproc },
1763 { WM_MDIACTIVATE, sent|defwinproc },
1764 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1766 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1767 { WM_SHOWWINDOW, sent|wparam, 1 },
1768 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1769 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1770 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1771 { WM_MDIREFRESHMENU, sent },
1773 { HCBT_DESTROYWND, hook },
1774 /* Win2k sends wparam set to
1775 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1776 * while Win9x doesn't bother to set child window id according to
1777 * CLIENTCREATESTRUCT.idFirstChild
1779 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1780 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
1781 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1782 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1783 { WM_ERASEBKGND, sent|parent|optional },
1784 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1786 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1787 { WM_DESTROY, sent|defwinproc },
1788 { WM_NCDESTROY, sent|defwinproc },
1791 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1792 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
1793 { WM_MDIDESTROY, sent }, /* in MDI client */
1794 { WM_SHOWWINDOW, sent|wparam, 0 },
1795 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1796 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1797 { WM_ERASEBKGND, sent|parent|optional },
1798 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1800 { HCBT_SETFOCUS, hook },
1801 { WM_KILLFOCUS, sent },
1802 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1803 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1804 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1805 { WM_SETFOCUS, sent }, /* in MDI client */
1806 { HCBT_SETFOCUS, hook },
1807 { WM_KILLFOCUS, sent }, /* in MDI client */
1808 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1809 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1810 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1811 { WM_SETFOCUS, sent },
1814 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1815 { WM_NCCALCSIZE, sent|wparam, 1 },
1816 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1817 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1820 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1821 { WM_NCCALCSIZE, sent|wparam, 1 },
1822 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1823 { WM_MOVE, sent|defwinproc },
1824 { WM_SIZE, sent|defwinproc },
1827 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1828 { WM_NCCALCSIZE, sent|wparam, 1 },
1829 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1833 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1834 { WM_NCCALCSIZE, sent|wparam, 1 },
1835 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1836 { WM_SIZE, sent|defwinproc },
1839 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1840 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1841 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1842 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1845 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1846 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1847 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1848 { WM_MOVE, sent|defwinproc },
1849 { WM_SIZE, sent|defwinproc },
1852 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1853 { WM_NCCALCSIZE, sent|wparam, 1 },
1854 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1858 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOZORDER },
1859 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1860 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1861 { WM_SIZE, sent|defwinproc },
1862 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1863 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1864 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1865 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1866 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1867 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1870 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1871 { WM_NCCALCSIZE, sent|wparam, 1 },
1872 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1873 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1875 { WM_NCACTIVATE, sent|wparam, 0 },
1876 { WM_MDIACTIVATE, sent },
1878 { HCBT_MINMAX, hook },
1879 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
1880 { WM_NCCALCSIZE, sent|wparam, 1 },
1882 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1884 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1885 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE|0x8000 },
1886 { WM_SIZE, sent|defwinproc },
1889 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1890 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1891 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1892 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
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 },
1898 { WM_MOVE, sent|defwinproc },
1899 { WM_SIZE, sent|defwinproc },
1902 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1903 { WM_NCCALCSIZE, sent|wparam, 1 },
1904 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1906 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1907 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1908 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1910 { HCBT_SETFOCUS, hook },
1911 { WM_KILLFOCUS, sent },
1912 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1913 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1914 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1915 { WM_SETFOCUS, sent }, /* in MDI client */
1917 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
1919 { HCBT_DESTROYWND, hook },
1920 /* Win2k sends wparam set to
1921 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1922 * while Win9x doesn't bother to set child window id according to
1923 * CLIENTCREATESTRUCT.idFirstChild
1925 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1927 { WM_SHOWWINDOW, sent|wparam, 0 },
1928 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1929 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1930 { WM_ERASEBKGND, sent|parent|optional },
1931 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1933 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1934 { WM_DESTROY, sent },
1935 { WM_NCDESTROY, sent },
1938 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1939 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
1940 { HCBT_MINMAX, hook },
1941 { WM_GETMINMAXINFO, sent },
1942 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1943 { WM_NCCALCSIZE, sent|wparam, 1 },
1944 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1945 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1947 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1948 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1949 { HCBT_SETFOCUS, hook },
1950 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1951 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1952 { WM_SETFOCUS, sent }, /* in MDI client */
1953 { HCBT_SETFOCUS, hook },
1954 { WM_KILLFOCUS, sent }, /* in MDI client */
1955 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1956 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1957 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1958 { WM_SETFOCUS, sent|defwinproc },
1959 { WM_MDIACTIVATE, sent|defwinproc },
1960 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1961 { WM_SIZE, sent|defwinproc },
1963 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1964 { WM_NCCALCSIZE, sent|wparam, 1 },
1965 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1966 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1967 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1970 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1971 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
1972 { HCBT_MINMAX, hook },
1973 { WM_GETMINMAXINFO, sent },
1974 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1975 { WM_NCCALCSIZE, sent|wparam, 1 },
1976 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1977 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1978 { WM_SIZE, sent|defwinproc },
1980 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1981 { WM_NCCALCSIZE, sent|wparam, 1 },
1982 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1983 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1984 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1987 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
1988 static const struct message WmRestoreMDIchildVisibleSeq[] = {
1989 { HCBT_MINMAX, hook },
1990 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1991 { WM_NCCALCSIZE, sent|wparam, 1 },
1992 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1993 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1994 { WM_SIZE, sent|defwinproc },
1996 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1997 { WM_NCCALCSIZE, sent|wparam, 1 },
1998 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1999 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2000 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2003 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
2004 static const struct message WmRestoreMDIchildInisibleSeq[] = {
2005 { HCBT_MINMAX, hook },
2006 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
2007 { WM_NCCALCSIZE, sent|wparam, 1 },
2008 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2009 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2010 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2011 { WM_SIZE, sent|defwinproc },
2013 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2014 { WM_NCCALCSIZE, sent|wparam, 1 },
2015 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2016 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2017 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2021 static HWND mdi_client;
2022 static WNDPROC old_mdi_client_proc;
2024 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2028 /* do not log painting messages */
2029 if (message != WM_PAINT &&
2030 message != WM_ERASEBKGND &&
2031 message != WM_NCPAINT &&
2032 message != WM_NCHITTEST &&
2033 message != WM_GETTEXT &&
2034 message != WM_MDIGETACTIVE &&
2035 message != WM_DEVICECHANGE)
2037 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2041 case WM_WINDOWPOSCHANGING:
2042 case WM_WINDOWPOSCHANGED:
2044 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2046 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2047 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2048 winpos->hwnd, winpos->hwndInsertAfter,
2049 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2051 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2052 * in the high word for internal purposes
2054 wParam = winpos->flags & 0xffff;
2059 msg.message = message;
2060 msg.flags = sent|wparam|lparam;
2061 msg.wParam = wParam;
2062 msg.lParam = lParam;
2066 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
2069 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2071 static long defwndproc_counter = 0;
2075 /* do not log painting messages */
2076 if (message != WM_PAINT &&
2077 message != WM_ERASEBKGND &&
2078 message != WM_NCPAINT &&
2079 message != WM_NCHITTEST &&
2080 message != WM_GETTEXT &&
2081 message != WM_DEVICECHANGE)
2083 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2087 case WM_WINDOWPOSCHANGING:
2088 case WM_WINDOWPOSCHANGED:
2090 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2092 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2093 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2094 winpos->hwnd, winpos->hwndInsertAfter,
2095 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2097 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2098 * in the high word for internal purposes
2100 wParam = winpos->flags & 0xffff;
2104 case WM_MDIACTIVATE:
2106 HWND active, client = GetParent(hwnd);
2108 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
2110 if (hwnd == (HWND)lParam) /* if we are being activated */
2111 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
2113 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
2118 msg.message = message;
2119 msg.flags = sent|wparam|lparam;
2120 if (defwndproc_counter) msg.flags |= defwinproc;
2121 msg.wParam = wParam;
2122 msg.lParam = lParam;
2126 defwndproc_counter++;
2127 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
2128 defwndproc_counter--;
2133 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2135 static long defwndproc_counter = 0;
2139 /* do not log painting messages */
2140 if (message != WM_PAINT &&
2141 message != WM_ERASEBKGND &&
2142 message != WM_NCPAINT &&
2143 message != WM_NCHITTEST &&
2144 message != WM_GETTEXT &&
2145 message != WM_DEVICECHANGE)
2147 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2151 case WM_WINDOWPOSCHANGING:
2152 case WM_WINDOWPOSCHANGED:
2154 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2156 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2157 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2158 winpos->hwnd, winpos->hwndInsertAfter,
2159 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2161 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2162 * in the high word for internal purposes
2164 wParam = winpos->flags & 0xffff;
2169 msg.message = message;
2170 msg.flags = sent|wparam|lparam;
2171 if (defwndproc_counter) msg.flags |= defwinproc;
2172 msg.wParam = wParam;
2173 msg.lParam = lParam;
2177 defwndproc_counter++;
2178 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
2179 defwndproc_counter--;
2184 static BOOL mdi_RegisterWindowClasses(void)
2189 cls.lpfnWndProc = mdi_frame_wnd_proc;
2192 cls.hInstance = GetModuleHandleA(0);
2194 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
2195 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2196 cls.lpszMenuName = NULL;
2197 cls.lpszClassName = "MDI_frame_class";
2198 if (!RegisterClassA(&cls)) return FALSE;
2200 cls.lpfnWndProc = mdi_child_wnd_proc;
2201 cls.lpszClassName = "MDI_child_class";
2202 if (!RegisterClassA(&cls)) return FALSE;
2204 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
2205 old_mdi_client_proc = cls.lpfnWndProc;
2206 cls.hInstance = GetModuleHandleA(0);
2207 cls.lpfnWndProc = mdi_client_hook_proc;
2208 cls.lpszClassName = "MDI_client_class";
2209 if (!RegisterClassA(&cls)) assert(0);
2214 static void test_mdi_messages(void)
2216 MDICREATESTRUCTA mdi_cs;
2217 CLIENTCREATESTRUCT client_cs;
2218 HWND mdi_frame, mdi_child, mdi_child2, active_child;
2220 HMENU hMenu = CreateMenu();
2222 assert(mdi_RegisterWindowClasses());
2226 trace("creating MDI frame window\n");
2227 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
2228 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2229 WS_MAXIMIZEBOX | WS_VISIBLE,
2230 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2231 GetDesktopWindow(), hMenu,
2232 GetModuleHandleA(0), NULL);
2234 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
2236 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2237 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
2239 trace("creating MDI client window\n");
2240 client_cs.hWindowMenu = 0;
2241 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
2242 mdi_client = CreateWindowExA(0, "MDI_client_class",
2244 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
2246 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
2248 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
2250 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2251 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
2253 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2254 ok(!active_child, "wrong active MDI child %p\n", active_child);
2255 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2260 trace("creating invisible MDI child window\n");
2261 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2263 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2264 mdi_client, 0, GetModuleHandleA(0), NULL);
2268 ShowWindow(mdi_child, SW_SHOWNORMAL);
2269 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
2271 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2272 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2274 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2275 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2277 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2278 ok(!active_child, "wrong active MDI child %p\n", active_child);
2279 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2281 ShowWindow(mdi_child, SW_HIDE);
2282 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
2285 ShowWindow(mdi_child, SW_SHOW);
2286 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
2288 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2289 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2291 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2292 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2294 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2295 ok(!active_child, "wrong active MDI child %p\n", active_child);
2296 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2298 DestroyWindow(mdi_child);
2301 trace("creating visible MDI child window\n");
2302 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2303 WS_CHILD | WS_VISIBLE,
2304 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2305 mdi_client, 0, GetModuleHandleA(0), NULL);
2307 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE);
2309 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2310 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2312 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2313 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2315 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2316 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2317 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2320 DestroyWindow(mdi_child);
2321 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2323 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2324 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2326 /* Win2k: MDI client still returns a just destroyed child as active
2327 * Win9x: MDI client returns 0
2329 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2330 ok(active_child == mdi_child || /* win2k */
2331 !active_child, /* win9x */
2332 "wrong active MDI child %p\n", active_child);
2333 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2337 trace("creating invisible MDI child window\n");
2338 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2340 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2341 mdi_client, 0, GetModuleHandleA(0), NULL);
2343 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
2345 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
2346 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
2348 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2349 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2351 /* Win2k: MDI client still returns a just destroyed child as active
2352 * Win9x: MDI client returns mdi_child2
2354 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2355 ok(active_child == mdi_child || /* win2k */
2356 active_child == mdi_child2, /* win9x */
2357 "wrong active MDI child %p\n", active_child);
2358 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2361 ShowWindow(mdi_child2, SW_MAXIMIZE);
2362 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
2364 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2365 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2367 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2368 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2369 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2372 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2373 ok(GetFocus() == mdi_child2 || /* win2k */
2374 GetFocus() == 0, /* win9x */
2375 "wrong focus window %p\n", GetFocus());
2380 ShowWindow(mdi_child2, SW_HIDE);
2381 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2383 ShowWindow(mdi_child2, SW_RESTORE);
2384 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
2387 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2388 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2390 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2391 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2392 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2398 ShowWindow(mdi_child2, SW_HIDE);
2399 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2401 ShowWindow(mdi_child2, SW_SHOW);
2402 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
2404 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2405 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2407 ShowWindow(mdi_child2, SW_MAXIMIZE);
2408 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
2410 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2411 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2413 ShowWindow(mdi_child2, SW_RESTORE);
2414 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
2416 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2417 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2422 ShowWindow(mdi_child2, SW_HIDE);
2423 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2425 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2426 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2428 DestroyWindow(mdi_child2);
2429 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
2431 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2432 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2434 /* test for maximized MDI children */
2435 trace("creating maximized visible MDI child window 1\n");
2436 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2437 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2438 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2439 mdi_client, 0, GetModuleHandleA(0), NULL);
2441 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
2442 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2444 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2445 ok(GetFocus() == mdi_child || /* win2k */
2446 GetFocus() == 0, /* win9x */
2447 "wrong focus window %p\n", GetFocus());
2449 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2450 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2451 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2454 trace("creating maximized visible MDI child window 2\n");
2455 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2456 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2457 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2458 mdi_client, 0, GetModuleHandleA(0), NULL);
2460 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2461 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2462 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2464 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2465 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2467 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2468 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2469 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2472 trace("destroying maximized visible MDI child window 2\n");
2473 DestroyWindow(mdi_child2);
2474 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2476 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2478 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2479 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2481 /* Win2k: MDI client still returns a just destroyed child as active
2482 * Win9x: MDI client returns 0
2484 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2485 ok(active_child == mdi_child2 || /* win2k */
2486 !active_child, /* win9x */
2487 "wrong active MDI child %p\n", active_child);
2490 ShowWindow(mdi_child, SW_MAXIMIZE);
2491 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2494 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2495 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2497 trace("re-creating maximized visible MDI child window 2\n");
2498 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2499 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2500 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2501 mdi_client, 0, GetModuleHandleA(0), NULL);
2503 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2504 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2505 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2507 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2508 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2510 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2511 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2512 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2515 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
2516 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
2517 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
2519 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2520 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2521 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2523 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2524 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2525 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2528 DestroyWindow(mdi_child);
2529 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2531 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2532 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2534 /* Win2k: MDI client still returns a just destroyed child as active
2535 * Win9x: MDI client returns 0
2537 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2538 ok(active_child == mdi_child || /* win2k */
2539 !active_child, /* win9x */
2540 "wrong active MDI child %p\n", active_child);
2542 /* end of test for maximized MDI children */
2544 mdi_cs.szClass = "MDI_child_Class";
2545 mdi_cs.szTitle = "MDI child";
2546 mdi_cs.hOwner = GetModuleHandleA(0);
2549 mdi_cs.cx = CW_USEDEFAULT;
2550 mdi_cs.cy = CW_USEDEFAULT;
2551 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
2553 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
2554 ok(mdi_child != 0, "MDI child creation failed\n");
2555 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
2557 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
2559 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2560 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2562 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
2563 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2564 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2566 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2567 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2568 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2571 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
2572 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
2574 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
2575 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2576 ok(!active_child, "wrong active MDI child %p\n", active_child);
2581 DestroyWindow(mdi_client);
2582 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
2584 DestroyWindow(mdi_frame);
2585 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
2587 /************************* End of MDI test **********************************/
2589 static void test_WM_SETREDRAW(HWND hwnd)
2591 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
2595 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
2596 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
2598 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
2599 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
2602 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
2603 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
2605 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2606 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
2608 /* restore original WS_VISIBLE state */
2609 SetWindowLongA(hwnd, GWL_STYLE, style);
2614 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2618 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2622 case WM_WINDOWPOSCHANGING:
2623 case WM_WINDOWPOSCHANGED:
2625 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2627 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2628 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2629 winpos->hwnd, winpos->hwndInsertAfter,
2630 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2632 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2633 * in the high word for internal purposes
2635 wParam = winpos->flags & 0xffff;
2640 msg.message = message;
2641 msg.flags = sent|wparam|lparam;
2642 msg.wParam = wParam;
2643 msg.lParam = lParam;
2646 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2647 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2651 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2653 DWORD style, exstyle;
2657 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2658 style = GetWindowLongA(hwnd, GWL_STYLE);
2659 /* do not be confused by WS_DLGFRAME set */
2660 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2662 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2663 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2665 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2666 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2667 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2668 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
2670 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2672 style = GetWindowLongA(hwnd, GWL_STYLE);
2673 if (set) ok(style & set, "style %08lx should be set\n", set);
2674 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2676 /* a subsequent call should do nothing */
2677 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2678 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2679 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2683 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2684 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax);
2685 ok( ret, "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
2686 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2687 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
2688 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
2691 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2693 DWORD style, exstyle;
2697 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2698 style = GetWindowLongA(hwnd, GWL_STYLE);
2699 /* do not be confused by WS_DLGFRAME set */
2700 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2702 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2703 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2705 si.cbSize = sizeof(si);
2706 si.fMask = SIF_RANGE;
2709 SetScrollInfo(hwnd, ctl, &si, TRUE);
2710 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2711 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
2713 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2715 style = GetWindowLongA(hwnd, GWL_STYLE);
2716 if (set) ok(style & set, "style %08lx should be set\n", set);
2717 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2719 /* a subsequent call should do nothing */
2720 SetScrollInfo(hwnd, ctl, &si, TRUE);
2721 if (style & WS_HSCROLL)
2722 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2723 else if (style & WS_VSCROLL)
2724 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2726 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2728 si.fMask = SIF_PAGE;
2730 SetScrollInfo(hwnd, ctl, &si, FALSE);
2731 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2735 SetScrollInfo(hwnd, ctl, &si, FALSE);
2736 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2738 si.fMask = SIF_RANGE;
2739 si.nMin = 0xdeadbeef;
2740 si.nMax = 0xdeadbeef;
2741 ret = GetScrollInfo(hwnd, ctl, &si);
2742 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2743 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2744 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
2745 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
2748 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2749 static void test_scroll_messages(HWND hwnd)
2757 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2758 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2759 if (sequence->message != WmGetScrollRangeSeq[0].message)
2760 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2761 /* values of min and max are undefined */
2764 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE);
2765 ok( ret, "SetScrollRange error %ld\n", GetLastError());
2766 if (sequence->message != WmSetScrollRangeSeq[0].message)
2767 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2772 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2773 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2774 if (sequence->message != WmGetScrollRangeSeq[0].message)
2775 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2776 /* values of min and max are undefined */
2779 si.cbSize = sizeof(si);
2780 si.fMask = SIF_RANGE;
2783 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2784 if (sequence->message != WmSetScrollRangeSeq[0].message)
2785 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2788 si.fMask = SIF_PAGE;
2790 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2791 if (sequence->message != WmSetScrollRangeSeq[0].message)
2792 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2797 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2798 if (sequence->message != WmSetScrollRangeSeq[0].message)
2799 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2802 si.fMask = SIF_RANGE;
2803 si.nMin = 0xdeadbeef;
2804 si.nMax = 0xdeadbeef;
2805 ret = GetScrollInfo(hwnd, SB_CTL, &si);
2806 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2807 if (sequence->message != WmGetScrollInfoSeq[0].message)
2808 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2809 /* values of min and max are undefined */
2812 /* set WS_HSCROLL */
2813 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2814 /* clear WS_HSCROLL */
2815 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2817 /* set WS_HSCROLL */
2818 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2819 /* clear WS_HSCROLL */
2820 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2822 /* set WS_VSCROLL */
2823 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2824 /* clear WS_VSCROLL */
2825 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2827 /* set WS_VSCROLL */
2828 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2829 /* clear WS_VSCROLL */
2830 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2833 static void test_showwindow(void)
2837 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2838 100, 100, 200, 200, 0, 0, 0, NULL);
2839 ok (hwnd != 0, "Failed to create overlapped window\n");
2840 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2841 0, 0, 10, 10, hwnd, 0, 0, NULL);
2842 ok (hchild != 0, "Failed to create child\n");
2845 /* ShowWindow( SW_SHOWNA) for invisible top level window */
2846 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
2847 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2848 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", TRUE);
2851 /* ShowWindow( SW_SHOWNA) for now visible top level window */
2852 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
2853 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2854 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE);
2856 /* back to invisible */
2857 ShowWindow(hchild, SW_HIDE);
2858 ShowWindow(hwnd, SW_HIDE);
2860 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
2861 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
2862 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2863 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", TRUE);
2865 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
2866 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
2868 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
2869 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2870 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", TRUE);
2872 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
2873 ShowWindow( hwnd, SW_SHOW);
2875 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
2876 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2877 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE);
2880 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
2881 ShowWindow( hchild, SW_HIDE);
2883 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
2884 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2885 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE);
2889 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture());
2890 DestroyWindow(hchild);
2891 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
2893 DestroyWindow(hwnd);
2897 static void test_sys_menu(HWND hwnd)
2902 /* test existing window without CS_NOCLOSE style */
2903 hmenu = GetSystemMenu(hwnd, FALSE);
2904 ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
2906 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
2907 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
2908 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
2910 EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
2911 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
2913 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
2914 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
2915 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state);
2917 EnableMenuItem(hmenu, SC_CLOSE, 0);
2918 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
2920 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
2921 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
2922 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
2924 /* test new window with CS_NOCLOSE style */
2925 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW,
2926 100, 100, 200, 200, 0, 0, 0, NULL);
2927 ok (hwnd != 0, "Failed to create overlapped window\n");
2929 hmenu = GetSystemMenu(hwnd, FALSE);
2930 ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
2932 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
2933 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state);
2935 DestroyWindow(hwnd);
2938 /* test if we receive the right sequence of messages */
2939 static void test_messages(void)
2941 HWND hwnd, hparent, hchild;
2942 HWND hchild2, hbutton;
2949 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2950 100, 100, 200, 200, 0, 0, 0, NULL);
2951 ok (hwnd != 0, "Failed to create overlapped window\n");
2952 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2954 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2955 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
2956 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
2958 /* test WM_SETREDRAW on a not visible top level window */
2959 test_WM_SETREDRAW(hwnd);
2961 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2962 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
2963 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
2965 ok(GetActiveWindow() == hwnd, "window should be active\n");
2966 ok(GetFocus() == hwnd, "window should have input focus\n");
2967 ShowWindow(hwnd, SW_HIDE);
2968 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
2970 ShowWindow(hwnd, SW_SHOW);
2971 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
2973 ShowWindow(hwnd, SW_HIDE);
2974 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
2976 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
2977 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE);
2979 ShowWindow(hwnd, SW_RESTORE);
2980 /* FIXME: add ok_sequence() here */
2983 ShowWindow(hwnd, SW_SHOW);
2984 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
2986 ok(GetActiveWindow() == hwnd, "window should be active\n");
2987 ok(GetFocus() == hwnd, "window should have input focus\n");
2988 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2989 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
2990 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
2991 ok(GetActiveWindow() == hwnd, "window should still be active\n");
2993 /* test WM_SETREDRAW on a visible top level window */
2994 ShowWindow(hwnd, SW_SHOW);
2995 test_WM_SETREDRAW(hwnd);
2997 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
2998 test_scroll_messages(hwnd);
3000 /* test resizing and moving */
3001 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
3002 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE );
3003 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE );
3004 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE );
3006 /* popups don't get WM_GETMINMAXINFO */
3007 SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP );
3008 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED);
3010 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
3011 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
3013 test_sys_menu(hwnd);
3016 DestroyWindow(hwnd);
3017 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
3019 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3020 100, 100, 200, 200, 0, 0, 0, NULL);
3021 ok (hparent != 0, "Failed to create parent window\n");
3024 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
3025 0, 0, 10, 10, hparent, 0, 0, NULL);
3026 ok (hchild != 0, "Failed to create child window\n");
3027 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
3028 DestroyWindow(hchild);
3031 /* visible child window with a caption */
3032 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
3033 WS_CHILD | WS_VISIBLE | WS_CAPTION,
3034 0, 0, 10, 10, hparent, 0, 0, NULL);
3035 ok (hchild != 0, "Failed to create child window\n");
3036 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
3038 trace("testing scroll APIs on a visible child window %p\n", hchild);
3039 test_scroll_messages(hchild);
3041 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3042 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
3044 DestroyWindow(hchild);
3047 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
3048 0, 0, 10, 10, hparent, 0, 0, NULL);
3049 ok (hchild != 0, "Failed to create child window\n");
3050 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
3052 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
3053 100, 100, 50, 50, hparent, 0, 0, NULL);
3054 ok (hchild2 != 0, "Failed to create child2 window\n");
3057 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
3058 0, 100, 50, 50, hchild, 0, 0, NULL);
3059 ok (hbutton != 0, "Failed to create button window\n");
3061 /* test WM_SETREDRAW on a not visible child window */
3062 test_WM_SETREDRAW(hchild);
3064 ShowWindow(hchild, SW_SHOW);
3065 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
3067 ShowWindow(hchild, SW_HIDE);
3068 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
3070 ShowWindow(hchild, SW_SHOW);
3071 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
3073 /* test WM_SETREDRAW on a visible child window */
3074 test_WM_SETREDRAW(hchild);
3076 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
3077 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
3079 ShowWindow(hchild, SW_HIDE);
3081 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3082 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
3084 ShowWindow(hchild, SW_HIDE);
3086 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
3087 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
3089 /* DestroyWindow sequence below expects that a child has focus */
3093 DestroyWindow(hchild);
3094 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
3095 DestroyWindow(hchild2);
3096 DestroyWindow(hbutton);
3099 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
3100 0, 0, 100, 100, hparent, 0, 0, NULL);
3101 ok (hchild != 0, "Failed to create child popup window\n");
3102 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
3103 DestroyWindow(hchild);
3105 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
3107 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
3108 0, 0, 100, 100, hparent, 0, 0, NULL);
3109 ok (hchild != 0, "Failed to create popup window\n");
3110 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
3111 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3112 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
3114 ShowWindow(hchild, SW_SHOW);
3115 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
3117 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3118 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
3120 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3121 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
3122 DestroyWindow(hchild);
3124 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
3125 * changes nothing in message sequences.
3128 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
3129 0, 0, 100, 100, hparent, 0, 0, NULL);
3130 ok (hchild != 0, "Failed to create popup window\n");
3131 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
3132 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3133 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
3135 ShowWindow(hchild, SW_SHOW);
3136 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
3138 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3139 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
3140 DestroyWindow(hchild);
3143 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
3144 0, 0, 100, 100, hparent, 0, 0, NULL);
3145 ok(hwnd != 0, "Failed to create custom dialog window\n");
3146 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
3149 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
3150 test_scroll_messages(hwnd);
3154 after_end_dialog = 1;
3155 EndDialog( hwnd, 0 );
3156 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
3158 DestroyWindow(hwnd);
3159 after_end_dialog = 0;
3161 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP,
3162 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
3163 ok(hwnd != 0, "Failed to create custom dialog window\n");
3165 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
3166 ShowWindow(hwnd, SW_SHOW);
3167 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
3168 DestroyWindow(hwnd);
3171 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
3172 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
3174 /* test showing child with hidden parent */
3175 ShowWindow( hparent, SW_HIDE );
3178 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
3179 0, 0, 10, 10, hparent, 0, 0, NULL);
3180 ok (hchild != 0, "Failed to create child window\n");
3181 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
3183 ShowWindow( hchild, SW_SHOW );
3184 ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", TRUE);
3185 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3186 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3188 ShowWindow( hchild, SW_HIDE );
3189 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", TRUE);
3190 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
3191 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3193 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3194 ok_sequence(WmShowChildInvisibleParentSeq_2, "SetWindowPos:show child with invisible parent", FALSE);
3195 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3196 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3198 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3199 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE);
3200 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
3201 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3203 DestroyWindow(hchild);
3204 DestroyWindow(hparent);
3207 /* Message sequence for SetMenu */
3208 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
3209 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
3211 hmenu = CreateMenu();
3212 ok (hmenu != 0, "Failed to create menu\n");
3213 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
3214 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3215 100, 100, 200, 200, 0, hmenu, 0, NULL);
3216 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
3217 ok (SetMenu(hwnd, 0), "SetMenu\n");
3218 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
3219 ok (SetMenu(hwnd, 0), "SetMenu\n");
3220 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
3221 ShowWindow(hwnd, SW_SHOW);
3223 ok (SetMenu(hwnd, 0), "SetMenu\n");
3224 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
3225 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
3226 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
3228 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
3229 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
3231 DestroyWindow(hwnd);
3234 /* Message sequence for EnableWindow */
3235 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3236 100, 100, 200, 200, 0, 0, 0, NULL);
3237 ok (hparent != 0, "Failed to create parent window\n");
3238 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
3239 0, 0, 10, 10, hparent, 0, 0, NULL);
3240 ok (hchild != 0, "Failed to create child window\n");
3245 EnableWindow(hparent, FALSE);
3246 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE);
3248 EnableWindow(hparent, TRUE);
3249 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(TRUE)", FALSE);
3251 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3254 /* MsgWaitForMultipleObjects test */
3255 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
3256 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %lx\n", ret);
3258 PostMessageA(hparent, WM_USER, 0, 0);
3260 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
3261 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %lx\n", ret);
3263 ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
3264 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
3266 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
3267 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %lx\n", ret);
3268 /* end of MsgWaitForMultipleObjects test */
3270 /* the following test causes an exception in user.exe under win9x */
3271 if (!PostMessageW( hparent, WM_USER, 0, 0 )) return;
3272 PostMessageW( hparent, WM_USER+1, 0, 0 );
3273 /* PeekMessage(NULL) fails, but still removes the message */
3274 SetLastError(0xdeadbeef);
3275 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
3276 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */
3277 GetLastError() == 0xdeadbeef, /* NT4 */
3278 "last error is %ld\n", GetLastError() );
3279 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
3280 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
3282 DestroyWindow(hchild);
3283 DestroyWindow(hparent);
3289 /****************** button message test *************************/
3290 static const struct message WmSetFocusButtonSeq[] =
3292 { HCBT_SETFOCUS, hook },
3293 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3294 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3295 { WM_SETFOCUS, sent|wparam, 0 },
3296 { WM_CTLCOLORBTN, sent|defwinproc },
3299 static const struct message WmKillFocusButtonSeq[] =
3301 { HCBT_SETFOCUS, hook },
3302 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3303 { WM_KILLFOCUS, sent|wparam, 0 },
3304 { WM_CTLCOLORBTN, sent|defwinproc },
3305 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3308 static const struct message WmSetFocusStaticSeq[] =
3310 { HCBT_SETFOCUS, hook },
3311 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3312 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3313 { WM_SETFOCUS, sent|wparam, 0 },
3314 { WM_CTLCOLORSTATIC, sent|defwinproc },
3317 static const struct message WmKillFocusStaticSeq[] =
3319 { HCBT_SETFOCUS, hook },
3320 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3321 { WM_KILLFOCUS, sent|wparam, 0 },
3322 { WM_CTLCOLORSTATIC, sent|defwinproc },
3323 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3326 static const struct message WmLButtonDownSeq[] =
3328 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
3329 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
3330 { HCBT_SETFOCUS, hook },
3331 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
3332 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3333 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
3334 { WM_CTLCOLORBTN, sent|defwinproc },
3335 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
3336 { WM_CTLCOLORBTN, sent|defwinproc },
3337 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3340 static const struct message WmLButtonUpSeq[] =
3342 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
3343 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
3344 { WM_CTLCOLORBTN, sent|defwinproc },
3345 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3346 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
3347 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
3351 static WNDPROC old_button_proc;
3353 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3355 static long defwndproc_counter = 0;
3359 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3361 msg.message = message;
3362 msg.flags = sent|wparam|lparam;
3363 if (defwndproc_counter) msg.flags |= defwinproc;
3364 msg.wParam = wParam;
3365 msg.lParam = lParam;
3368 if (message == BM_SETSTATE)
3369 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
3371 defwndproc_counter++;
3372 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
3373 defwndproc_counter--;
3378 static void subclass_button(void)
3382 if (!GetClassInfoA(0, "button", &cls)) assert(0);
3384 old_button_proc = cls.lpfnWndProc;
3386 cls.hInstance = GetModuleHandle(0);
3387 cls.lpfnWndProc = button_hook_proc;
3388 cls.lpszClassName = "my_button_class";
3389 if (!RegisterClassA(&cls)) assert(0);
3392 static void test_button_messages(void)
3398 const struct message *setfocus;
3399 const struct message *killfocus;
3401 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3402 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3403 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
3404 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3405 { BS_CHECKBOX, DLGC_BUTTON,
3406 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3407 { BS_AUTOCHECKBOX, DLGC_BUTTON,
3408 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3409 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3410 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3411 { BS_3STATE, DLGC_BUTTON,
3412 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3413 { BS_AUTO3STATE, DLGC_BUTTON,
3414 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3415 { BS_GROUPBOX, DLGC_STATIC,
3416 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3417 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3418 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3419 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3420 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3421 { BS_OWNERDRAW, DLGC_BUTTON,
3422 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
3430 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
3432 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
3433 0, 0, 50, 14, 0, 0, 0, NULL);
3434 ok(hwnd != 0, "Failed to create button window\n");
3436 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
3437 ok(dlg_code == button[i].dlg_code, "%d: wrong dlg_code %08lx\n", i, dlg_code);
3439 ShowWindow(hwnd, SW_SHOW);
3444 trace("button style %08lx\n", button[i].style);
3446 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
3449 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
3451 DestroyWindow(hwnd);
3454 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
3455 0, 0, 50, 14, 0, 0, 0, NULL);
3456 ok(hwnd != 0, "Failed to create button window\n");
3461 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
3462 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
3464 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
3465 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONUP on a button", FALSE);
3466 DestroyWindow(hwnd);
3469 /************* painting message test ********************/
3471 void dump_region(HRGN hrgn)
3474 RGNDATA *data = NULL;
3479 printf( "null region\n" );
3482 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
3483 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
3484 GetRegionData( hrgn, size, data );
3485 printf("%ld rects:", data->rdh.nCount );
3486 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
3487 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
3489 HeapFree( GetProcessHeap(), 0, data );
3492 static void check_update_rgn( HWND hwnd, HRGN hrgn )
3496 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
3497 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
3499 ret = GetUpdateRgn( hwnd, update, FALSE );
3500 ok( ret != ERROR, "GetUpdateRgn failed\n" );
3501 if (ret == NULLREGION)
3503 ok( !hrgn, "Update region shouldn't be empty\n" );
3507 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
3509 ok( 0, "Regions are different\n" );
3510 if (winetest_debug > 0)
3512 printf( "Update region: " );
3513 dump_region( update );
3514 printf( "Wanted region: " );
3515 dump_region( hrgn );
3519 GetRgnBox( update, &r1 );
3520 GetUpdateRect( hwnd, &r2, FALSE );
3521 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
3522 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
3523 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
3525 DeleteObject( tmp );
3526 DeleteObject( update );
3529 static const struct message WmInvalidateRgn[] = {
3530 { WM_NCPAINT, sent },
3531 { WM_GETTEXT, sent|defwinproc|optional },
3535 static const struct message WmGetUpdateRect[] = {
3536 { WM_NCPAINT, sent },
3537 { WM_GETTEXT, sent|defwinproc|optional },
3542 static const struct message WmInvalidateFull[] = {
3543 { WM_NCPAINT, sent|wparam, 1 },
3544 { WM_GETTEXT, sent|defwinproc|optional },
3548 static const struct message WmInvalidateErase[] = {
3549 { WM_NCPAINT, sent|wparam, 1 },
3550 { WM_GETTEXT, sent|defwinproc|optional },
3551 { WM_ERASEBKGND, sent },
3555 static const struct message WmInvalidatePaint[] = {
3557 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3558 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3562 static const struct message WmInvalidateErasePaint[] = {
3564 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3565 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3566 { WM_ERASEBKGND, sent|beginpaint },
3570 static const struct message WmInvalidateErasePaint2[] = {
3572 { WM_NCPAINT, sent|beginpaint },
3573 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3574 { WM_ERASEBKGND, sent|beginpaint },
3578 static const struct message WmErase[] = {
3579 { WM_ERASEBKGND, sent },
3583 static const struct message WmPaint[] = {
3588 static const struct message WmParentOnlyPaint[] = {
3589 { WM_PAINT, sent|parent },
3593 static const struct message WmInvalidateParent[] = {
3594 { WM_NCPAINT, sent|parent },
3595 { WM_GETTEXT, sent|defwinproc|parent|optional },
3596 { WM_ERASEBKGND, sent|parent },
3600 static const struct message WmInvalidateParentChild[] = {
3601 { WM_NCPAINT, sent|parent },
3602 { WM_GETTEXT, sent|defwinproc|parent|optional },
3603 { WM_ERASEBKGND, sent|parent },
3604 { WM_NCPAINT, sent },
3605 { WM_GETTEXT, sent|defwinproc|optional },
3606 { WM_ERASEBKGND, sent },
3610 static const struct message WmInvalidateParentChild2[] = {
3611 { WM_ERASEBKGND, sent|parent },
3612 { WM_NCPAINT, sent },
3613 { WM_GETTEXT, sent|defwinproc|optional },
3614 { WM_ERASEBKGND, sent },
3618 static const struct message WmParentPaint[] = {
3619 { WM_PAINT, sent|parent },
3624 static const struct message WmParentPaintNc[] = {
3625 { WM_PAINT, sent|parent },
3627 { WM_NCPAINT, sent|beginpaint },
3628 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3629 { WM_ERASEBKGND, sent|beginpaint },
3633 static const struct message WmChildPaintNc[] = {
3635 { WM_NCPAINT, sent|beginpaint },
3636 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3637 { WM_ERASEBKGND, sent|beginpaint },
3641 static const struct message WmParentErasePaint[] = {
3642 { WM_PAINT, sent|parent },
3643 { WM_NCPAINT, sent|parent|beginpaint },
3644 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3645 { WM_ERASEBKGND, sent|parent|beginpaint },
3647 { WM_NCPAINT, sent|beginpaint },
3648 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3649 { WM_ERASEBKGND, sent|beginpaint },
3653 static const struct message WmParentOnlyNcPaint[] = {
3654 { WM_PAINT, sent|parent },
3655 { WM_NCPAINT, sent|parent|beginpaint },
3656 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3660 static const struct message WmSetParentStyle[] = {
3661 { WM_STYLECHANGING, sent|parent },
3662 { WM_STYLECHANGED, sent|parent },
3666 static void test_paint_messages(void)
3671 HWND hparent, hchild;
3672 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
3673 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
3674 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3675 100, 100, 200, 200, 0, 0, 0, NULL);
3676 ok (hwnd != 0, "Failed to create overlapped window\n");
3678 ShowWindow( hwnd, SW_SHOW );
3679 UpdateWindow( hwnd );
3681 /* try to flush pending X expose events */
3682 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3683 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3685 check_update_rgn( hwnd, 0 );
3686 SetRectRgn( hrgn, 10, 10, 20, 20 );
3687 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3688 check_update_rgn( hwnd, hrgn );
3689 SetRectRgn( hrgn2, 20, 20, 30, 30 );
3690 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
3691 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
3692 check_update_rgn( hwnd, hrgn );
3693 /* validate everything */
3694 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3695 check_update_rgn( hwnd, 0 );
3696 /* now with frame */
3697 SetRectRgn( hrgn, -5, -5, 20, 20 );
3699 /* flush pending messages */
3700 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3703 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3704 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3706 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
3707 check_update_rgn( hwnd, hrgn );
3710 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3711 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3714 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3715 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
3717 GetClientRect( hwnd, &rect );
3718 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
3719 check_update_rgn( hwnd, hrgn );
3722 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
3723 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3726 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
3727 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
3728 check_update_rgn( hwnd, 0 );
3731 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
3732 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
3733 check_update_rgn( hwnd, 0 );
3736 SetRectRgn( hrgn, 0, 0, 100, 100 );
3737 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3738 SetRectRgn( hrgn, 0, 0, 50, 100 );
3739 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
3740 SetRectRgn( hrgn, 50, 0, 100, 100 );
3741 check_update_rgn( hwnd, hrgn );
3742 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3743 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
3744 check_update_rgn( hwnd, 0 );
3747 SetRectRgn( hrgn, 0, 0, 100, 100 );
3748 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3749 SetRectRgn( hrgn, 0, 0, 100, 50 );
3750 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3751 ok_sequence( WmErase, "Erase", FALSE );
3752 SetRectRgn( hrgn, 0, 50, 100, 100 );
3753 check_update_rgn( hwnd, hrgn );
3756 SetRectRgn( hrgn, 0, 0, 100, 100 );
3757 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3758 SetRectRgn( hrgn, 0, 0, 50, 50 );
3759 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
3760 ok_sequence( WmPaint, "Paint", FALSE );
3763 SetRectRgn( hrgn, -4, -4, -2, -2 );
3764 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3765 SetRectRgn( hrgn, -200, -200, -198, -198 );
3766 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
3767 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3770 SetRectRgn( hrgn, -4, -4, -2, -2 );
3771 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3772 SetRectRgn( hrgn, -4, -4, -3, -3 );
3773 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
3774 SetRectRgn( hrgn, 0, 0, 1, 1 );
3775 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
3776 ok_sequence( WmPaint, "Paint", FALSE );
3779 SetRectRgn( hrgn, -4, -4, -1, -1 );
3780 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3781 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
3782 /* make sure no WM_PAINT was generated */
3783 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3784 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3787 SetRectRgn( hrgn, -4, -4, -1, -1 );
3788 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3789 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
3791 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
3793 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
3794 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
3795 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
3796 ret = GetUpdateRect( hwnd, &rect, FALSE );
3797 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
3798 /* this will send WM_NCPAINT and validate the non client area */
3799 ret = GetUpdateRect( hwnd, &rect, TRUE );
3800 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
3802 DispatchMessage( &msg );
3804 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
3806 DestroyWindow( hwnd );
3808 /* now test with a child window */
3810 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
3811 100, 100, 200, 200, 0, 0, 0, NULL);
3812 ok (hparent != 0, "Failed to create parent window\n");
3814 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
3815 10, 10, 100, 100, hparent, 0, 0, NULL);
3816 ok (hchild != 0, "Failed to create child window\n");
3818 ShowWindow( hparent, SW_SHOW );
3819 UpdateWindow( hparent );
3820 UpdateWindow( hchild );
3821 /* try to flush pending X expose events */
3822 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3823 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3826 log_all_parent_messages++;
3828 SetRect( &rect, 0, 0, 50, 50 );
3829 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3830 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3831 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
3833 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3835 MapWindowPoints( hchild, hparent, &pt, 1 );
3836 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
3837 check_update_rgn( hchild, hrgn );
3838 SetRectRgn( hrgn, 0, 0, 50, 50 );
3839 check_update_rgn( hparent, hrgn );
3840 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3841 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
3842 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3843 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3845 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3846 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
3848 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3849 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3850 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
3851 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3852 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3854 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
3855 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3856 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
3858 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3860 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3861 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3862 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
3864 /* flush all paint messages */
3865 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3868 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
3869 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3870 SetRectRgn( hrgn, 0, 0, 50, 50 );
3871 check_update_rgn( hparent, hrgn );
3872 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3873 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3874 SetRectRgn( hrgn, 0, 0, 50, 50 );
3875 check_update_rgn( hparent, hrgn );
3877 /* flush all paint messages */
3878 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3879 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3882 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
3883 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3884 SetRectRgn( hrgn, 0, 0, 50, 50 );
3885 check_update_rgn( hparent, hrgn );
3886 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3887 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3888 SetRectRgn( hrgn2, 10, 10, 50, 50 );
3889 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
3890 check_update_rgn( hparent, hrgn );
3891 /* flush all paint messages */
3892 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3895 /* same as above but parent gets completely validated */
3896 SetRect( &rect, 20, 20, 30, 30 );
3897 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3898 SetRectRgn( hrgn, 20, 20, 30, 30 );
3899 check_update_rgn( hparent, hrgn );
3900 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3901 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3902 check_update_rgn( hparent, 0 ); /* no update region */
3903 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3904 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
3906 /* make sure RDW_VALIDATE on child doesn't have the same effect */
3908 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3909 SetRectRgn( hrgn, 20, 20, 30, 30 );
3910 check_update_rgn( hparent, hrgn );
3911 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
3912 SetRectRgn( hrgn, 20, 20, 30, 30 );
3913 check_update_rgn( hparent, hrgn );
3915 /* same as above but normal WM_PAINT doesn't validate parent */
3917 SetRect( &rect, 20, 20, 30, 30 );
3918 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3919 SetRectRgn( hrgn, 20, 20, 30, 30 );
3920 check_update_rgn( hparent, hrgn );
3921 /* no WM_PAINT in child while parent still pending */
3922 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3923 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3924 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3925 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
3928 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3929 /* no WM_PAINT in child while parent still pending */
3930 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3931 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3932 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
3933 /* now that parent is valid child should get WM_PAINT */
3934 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3935 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3936 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3937 ok_sequence( WmEmptySeq, "No other message", FALSE );
3939 /* same thing with WS_CLIPCHILDREN in parent */
3941 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3942 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3943 /* changing style invalidates non client area, but we need to invalidate something else to see it */
3944 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
3945 ok_sequence( WmEmptySeq, "No message", FALSE );
3946 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
3947 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
3950 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
3951 SetRectRgn( hrgn, 20, 20, 30, 30 );
3952 check_update_rgn( hparent, hrgn );
3953 /* no WM_PAINT in child while parent still pending */
3954 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3955 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3956 /* WM_PAINT in parent first */
3957 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3958 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
3960 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
3962 SetRect( &rect, 0, 0, 30, 30 );
3963 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
3964 SetRectRgn( hrgn, 0, 0, 30, 30 );
3965 check_update_rgn( hparent, hrgn );
3966 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3967 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
3969 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3971 SetRect( &rect, -10, 0, 30, 30 );
3972 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3973 SetRect( &rect, 0, 0, 20, 20 );
3974 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3975 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3976 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
3978 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3980 SetRect( &rect, -10, 0, 30, 30 );
3981 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3982 SetRect( &rect, 0, 0, 100, 100 );
3983 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3984 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3985 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
3986 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3987 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
3989 /* test RDW_INTERNALPAINT behavior */
3992 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
3993 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3994 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3996 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
3997 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3998 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
4000 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
4001 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4002 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
4004 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
4005 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
4006 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
4007 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4008 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
4010 log_all_parent_messages--;
4011 DestroyWindow( hparent );
4012 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
4014 DeleteObject( hrgn );
4015 DeleteObject( hrgn2 );
4024 static DWORD WINAPI thread_proc(void *param)
4027 struct wnd_event *wnd_event = (struct wnd_event *)param;
4029 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
4030 100, 100, 200, 200, 0, 0, 0, NULL);
4031 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
4033 SetEvent(wnd_event->event);
4035 while (GetMessage(&msg, 0, 0, 0))
4037 TranslateMessage(&msg);
4038 DispatchMessage(&msg);
4041 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
4046 static void test_interthread_messages(void)
4053 int len, expected_len;
4054 struct wnd_event wnd_event;
4057 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
4058 if (!wnd_event.event)
4060 trace("skipping interthread message test under win9x\n");
4064 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
4065 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4067 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4069 CloseHandle(wnd_event.event);
4071 SetLastError(0xdeadbeef);
4072 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
4073 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
4075 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
4076 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
4078 expected_len = lstrlenA("window caption text");
4079 memset(buf, 0, sizeof(buf));
4080 SetLastError(0xdeadbeef);
4081 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
4082 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
4083 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
4085 msg.hwnd = wnd_event.hwnd;
4086 msg.message = WM_GETTEXT;
4087 msg.wParam = sizeof(buf);
4088 msg.lParam = (LPARAM)buf;
4089 memset(buf, 0, sizeof(buf));
4090 SetLastError(0xdeadbeef);
4091 len = DispatchMessageA(&msg);
4092 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4093 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
4095 /* the following test causes an exception in user.exe under win9x */
4096 msg.hwnd = wnd_event.hwnd;
4097 msg.message = WM_TIMER;
4099 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
4100 SetLastError(0xdeadbeef);
4101 len = DispatchMessageA(&msg);
4102 ok(!len && GetLastError() == 0xdeadbeef,
4103 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
4105 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
4106 ok( ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4108 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4109 CloseHandle(hThread);
4111 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
4115 static const struct message WmVkN[] = {
4116 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4117 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4118 { WM_CHAR, wparam|lparam, 'n', 1 },
4119 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
4120 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4121 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4124 static const struct message WmShiftVkN[] = {
4125 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
4126 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
4127 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4128 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4129 { WM_CHAR, wparam|lparam, 'N', 1 },
4130 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
4131 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4132 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4133 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
4134 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
4137 static const struct message WmCtrlVkN[] = {
4138 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4139 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4140 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4141 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4142 { WM_CHAR, wparam|lparam, 0x000e, 1 },
4143 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
4144 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4145 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4146 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4147 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4150 static const struct message WmCtrlVkN_2[] = {
4151 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4152 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4153 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4154 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
4155 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4156 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4157 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4158 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4161 static const struct message WmAltVkN[] = {
4162 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4163 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4164 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
4165 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
4166 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
4167 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
4168 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
4169 { HCBT_SYSCOMMAND, hook },
4170 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4171 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4172 { WM_INITMENU, sent|defwinproc },
4173 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4174 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
4175 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
4176 { WM_CAPTURECHANGED, sent|defwinproc },
4177 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
4178 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4179 { WM_EXITMENULOOP, sent|defwinproc },
4180 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
4181 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
4182 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4183 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4184 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4185 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4188 static const struct message WmAltVkN_2[] = {
4189 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4190 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4191 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
4192 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
4193 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4194 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4195 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4196 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4199 static const struct message WmCtrlAltVkN[] = {
4200 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4201 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4202 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4203 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4204 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
4205 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
4206 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
4207 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4208 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4209 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4210 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4211 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4214 static const struct message WmCtrlShiftVkN[] = {
4215 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4216 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4217 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
4218 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
4219 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4220 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 },
4221 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4222 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4223 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
4224 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
4225 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4226 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4229 static const struct message WmCtrlAltShiftVkN[] = {
4230 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4231 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4232 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4233 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4234 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 },
4235 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 },
4236 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
4237 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 },
4238 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
4239 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4240 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 },
4241 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 },
4242 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4243 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4244 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4245 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4248 static const struct message WmAltPressRelease[] = {
4249 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4250 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4251 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4252 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4253 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 },
4254 { HCBT_SYSCOMMAND, hook },
4255 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4256 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4257 { WM_INITMENU, sent|defwinproc },
4258 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4259 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE) },
4260 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4262 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4263 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
4264 { WM_CAPTURECHANGED, sent|defwinproc },
4265 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) },
4266 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4267 { WM_EXITMENULOOP, sent|defwinproc },
4268 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4269 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4272 static const struct message WmAltMouseButton[] = {
4273 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4274 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4275 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
4276 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
4277 { WM_LBUTTONDOWN, wparam, MK_LBUTTON, 0 },
4278 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON, 0 },
4279 { WM_LBUTTONUP, wparam, 0, 0 },
4280 { WM_LBUTTONUP, sent|wparam, 0, 0 },
4281 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4282 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4286 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
4290 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
4292 struct message log_msg;
4294 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
4296 /* ignore some unwanted messages */
4297 if (msg.message == WM_MOUSEMOVE ||
4298 msg.message == WM_DEVICECHANGE)
4301 log_msg.message = msg.message;
4302 log_msg.flags = wparam|lparam;
4303 log_msg.wParam = msg.wParam;
4304 log_msg.lParam = msg.lParam;
4305 add_message(&log_msg);
4307 if (!hAccel || !TranslateAccelerator(hwnd, hAccel, &msg))
4309 TranslateMessage(&msg);
4310 DispatchMessage(&msg);
4315 static void test_accelerators(void)
4320 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4321 100, 100, 200, 200, 0, 0, 0, NULL);
4327 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
4329 state = GetKeyState(VK_SHIFT);
4330 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
4331 state = GetKeyState(VK_CAPITAL);
4332 ok(state == 0, "wrong CapsLock state %04x\n", state);
4334 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
4335 assert(hAccel != 0);
4337 pump_msg_loop(hwnd, 0);
4340 trace("testing VK_N press/release\n");
4342 keybd_event('N', 0, 0, 0);
4343 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4344 pump_msg_loop(hwnd, hAccel);
4345 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4347 trace("testing Shift+VK_N press/release\n");
4349 keybd_event(VK_SHIFT, 0, 0, 0);
4350 keybd_event('N', 0, 0, 0);
4351 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4352 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4353 pump_msg_loop(hwnd, hAccel);
4354 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4356 trace("testing Ctrl+VK_N press/release\n");
4358 keybd_event(VK_CONTROL, 0, 0, 0);
4359 keybd_event('N', 0, 0, 0);
4360 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4361 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4362 pump_msg_loop(hwnd, hAccel);
4363 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
4365 trace("testing Alt+VK_N press/release\n");
4367 keybd_event(VK_MENU, 0, 0, 0);
4368 keybd_event('N', 0, 0, 0);
4369 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4370 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4371 pump_msg_loop(hwnd, hAccel);
4372 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
4374 trace("testing Ctrl+Alt+VK_N press/release 1\n");
4376 keybd_event(VK_CONTROL, 0, 0, 0);
4377 keybd_event(VK_MENU, 0, 0, 0);
4378 keybd_event('N', 0, 0, 0);
4379 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4380 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4381 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4382 pump_msg_loop(hwnd, hAccel);
4383 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
4385 ret = DestroyAcceleratorTable(hAccel);
4386 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4388 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
4389 assert(hAccel != 0);
4391 trace("testing VK_N press/release\n");
4393 keybd_event('N', 0, 0, 0);
4394 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4395 pump_msg_loop(hwnd, hAccel);
4396 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4398 trace("testing Shift+VK_N press/release\n");
4400 keybd_event(VK_SHIFT, 0, 0, 0);
4401 keybd_event('N', 0, 0, 0);
4402 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4403 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4404 pump_msg_loop(hwnd, hAccel);
4405 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4407 trace("testing Ctrl+VK_N press/release 2\n");
4409 keybd_event(VK_CONTROL, 0, 0, 0);
4410 keybd_event('N', 0, 0, 0);
4411 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4412 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4413 pump_msg_loop(hwnd, hAccel);
4414 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
4416 trace("testing Alt+VK_N press/release 2\n");
4418 keybd_event(VK_MENU, 0, 0, 0);
4419 keybd_event('N', 0, 0, 0);
4420 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4421 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4422 pump_msg_loop(hwnd, hAccel);
4423 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
4425 trace("testing Ctrl+Alt+VK_N press/release 2\n");
4427 keybd_event(VK_CONTROL, 0, 0, 0);
4428 keybd_event(VK_MENU, 0, 0, 0);
4429 keybd_event('N', 0, 0, 0);
4430 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4431 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4432 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4433 pump_msg_loop(hwnd, hAccel);
4434 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
4436 trace("testing Ctrl+Shift+VK_N press/release\n");
4438 keybd_event(VK_CONTROL, 0, 0, 0);
4439 keybd_event(VK_SHIFT, 0, 0, 0);
4440 keybd_event('N', 0, 0, 0);
4441 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4442 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4443 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4444 pump_msg_loop(hwnd, hAccel);
4445 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE);
4447 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
4449 keybd_event(VK_CONTROL, 0, 0, 0);
4450 keybd_event(VK_MENU, 0, 0, 0);
4451 keybd_event(VK_SHIFT, 0, 0, 0);
4452 keybd_event('N', 0, 0, 0);
4453 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4454 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4455 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4456 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4457 pump_msg_loop(hwnd, hAccel);
4458 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE);
4460 ret = DestroyAcceleratorTable(hAccel);
4461 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4463 trace("testing Alt press/release\n");
4465 keybd_event(VK_MENU, 0, 0, 0);
4466 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4467 keybd_event(VK_MENU, 0, 0, 0);
4468 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4469 pump_msg_loop(hwnd, 0);
4470 /* this test doesn't pass in Wine for managed windows */
4471 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
4473 trace("testing Alt+MouseButton press/release\n");
4474 /* first, move mouse pointer inside of the window client area */
4475 GetClientRect(hwnd, &rc);
4476 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
4477 rc.left += (rc.right - rc.left)/2;
4478 rc.top += (rc.bottom - rc.top)/2;
4479 SetCursorPos(rc.left, rc.top);
4481 pump_msg_loop(hwnd, 0);
4483 keybd_event(VK_MENU, 0, 0, 0);
4484 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
4485 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
4486 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4487 pump_msg_loop(hwnd, 0);
4488 ok_sequence(WmAltMouseButton, "Alt+MouseButton press/release", FALSE);
4490 DestroyWindow(hwnd);
4493 /************* window procedures ********************/
4495 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4497 static long defwndproc_counter = 0;
4498 static long beginpaint_counter = 0;
4502 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4508 LONG style = GetWindowLongA(hwnd, GWL_STYLE);
4509 ok((BOOL)wParam == !(style & WS_DISABLED),
4510 "wrong WS_DISABLED state: %d != %d\n", wParam, !(style & WS_DISABLED));
4514 case WM_CAPTURECHANGED:
4515 if (test_DestroyWindow_flag)
4517 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
4518 if (style & WS_CHILD)
4519 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
4520 else if (style & WS_POPUP)
4521 lParam = WND_POPUP_ID;
4523 lParam = WND_PARENT_ID;
4531 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
4532 capture = GetCapture();
4535 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture);
4536 trace("current capture %p, releasing...\n", capture);
4543 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n");
4544 if (test_DestroyWindow_flag)
4546 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
4547 if (style & WS_CHILD)
4548 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
4549 else if (style & WS_POPUP)
4550 lParam = WND_POPUP_ID;
4552 lParam = WND_PARENT_ID;
4556 /* test_accelerators() depends on this */
4563 case WM_DEVICECHANGE:
4566 case WM_WINDOWPOSCHANGING:
4567 case WM_WINDOWPOSCHANGED:
4569 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4571 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4572 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4573 winpos->hwnd, winpos->hwndInsertAfter,
4574 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4576 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4577 * in the high word for internal purposes
4579 wParam = winpos->flags & 0xffff;
4584 msg.message = message;
4585 msg.flags = sent|wparam|lparam;
4586 if (defwndproc_counter) msg.flags |= defwinproc;
4587 if (beginpaint_counter) msg.flags |= beginpaint;
4588 msg.wParam = wParam;
4589 msg.lParam = lParam;
4592 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
4594 HWND parent = GetParent(hwnd);
4596 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
4598 GetClientRect(parent, &rc);
4599 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
4601 trace("ptReserved = (%ld,%ld)\n"
4602 "ptMaxSize = (%ld,%ld)\n"
4603 "ptMaxPosition = (%ld,%ld)\n"
4604 "ptMinTrackSize = (%ld,%ld)\n"
4605 "ptMaxTrackSize = (%ld,%ld)\n",
4606 minmax->ptReserved.x, minmax->ptReserved.y,
4607 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
4608 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
4609 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
4610 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
4612 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
4613 minmax->ptMaxSize.x, rc.right);
4614 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
4615 minmax->ptMaxSize.y, rc.bottom);
4618 if (message == WM_PAINT)
4621 beginpaint_counter++;
4622 BeginPaint( hwnd, &ps );
4623 beginpaint_counter--;
4624 EndPaint( hwnd, &ps );
4628 defwndproc_counter++;
4629 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4630 defwndproc_counter--;
4635 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4637 static long defwndproc_counter = 0;
4641 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4643 msg.message = message;
4644 msg.flags = sent|wparam|lparam;
4645 if (defwndproc_counter) msg.flags |= defwinproc;
4646 msg.wParam = wParam;
4647 msg.lParam = lParam;
4650 if (message == WM_CREATE)
4652 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
4653 SetWindowLongA(hwnd, GWL_STYLE, style);
4656 defwndproc_counter++;
4657 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4658 defwndproc_counter--;
4663 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4665 static long defwndproc_counter = 0;
4666 static long beginpaint_counter = 0;
4670 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4672 if (log_all_parent_messages ||
4673 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
4674 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
4675 message == WM_ENABLE || message == WM_ENTERIDLE ||
4676 message == WM_IME_SETCONTEXT)
4678 msg.message = message;
4679 msg.flags = sent|parent|wparam|lparam;
4680 if (defwndproc_counter) msg.flags |= defwinproc;
4681 if (beginpaint_counter) msg.flags |= beginpaint;
4682 msg.wParam = wParam;
4683 msg.lParam = lParam;
4687 if (message == WM_PAINT)
4690 beginpaint_counter++;
4691 BeginPaint( hwnd, &ps );
4692 beginpaint_counter--;
4693 EndPaint( hwnd, &ps );
4697 defwndproc_counter++;
4698 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4699 defwndproc_counter--;
4704 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4706 static long defwndproc_counter = 0;
4710 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4712 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
4713 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4714 if (after_end_dialog)
4715 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
4717 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
4721 case WM_WINDOWPOSCHANGING:
4722 case WM_WINDOWPOSCHANGED:
4724 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4726 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4727 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4728 winpos->hwnd, winpos->hwndInsertAfter,
4729 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4731 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4732 * in the high word for internal purposes
4734 wParam = winpos->flags & 0xffff;
4739 msg.message = message;
4740 msg.flags = sent|wparam|lparam;
4741 if (defwndproc_counter) msg.flags |= defwinproc;
4742 msg.wParam = wParam;
4743 msg.lParam = lParam;
4746 defwndproc_counter++;
4747 ret = DefDlgProcA(hwnd, message, wParam, lParam);
4748 defwndproc_counter--;
4753 static BOOL RegisterWindowClasses(void)
4758 cls.lpfnWndProc = MsgCheckProcA;
4761 cls.hInstance = GetModuleHandleA(0);
4763 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
4764 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4765 cls.lpszMenuName = NULL;
4766 cls.lpszClassName = "TestWindowClass";
4767 if(!RegisterClassA(&cls)) return FALSE;
4769 cls.lpfnWndProc = PopupMsgCheckProcA;
4770 cls.lpszClassName = "TestPopupClass";
4771 if(!RegisterClassA(&cls)) return FALSE;
4773 cls.lpfnWndProc = ParentMsgCheckProcA;
4774 cls.lpszClassName = "TestParentClass";
4775 if(!RegisterClassA(&cls)) return FALSE;
4777 cls.lpfnWndProc = DefWindowProcA;
4778 cls.lpszClassName = "SimpleWindowClass";
4779 if(!RegisterClassA(&cls)) return FALSE;
4781 cls.style = CS_NOCLOSE;
4782 cls.lpszClassName = "NoCloseWindowClass";
4783 if(!RegisterClassA(&cls)) return FALSE;
4785 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
4787 cls.hInstance = GetModuleHandleA(0);
4788 cls.hbrBackground = 0;
4789 cls.lpfnWndProc = TestDlgProcA;
4790 cls.lpszClassName = "TestDialogClass";
4791 if(!RegisterClassA(&cls)) return FALSE;
4796 static HHOOK hCBT_hook;
4797 static DWORD cbt_hook_thread_id;
4799 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
4801 static const char *CBT_code_name[10] = {
4808 "HCBT_CLICKSKIPPED",
4812 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
4816 trace("CBT: %d (%s), %08x, %08lx\n", nCode, code_name, wParam, lParam);
4818 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
4820 if (nCode == HCBT_SYSCOMMAND)
4824 msg.message = nCode;
4825 msg.flags = hook|wparam|lparam;
4826 msg.wParam = wParam;
4827 msg.lParam = lParam;
4830 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
4833 if (nCode == HCBT_DESTROYWND)
4835 if (test_DestroyWindow_flag)
4837 DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE);
4838 if (style & WS_CHILD)
4839 lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID);
4840 else if (style & WS_POPUP)
4841 lParam = WND_POPUP_ID;
4843 lParam = WND_PARENT_ID;
4847 /* Log also SetFocus(0) calls */
4848 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
4850 if (GetClassNameA(hwnd, buf, sizeof(buf)))
4852 if (!lstrcmpiA(buf, "TestWindowClass") ||
4853 !lstrcmpiA(buf, "TestParentClass") ||
4854 !lstrcmpiA(buf, "TestPopupClass") ||
4855 !lstrcmpiA(buf, "SimpleWindowClass") ||
4856 !lstrcmpiA(buf, "TestDialogClass") ||
4857 !lstrcmpiA(buf, "MDI_frame_class") ||
4858 !lstrcmpiA(buf, "MDI_client_class") ||
4859 !lstrcmpiA(buf, "MDI_child_class") ||
4860 !lstrcmpiA(buf, "my_button_class") ||
4861 !lstrcmpiA(buf, "static") ||
4862 !lstrcmpiA(buf, "#32770"))
4866 msg.message = nCode;
4867 msg.flags = hook|wparam|lparam;
4868 msg.wParam = wParam;
4869 msg.lParam = lParam;
4873 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
4876 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
4886 trace("WEH:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
4887 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
4889 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
4891 /* ignore mouse cursor events */
4892 if (object_id == OBJID_CURSOR) return;
4894 if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf)))
4897 !lstrcmpiA(buf, "TestWindowClass") ||
4898 !lstrcmpiA(buf, "TestParentClass") ||
4899 !lstrcmpiA(buf, "TestPopupClass") ||
4900 !lstrcmpiA(buf, "SimpleWindowClass") ||
4901 !lstrcmpiA(buf, "TestDialogClass") ||
4902 !lstrcmpiA(buf, "MDI_frame_class") ||
4903 !lstrcmpiA(buf, "MDI_client_class") ||
4904 !lstrcmpiA(buf, "MDI_child_class") ||
4905 !lstrcmpiA(buf, "my_button_class") ||
4906 !lstrcmpiA(buf, "static") ||
4907 !lstrcmpiA(buf, "#32770"))
4911 msg.message = event;
4912 msg.flags = winevent_hook|wparam|lparam;
4913 msg.wParam = object_id;
4914 msg.lParam = child_id;
4920 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
4921 static const WCHAR wszAnsi[] = {'U',0};
4923 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4927 case CB_FINDSTRINGEXACT:
4928 trace("String: %p\n", (LPCWSTR)lParam);
4929 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
4931 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
4935 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
4938 static void test_message_conversion(void)
4940 static const WCHAR wszMsgConversionClass[] =
4941 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
4948 cls.lpfnWndProc = MsgConversionProcW;
4951 cls.hInstance = GetModuleHandleW(NULL);
4953 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
4954 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
4955 cls.lpszMenuName = NULL;
4956 cls.lpszClassName = wszMsgConversionClass;
4957 /* this call will fail on Win9x, but that doesn't matter as this test is
4958 * meaningless on those platforms */
4959 if(!RegisterClassW(&cls)) return;
4961 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
4962 100, 100, 200, 200, 0, 0, 0, NULL);
4963 ok(hwnd != NULL, "Window creation failed\n");
4967 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
4968 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4969 ok(lRes == 0, "String should have been converted\n");
4970 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4971 ok(lRes == 1, "String shouldn't have been converted\n");
4975 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
4976 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4977 ok(lRes == 1, "String shouldn't have been converted\n");
4978 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4979 ok(lRes == 1, "String shouldn't have been converted\n");
4981 /* Synchronous messages */
4983 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4984 ok(lRes == 0, "String should have been converted\n");
4985 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4986 ok(lRes == 1, "String shouldn't have been converted\n");
4988 /* Asynchronous messages */
4991 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4992 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
4993 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4995 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4996 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
4997 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4999 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5000 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5001 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5003 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5004 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5005 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5007 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5008 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5009 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5011 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5012 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5013 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5015 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
5016 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5017 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5019 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
5020 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5021 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5024 typedef struct _thread_info
5031 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
5035 #define TIMER_ID 0x19
5037 static DWORD WINAPI timer_thread_proc(LPVOID x)
5039 thread_info *info = x;
5042 r = KillTimer(info->hWnd, 0x19);
5043 ok(r,"KillTimer failed in thread\n");
5044 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
5045 ok(r,"SetTimer failed in thread\n");
5046 ok(r==TIMER_ID,"SetTimer id different\n");
5047 r = SetEvent(info->handles[0]);
5048 ok(r,"SetEvent failed in thread\n");
5052 static void test_timers(void)
5057 info.hWnd = CreateWindow ("TestWindowClass", NULL,
5058 WS_OVERLAPPEDWINDOW ,
5059 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5062 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
5063 ok(info.id, "SetTimer failed\n");
5064 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
5065 info.handles[0] = CreateEvent(NULL,0,0,NULL);
5066 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
5068 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
5070 WaitForSingleObject(info.handles[1], INFINITE);
5072 CloseHandle(info.handles[0]);
5073 CloseHandle(info.handles[1]);
5075 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
5077 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
5080 /* Various win events with arbitrary parameters */
5081 static const struct message WmWinEventsSeq[] = {
5082 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
5083 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
5084 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
5085 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
5086 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
5087 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
5088 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
5089 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
5090 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
5091 /* our win event hook ignores OBJID_CURSOR events */
5092 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
5093 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
5094 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
5095 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
5096 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
5097 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
5098 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
5099 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
5100 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
5101 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
5102 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
5103 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
5104 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
5105 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
5108 static const struct message WmWinEventCaretSeq[] = {
5109 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5110 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5111 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */
5112 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5115 static const struct message WmWinEventCaretSeq_2[] = {
5116 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5117 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5118 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5121 static const struct message WmWinEventAlertSeq[] = {
5122 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 },
5125 static const struct message WmWinEventAlertSeq_2[] = {
5126 /* create window in the thread proc */
5127 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 },
5128 /* our test event */
5129 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 },
5132 static const struct message WmGlobalHookSeq_1[] = {
5133 /* create window in the thread proc */
5134 { HCBT_CREATEWND, hook|lparam, 0, 2 },
5135 /* our test events */
5136 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 },
5137 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 },
5140 static const struct message WmGlobalHookSeq_2[] = {
5141 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */
5142 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */
5143 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */
5144 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */
5148 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent,
5158 trace("WEH_2:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
5159 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
5161 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5163 if (!lstrcmpiA(buf, "TestWindowClass") ||
5164 !lstrcmpiA(buf, "static"))
5168 msg.message = event;
5169 msg.flags = winevent_hook|wparam|lparam;
5170 msg.wParam = object_id;
5171 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2);
5177 static HHOOK hCBT_global_hook;
5178 static DWORD cbt_global_hook_thread_id;
5180 static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
5185 trace("CBT_2: %d, %08x, %08lx\n", nCode, wParam, lParam);
5187 if (nCode == HCBT_SYSCOMMAND)
5191 msg.message = nCode;
5192 msg.flags = hook|wparam|lparam;
5193 msg.wParam = wParam;
5194 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
5197 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
5200 /* Log also SetFocus(0) calls */
5201 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
5203 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5205 if (!lstrcmpiA(buf, "TestWindowClass") ||
5206 !lstrcmpiA(buf, "static"))
5210 msg.message = nCode;
5211 msg.flags = hook|wparam|lparam;
5212 msg.wParam = wParam;
5213 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
5217 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
5220 static DWORD WINAPI win_event_global_thread_proc(void *param)
5224 HANDLE hevent = *(HANDLE *)param;
5225 HMODULE user32 = GetModuleHandleA("user32.dll");
5226 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
5228 assert(pNotifyWinEvent);
5230 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
5232 trace("created thread window %p\n", hwnd);
5234 *(HWND *)param = hwnd;
5237 /* this event should be received only by our new hook proc,
5238 * an old one does not expect an event from another thread.
5240 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0);
5243 while (GetMessage(&msg, 0, 0, 0))
5245 TranslateMessage(&msg);
5246 DispatchMessage(&msg);
5251 static DWORD WINAPI cbt_global_hook_thread_proc(void *param)
5255 HANDLE hevent = *(HANDLE *)param;
5258 /* these events should be received only by our new hook proc,
5259 * an old one does not expect an event from another thread.
5262 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
5264 trace("created thread window %p\n", hwnd);
5266 *(HWND *)param = hwnd;
5268 /* Windows doesn't like when a thread plays games with the focus,
5269 that leads to all kinds of misbehaviours and failures to activate
5270 a window. So, better keep next lines commented out.
5274 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
5275 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
5279 while (GetMessage(&msg, 0, 0, 0))
5281 TranslateMessage(&msg);
5282 DispatchMessage(&msg);
5287 static void test_winevents(void)
5293 HANDLE hthread, hevent;
5295 HWINEVENTHOOK hhook;
5296 const struct message *events = WmWinEventsSeq;
5297 HMODULE user32 = GetModuleHandleA("user32.dll");
5298 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
5299 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
5300 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
5302 hwnd = CreateWindowExA(0, "TestWindowClass", NULL,
5303 WS_OVERLAPPEDWINDOW,
5304 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5308 /****** start of global hook test *************/
5309 hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0);
5310 assert(hCBT_global_hook);
5312 hevent = CreateEventA(NULL, 0, 0, NULL);
5314 hwnd2 = (HWND)hevent;
5316 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid);
5317 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5319 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5321 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
5324 /* this one should be received only by old hook proc */
5325 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
5326 /* this one should be received only by old hook proc */
5327 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
5329 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
5331 ret = UnhookWindowsHookEx(hCBT_global_hook);
5332 ok( ret, "UnhookWindowsHookEx error %ld\n", GetLastError());
5334 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5335 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5336 CloseHandle(hthread);
5337 CloseHandle(hevent);
5338 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5339 /****** end of global hook test *************/
5341 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent)
5343 ok(DestroyWindow(hwnd), "failed to destroy window\n");
5349 #if 0 /* this test doesn't pass under Win9x */
5350 /* win2k ignores events with hwnd == 0 */
5351 SetLastError(0xdeadbeef);
5352 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
5353 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
5354 GetLastError() == 0xdeadbeef, /* Win9x */
5355 "unexpected error %ld\n", GetLastError());
5356 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
5359 for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
5360 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
5362 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
5364 /****** start of event filtering test *************/
5365 hhook = (HWINEVENTHOOK)pSetWinEventHook(
5366 EVENT_OBJECT_SHOW, /* 0x8002 */
5367 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */
5368 GetModuleHandleA(0), win_event_global_hook_proc,
5369 GetCurrentProcessId(), 0,
5370 WINEVENT_INCONTEXT);
5371 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
5373 hevent = CreateEventA(NULL, 0, 0, NULL);
5375 hwnd2 = (HWND)hevent;
5377 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
5378 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5380 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5382 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
5385 /* this one should be received only by old hook proc */
5386 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
5387 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
5388 /* this one should be received only by old hook proc */
5389 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
5391 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
5393 ret = pUnhookWinEvent(hhook);
5394 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5396 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5397 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5398 CloseHandle(hthread);
5399 CloseHandle(hevent);
5400 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5401 /****** end of event filtering test *************/
5403 /****** start of out of context event test *************/
5404 hhook = (HWINEVENTHOOK)pSetWinEventHook(
5405 EVENT_MIN, EVENT_MAX,
5406 0, win_event_global_hook_proc,
5407 GetCurrentProcessId(), 0,
5408 WINEVENT_OUTOFCONTEXT);
5409 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
5411 hevent = CreateEventA(NULL, 0, 0, NULL);
5413 hwnd2 = (HWND)hevent;
5417 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
5418 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5420 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5422 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
5423 /* process pending winevent messages */
5424 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
5425 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
5428 /* this one should be received only by old hook proc */
5429 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
5430 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
5431 /* this one should be received only by old hook proc */
5432 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
5434 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE);
5435 /* process pending winevent messages */
5436 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
5437 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
5439 ret = pUnhookWinEvent(hhook);
5440 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5442 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5443 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5444 CloseHandle(hthread);
5445 CloseHandle(hevent);
5446 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5447 /****** end of out of context event test *************/
5449 ok(DestroyWindow(hwnd), "failed to destroy window\n");
5452 static void test_set_hook(void)
5456 HWINEVENTHOOK hwinevent_hook;
5457 HMODULE user32 = GetModuleHandleA("user32.dll");
5458 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
5459 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
5461 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId());
5462 ok(hhook != 0, "local hook does not require hModule set to 0\n");
5463 UnhookWindowsHookEx(hhook);
5465 #if 0 /* this test doesn't pass under Win9x: BUG! */
5466 SetLastError(0xdeadbeef);
5467 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0);
5468 ok(!hhook, "global hook requires hModule != 0\n");
5469 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %ld\n", GetLastError());
5472 SetLastError(0xdeadbeef);
5473 hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId());
5474 ok(!hhook, "SetWinEventHook with invalid proc should fail\n");
5475 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */
5476 GetLastError() == 0xdeadbeef, /* Win9x */
5477 "unexpected error %ld\n", GetLastError());
5479 SetLastError(0xdeadbeef);
5480 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
5481 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */
5482 GetLastError() == 0xdeadbeef, /* Win9x */
5483 "unexpected error %ld\n", GetLastError());
5485 if (!pSetWinEventHook || !pUnhookWinEvent) return;
5487 /* even process local incontext hooks require hmodule */
5488 SetLastError(0xdeadbeef);
5489 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
5490 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
5491 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
5492 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
5493 GetLastError() == 0xdeadbeef, /* Win9x */
5494 "unexpected error %ld\n", GetLastError());
5496 /* even thread local incontext hooks require hmodule */
5497 SetLastError(0xdeadbeef);
5498 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
5499 0, win_event_proc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT);
5500 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
5501 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
5502 GetLastError() == 0xdeadbeef, /* Win9x */
5503 "unexpected error %ld\n", GetLastError());
5505 #if 0 /* these 3 tests don't pass under Win9x */
5506 SetLastError(0xdeadbeef);
5507 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(1, 0,
5508 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
5509 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
5510 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
5512 SetLastError(0xdeadbeef);
5513 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(-1, 1,
5514 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
5515 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
5516 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
5518 SetLastError(0xdeadbeef);
5519 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
5520 0, win_event_proc, 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT);
5521 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n");
5522 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %ld\n", GetLastError());
5525 SetLastError(0xdeadbeef);
5526 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(0, 0,
5527 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
5528 ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
5529 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
5530 ret = pUnhookWinEvent(hwinevent_hook);
5531 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5534 /* This call succeeds under win2k SP4, but fails under Wine.
5535 Does win2k test/use passed process id? */
5536 SetLastError(0xdeadbeef);
5537 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
5538 0, win_event_proc, 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT);
5539 ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
5540 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
5541 ret = pUnhookWinEvent(hwinevent_hook);
5542 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5545 SetLastError(0xdeadbeef);
5546 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n");
5547 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
5548 GetLastError() == 0xdeadbeef, /* Win9x */
5549 "unexpected error %ld\n", GetLastError());
5552 static const struct message ScrollWindowPaint1[] = {
5554 { WM_ERASEBKGND, sent|beginpaint },
5558 static const struct message ScrollWindowPaint2[] = {
5563 static void test_scrollwindowex(void)
5566 RECT rect={0,0,130,130};
5569 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll",
5570 WS_VISIBLE|WS_OVERLAPPEDWINDOW,
5571 100, 100, 200, 200, 0, 0, 0, NULL);
5572 ok (hwnd != 0, "Failed to create overlapped window\n");
5573 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
5574 WS_VISIBLE|WS_CAPTION|WS_CHILD,
5575 10, 10, 150, 150, hwnd, 0, 0, NULL);
5576 ok (hchild != 0, "Failed to create child\n");
5578 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5581 /* scroll without the child window */
5582 trace("start scroll\n");
5583 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
5584 SW_ERASE|SW_INVALIDATE);
5585 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
5586 trace("end scroll\n");
5588 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5589 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
5591 /* Now without the SW_ERASE flag */
5592 trace("start scroll\n");
5593 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE);
5594 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
5595 trace("end scroll\n");
5597 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5598 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", 0);
5600 /* now scroll the child window as well */
5601 trace("start scroll\n");
5602 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
5603 SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
5604 todo_wine { /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
5605 /* windows sometimes a WM_MOVE */
5606 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
5608 trace("end scroll\n");
5610 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5611 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
5613 /* now scroll with ScrollWindow() */
5614 trace("start scroll with ScrollWindow\n");
5615 ScrollWindow( hwnd, 5, 5, NULL, NULL);
5616 trace("end scroll\n");
5618 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5619 ok_sequence(ScrollWindowPaint1, "ScrollWindow", 0);
5621 ok(DestroyWindow(hchild), "failed to destroy window\n");
5622 ok(DestroyWindow(hwnd), "failed to destroy window\n");
5626 static const struct message destroy_window_with_children[] = {
5627 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
5628 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */
5629 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */
5630 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
5631 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
5632 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
5633 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
5634 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */
5635 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
5636 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
5637 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
5638 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
5639 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
5640 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
5641 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
5642 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
5646 static void test_DestroyWindow(void)
5649 HWND parent, child1, child2, child3, child4, test;
5650 UINT child_id = WND_CHILD_ID + 1;
5652 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
5653 100, 100, 200, 200, 0, 0, 0, NULL);
5654 assert(parent != 0);
5655 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
5656 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL);
5657 assert(child1 != 0);
5658 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
5659 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL);
5660 assert(child2 != 0);
5661 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
5662 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL);
5663 assert(child3 != 0);
5664 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP,
5665 0, 0, 50, 50, parent, 0, 0, NULL);
5666 assert(child4 != 0);
5668 /* test owner/parent of child2 */
5669 test = GetParent(child2);
5670 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
5671 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
5673 test = pGetAncestor(child2, GA_PARENT);
5674 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
5676 test = GetWindow(child2, GW_OWNER);
5677 ok(!test, "wrong owner %p\n", test);
5679 test = SetParent(child2, parent);
5680 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test);
5682 /* test owner/parent of the parent */
5683 test = GetParent(parent);
5684 ok(!test, "wrong parent %p\n", test);
5686 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent);
5689 test = pGetAncestor(parent, GA_PARENT);
5690 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
5692 test = GetWindow(parent, GW_OWNER);
5693 ok(!test, "wrong owner %p\n", test);
5695 /* test owner/parent of child1 */
5696 test = GetParent(child1);
5697 ok(test == parent, "wrong parent %p\n", test);
5698 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
5700 test = pGetAncestor(child1, GA_PARENT);
5701 ok(test == parent, "wrong parent %p\n", test);
5703 test = GetWindow(child1, GW_OWNER);
5704 ok(!test, "wrong owner %p\n", test);
5706 /* test owner/parent of child2 */
5707 test = GetParent(child2);
5708 ok(test == parent, "wrong parent %p\n", test);
5709 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
5711 test = pGetAncestor(child2, GA_PARENT);
5712 ok(test == parent, "wrong parent %p\n", test);
5714 test = GetWindow(child2, GW_OWNER);
5715 ok(!test, "wrong owner %p\n", test);
5717 /* test owner/parent of child3 */
5718 test = GetParent(child3);
5719 ok(test == child1, "wrong parent %p\n", test);
5720 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
5722 test = pGetAncestor(child3, GA_PARENT);
5723 ok(test == child1, "wrong parent %p\n", test);
5725 test = GetWindow(child3, GW_OWNER);
5726 ok(!test, "wrong owner %p\n", test);
5728 /* test owner/parent of child4 */
5729 test = GetParent(child4);
5730 ok(test == parent, "wrong parent %p\n", test);
5731 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
5733 test = pGetAncestor(child4, GA_PARENT);
5734 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
5736 test = GetWindow(child4, GW_OWNER);
5737 ok(test == parent, "wrong owner %p\n", test);
5741 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
5742 parent, child1, child2, child3, child4);
5745 test = GetCapture();
5746 ok(test == child4, "wrong capture window %p\n", test);
5748 test_DestroyWindow_flag = TRUE;
5749 ret = DestroyWindow(parent);
5750 ok( ret, "DestroyWindow() error %ld\n", GetLastError());
5751 test_DestroyWindow_flag = FALSE;
5752 ok_sequence(destroy_window_with_children, "destroy window with children", 0);
5754 ok(!IsWindow(parent), "parent still exists\n");
5755 ok(!IsWindow(child1), "child1 still exists\n");
5756 ok(!IsWindow(child2), "child2 still exists\n");
5757 ok(!IsWindow(child3), "child3 still exists\n");
5758 ok(!IsWindow(child4), "child4 still exists\n");
5760 test = GetCapture();
5761 ok(!test, "wrong capture window %p\n", test);
5765 static const struct message WmDispatchPaint[] = {
5766 { WM_NCPAINT, sent },
5767 { WM_GETTEXT, sent|defwinproc|optional },
5768 { WM_GETTEXT, sent|defwinproc|optional },
5769 { WM_ERASEBKGND, sent },
5773 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5775 if (message == WM_PAINT)
5777 trace( "Got WM_PAINT, ignoring\n" );
5780 return MsgCheckProcA( hwnd, message, wParam, lParam );
5783 static void test_DispatchMessage(void)
5788 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
5789 100, 100, 200, 200, 0, 0, 0, NULL);
5790 ShowWindow( hwnd, SW_SHOW );
5791 UpdateWindow( hwnd );
5792 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5794 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc );
5796 SetRect( &rect, -5, -5, 5, 5 );
5797 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
5799 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
5801 if (msg.message != WM_PAINT) DispatchMessage( &msg );
5805 DispatchMessage( &msg );
5806 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
5807 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
5808 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE );
5809 if (++count > 10) break;
5812 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" );
5814 trace("now without DispatchMessage\n");
5816 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
5818 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
5820 if (msg.message != WM_PAINT) DispatchMessage( &msg );
5823 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
5825 /* this will send WM_NCCPAINT just like DispatchMessage does */
5826 GetUpdateRgn( hwnd, hrgn, TRUE );
5827 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
5828 DeleteObject( hrgn );
5829 GetClientRect( hwnd, &rect );
5830 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */
5831 ok( !count, "Got multiple WM_PAINTs\n" );
5832 if (++count > 10) break;
5841 HMODULE user32 = GetModuleHandleA("user32.dll");
5842 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
5843 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
5844 FARPROC pIsWinEventHookInstalled = 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
5845 pGetAncestor = (void*) GetProcAddress(user32, "GetAncestor");
5847 if (!RegisterWindowClasses()) assert(0);
5849 if (pSetWinEventHook)
5851 hEvent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
5852 GetModuleHandleA(0),
5855 GetCurrentThreadId(),
5856 WINEVENT_INCONTEXT);
5857 assert(hEvent_hook);
5859 if (pIsWinEventHookInstalled)
5862 for (event = EVENT_MIN; event <= EVENT_MAX; event++)
5863 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
5867 cbt_hook_thread_id = GetCurrentThreadId();
5868 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
5873 /* Fix message sequences before removing 3 lines below */
5874 ret = pUnhookWinEvent(hEvent_hook);
5875 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5876 pUnhookWinEvent = 0;
5879 test_scrollwindowex();
5881 test_mdi_messages();
5882 test_button_messages();
5883 test_paint_messages();
5884 test_interthread_messages();
5885 test_message_conversion();
5886 test_accelerators();
5889 test_DestroyWindow();
5890 test_DispatchMessage();
5892 UnhookWindowsHookEx(hCBT_hook);
5893 if (pUnhookWinEvent)
5895 ret = pUnhookWinEvent(hEvent_hook);
5896 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5897 SetLastError(0xdeadbeef);
5898 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n");
5899 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
5900 GetLastError() == 0xdeadbeef, /* Win9x */
5901 "unexpected error %ld\n", GetLastError());