user/tests: Remove todo_wine from a few tests that (usually) succeed.
[wine/multimedia.git] / dlls / user / tests / msg.c
blob3cdaf5e49be1ca96b2a3d82dcc1a651940ce1982
1 /*
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
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <stdio.h>
27 #define _WIN32_WINNT 0x0501 /* For WM_CHANGEUISTATE,QS_RAWINPUT */
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winnls.h"
35 #include "wine/test.h"
37 #define MDI_FIRST_CHILD_ID 2004
39 /* undocumented SWP flags - from SDK 3.1 */
40 #define SWP_NOCLIENTSIZE 0x0800
41 #define SWP_NOCLIENTMOVE 0x1000
43 #define WND_PARENT_ID 1
44 #define WND_POPUP_ID 2
45 #define WND_CHILD_ID 3
47 static BOOL test_DestroyWindow_flag;
48 static HWINEVENTHOOK hEvent_hook;
50 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
53 FIXME: add tests for these
54 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
55 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
56 WS_THICKFRAME: thick border
57 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
58 WS_BORDER (default for overlapped windows): single black border
59 none (default for child (and popup?) windows): no border
62 typedef enum {
63 sent=0x1,
64 posted=0x2,
65 parent=0x4,
66 wparam=0x8,
67 lparam=0x10,
68 defwinproc=0x20,
69 beginpaint=0x40,
70 optional=0x80,
71 hook=0x100,
72 winevent_hook=0x200
73 } msg_flags_t;
75 struct message {
76 UINT message; /* the WM_* code */
77 msg_flags_t flags; /* message props */
78 WPARAM wParam; /* expected value of wParam */
79 LPARAM lParam; /* expected value of lParam */
82 /* Empty message sequence */
83 static const struct message WmEmptySeq[] =
85 { 0 }
87 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
88 static const struct message WmCreateOverlappedSeq[] = {
89 { HCBT_CREATEWND, hook },
90 { WM_GETMINMAXINFO, sent },
91 { WM_NCCREATE, sent },
92 { WM_NCCALCSIZE, sent|wparam, 0 },
93 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
94 { WM_CREATE, sent },
95 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
96 { 0 }
98 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
99 * for a not visible overlapped window.
101 static const struct message WmSWP_ShowOverlappedSeq[] = {
102 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
103 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
104 { WM_NCPAINT, sent|wparam|optional, 1 },
105 { WM_GETTEXT, sent|defwinproc|optional },
106 { WM_ERASEBKGND, sent|optional },
107 { HCBT_ACTIVATE, hook },
108 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
109 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
110 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
111 { WM_ACTIVATEAPP, sent|wparam, 1 },
112 { WM_NCACTIVATE, sent|wparam, 1 },
113 { WM_GETTEXT, sent|defwinproc|optional },
114 { WM_ACTIVATE, sent|wparam, 1 },
115 { HCBT_SETFOCUS, hook },
116 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
117 { WM_IME_NOTIFY, sent|defwinproc|optional },
118 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
119 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
120 { WM_NCPAINT, sent|wparam|optional, 1 },
121 { WM_GETTEXT, sent|defwinproc|optional },
122 { WM_ERASEBKGND, sent|optional },
123 /* Win9x adds SWP_NOZORDER below */
124 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
125 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
126 { WM_NCPAINT, sent|wparam|optional, 1 },
127 { WM_ERASEBKGND, sent|optional },
128 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
129 { 0 }
131 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
132 * for a visible overlapped window.
134 static const struct message WmSWP_HideOverlappedSeq[] = {
135 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
136 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
137 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
138 { 0 }
141 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
142 * for a visible overlapped window.
144 static const struct message WmSWP_ResizeSeq[] = {
145 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE },
146 { WM_GETMINMAXINFO, sent|defwinproc },
147 { WM_NCCALCSIZE, sent|wparam, TRUE },
148 { WM_NCPAINT, sent|optional },
149 { WM_GETTEXT, sent|defwinproc|optional },
150 { WM_ERASEBKGND, sent|optional },
151 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
152 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
153 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
154 { WM_NCPAINT, sent|optional },
155 { WM_GETTEXT, sent|defwinproc|optional },
156 { WM_ERASEBKGND, sent|optional },
157 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
158 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
159 { 0 }
162 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
163 * for a visible popup window.
165 static const struct message WmSWP_ResizePopupSeq[] = {
166 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE },
167 { WM_NCCALCSIZE, sent|wparam, TRUE },
168 { WM_NCPAINT, sent|optional },
169 { WM_GETTEXT, sent|defwinproc|optional },
170 { WM_ERASEBKGND, sent|optional },
171 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
172 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
173 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
174 { WM_NCPAINT, sent|optional },
175 { WM_GETTEXT, sent|defwinproc|optional },
176 { WM_ERASEBKGND, sent|optional },
177 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
178 { 0 }
181 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
182 * for a visible overlapped window.
184 static const struct message WmSWP_MoveSeq[] = {
185 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE },
186 { WM_NCPAINT, sent|optional },
187 { WM_GETTEXT, sent|defwinproc|optional },
188 { WM_ERASEBKGND, sent|optional },
189 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE },
190 { WM_MOVE, sent|defwinproc|wparam, 0 },
191 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
192 { 0 }
195 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
196 SWP_NOZORDER|SWP_FRAMECHANGED)
197 * for a visible overlapped window with WS_CLIPCHILDREN style set.
199 static const struct message WmSWP_FrameChanged_clip[] = {
200 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
201 { WM_NCCALCSIZE, sent|wparam|parent, 1 },
202 { WM_NCPAINT, sent|parent }, /* wparam != 1 */
203 { WM_GETTEXT, sent|parent|defwinproc|optional },
204 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
205 { WM_NCPAINT, sent }, /* wparam != 1 */
206 { WM_ERASEBKGND, sent },
207 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
208 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
209 { WM_PAINT, sent },
210 { 0 }
212 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
213 SWP_NOZORDER|SWP_FRAMECHANGED)
214 * for a visible overlapped window.
216 static const struct message WmSWP_FrameChangedDeferErase[] = {
217 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
218 { WM_NCCALCSIZE, sent|wparam|parent, 1 },
219 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
220 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
221 { WM_PAINT, sent|parent },
222 { WM_NCPAINT, sent|beginpaint|parent }, /* wparam != 1 */
223 { WM_GETTEXT, sent|beginpaint|parent|defwinproc|optional },
224 { WM_PAINT, sent },
225 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
226 { WM_ERASEBKGND, sent|beginpaint },
227 { 0 }
230 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
231 SWP_NOZORDER|SWP_FRAMECHANGED)
232 * for a visible overlapped window without WS_CLIPCHILDREN style set.
234 static const struct message WmSWP_FrameChanged_noclip[] = {
235 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
236 { WM_NCCALCSIZE, sent|wparam|parent, 1 },
237 { WM_NCPAINT, sent|parent }, /* wparam != 1 */
238 { WM_GETTEXT, sent|parent|defwinproc|optional },
239 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
240 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
241 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
242 { WM_PAINT, sent },
243 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
244 { WM_ERASEBKGND, sent|beginpaint },
245 { 0 }
248 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
249 static const struct message WmShowOverlappedSeq[] = {
250 { WM_SHOWWINDOW, sent|wparam, 1 },
251 { WM_NCPAINT, sent|wparam|optional, 1 },
252 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
253 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
254 { WM_NCPAINT, sent|wparam|optional, 1 },
255 { WM_GETTEXT, sent|defwinproc|optional },
256 { WM_ERASEBKGND, sent|optional },
257 { HCBT_ACTIVATE, hook },
258 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
259 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
260 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
261 { WM_ACTIVATEAPP, sent|wparam, 1 },
262 { WM_NCACTIVATE, sent|wparam, 1 },
263 { WM_GETTEXT, sent|defwinproc|optional },
264 { WM_ACTIVATE, sent|wparam, 1 },
265 { HCBT_SETFOCUS, hook },
266 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
267 { WM_IME_NOTIFY, sent|defwinproc|optional },
268 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
269 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
270 { WM_NCPAINT, sent|wparam|optional, 1 },
271 { WM_GETTEXT, sent|defwinproc|optional },
272 { WM_ERASEBKGND, sent|optional },
273 /* Win9x adds SWP_NOZORDER below */
274 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
275 { WM_NCCALCSIZE, sent|optional },
276 { WM_NCPAINT, sent|optional },
277 { WM_ERASEBKGND, sent|optional },
278 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
279 * messages. Does that mean that CreateWindow doesn't set initial
280 * window dimensions for overlapped windows?
282 { WM_SIZE, sent },
283 { WM_MOVE, sent },
284 #endif
285 { 0 }
287 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
288 static const struct message WmShowMaxOverlappedSeq[] = {
289 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
290 { WM_GETMINMAXINFO, sent },
291 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
292 { WM_GETMINMAXINFO, sent|defwinproc },
293 { WM_NCCALCSIZE, sent|wparam, TRUE },
294 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
295 { HCBT_ACTIVATE, hook },
296 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
297 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
298 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
299 { WM_ACTIVATEAPP, sent|wparam, 1 },
300 { WM_NCACTIVATE, sent|wparam, 1 },
301 { WM_GETTEXT, sent|defwinproc|optional },
302 { WM_ACTIVATE, sent|wparam, 1 },
303 { HCBT_SETFOCUS, hook },
304 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
305 { WM_IME_NOTIFY, sent|defwinproc|optional },
306 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
307 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
308 { WM_NCPAINT, sent|wparam|optional, 1 },
309 { WM_GETTEXT, sent|defwinproc|optional },
310 { WM_ERASEBKGND, sent|optional },
311 /* Win9x adds SWP_NOZORDER below */
312 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
313 { WM_MOVE, sent|defwinproc },
314 { WM_SIZE, sent|defwinproc },
315 { WM_NCCALCSIZE, sent|optional },
316 { WM_NCPAINT, sent|optional },
317 { WM_ERASEBKGND, sent|optional },
318 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
319 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
320 { 0 }
322 /* ShowWindow(SW_HIDE) for a visible overlapped window */
323 static const struct message WmHideOverlappedSeq[] = {
324 { WM_SHOWWINDOW, sent|wparam, 0 },
325 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
326 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
327 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
328 { WM_SIZE, sent|optional }, /* XP doesn't send it */
329 { WM_MOVE, sent|optional }, /* XP doesn't send it */
330 { WM_NCACTIVATE, sent|wparam, 0 },
331 { WM_ACTIVATE, sent|wparam, 0 },
332 { WM_ACTIVATEAPP, sent|wparam, 0 },
333 { WM_KILLFOCUS, sent|wparam, 0 },
334 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
335 { WM_IME_NOTIFY, sent|optional|defwinproc },
336 { 0 }
338 /* DestroyWindow for a visible overlapped window */
339 static const struct message WmDestroyOverlappedSeq[] = {
340 { HCBT_DESTROYWND, hook },
341 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
342 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
343 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
344 { WM_NCACTIVATE, sent|wparam, 0 },
345 { WM_ACTIVATE, sent|wparam, 0 },
346 { WM_ACTIVATEAPP, sent|wparam, 0 },
347 { WM_KILLFOCUS, sent|wparam, 0 },
348 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
349 { WM_IME_NOTIFY, sent|optional|defwinproc },
350 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
351 { WM_DESTROY, sent },
352 { WM_NCDESTROY, sent },
353 { 0 }
355 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
356 static const struct message WmCreateMaxPopupSeq[] = {
357 { HCBT_CREATEWND, hook },
358 { WM_NCCREATE, sent },
359 { WM_NCCALCSIZE, sent|wparam, 0 },
360 { WM_CREATE, sent },
361 { WM_SIZE, sent },
362 { WM_MOVE, sent },
363 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
364 { WM_GETMINMAXINFO, sent },
365 { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
366 { WM_NCCALCSIZE, sent|wparam, TRUE },
367 { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOZORDER|0x8000*/ },
368 { WM_MOVE, sent|defwinproc },
369 { WM_SIZE, sent|defwinproc },
370 { WM_SHOWWINDOW, sent|wparam, 1 },
371 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
372 { HCBT_ACTIVATE, hook },
373 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
374 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
375 { WM_ACTIVATEAPP, sent|wparam, 1 },
376 { WM_NCACTIVATE, sent|wparam, 1 },
377 { WM_ACTIVATE, sent|wparam, 1 },
378 { HCBT_SETFOCUS, hook },
379 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
380 { WM_SYNCPAINT, sent|wparam|optional, 4 },
381 { WM_NCPAINT, sent|wparam|optional, 1 },
382 { WM_ERASEBKGND, sent|optional },
383 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE },
384 { 0 }
386 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
387 static const struct message WmCreateInvisibleMaxPopupSeq[] = {
388 { HCBT_CREATEWND, hook },
389 { WM_NCCREATE, sent },
390 { WM_NCCALCSIZE, sent|wparam, 0 },
391 { WM_CREATE, sent },
392 { WM_SIZE, sent },
393 { WM_MOVE, sent },
394 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
395 { WM_GETMINMAXINFO, sent },
396 { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
397 { WM_NCCALCSIZE, sent|wparam, TRUE },
398 { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOZORDER|0x8000*/ },
399 { WM_MOVE, sent|defwinproc },
400 { WM_SIZE, sent|defwinproc },
401 { 0 }
403 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
404 static const struct message WmShowMaxPopupResizedSeq[] = {
405 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
406 { WM_GETMINMAXINFO, sent },
407 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
408 { WM_NCCALCSIZE, sent|wparam, TRUE },
409 { HCBT_ACTIVATE, hook },
410 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
411 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
412 { WM_ACTIVATEAPP, sent|wparam, 1 },
413 { WM_NCACTIVATE, sent|wparam, 1 },
414 { WM_ACTIVATE, sent|wparam, 1 },
415 { HCBT_SETFOCUS, hook },
416 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
417 { WM_NCPAINT, sent|wparam|optional, 1 },
418 { WM_ERASEBKGND, sent|optional },
419 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOZORDER },
420 /* WinNT4.0 sends WM_MOVE */
421 { WM_MOVE, sent|defwinproc|optional },
422 { WM_SIZE, sent|defwinproc },
423 { 0 }
425 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
426 static const struct message WmShowMaxPopupSeq[] = {
427 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
428 { WM_GETMINMAXINFO, sent },
429 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
430 { WM_NCCALCSIZE, sent|wparam, TRUE },
431 { HCBT_ACTIVATE, hook },
432 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
433 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
434 { WM_ACTIVATEAPP, sent|wparam, 1 },
435 { WM_NCACTIVATE, sent|wparam, 1 },
436 { WM_ACTIVATE, sent|wparam, 1 },
437 { HCBT_SETFOCUS, hook },
438 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
439 { WM_SYNCPAINT, sent|wparam|optional, 4 },
440 { WM_NCPAINT, sent|wparam|optional, 1 },
441 { WM_ERASEBKGND, sent|optional },
442 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
443 { 0 }
445 /* CreateWindow(WS_VISIBLE) for popup window */
446 static const struct message WmCreatePopupSeq[] = {
447 { HCBT_CREATEWND, hook },
448 { WM_NCCREATE, sent },
449 { WM_NCCALCSIZE, sent|wparam, 0 },
450 { WM_CREATE, sent },
451 { WM_SIZE, sent },
452 { WM_MOVE, sent },
453 { WM_SHOWWINDOW, sent|wparam, 1 },
454 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
455 { HCBT_ACTIVATE, hook },
456 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
457 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
458 { WM_NCPAINT, sent|wparam|optional, 1 },
459 { WM_ERASEBKGND, sent|optional },
460 { WM_ACTIVATEAPP, sent|wparam, 1 },
461 { WM_NCACTIVATE, sent|wparam, 1 },
462 { WM_ACTIVATE, sent|wparam, 1 },
463 { HCBT_SETFOCUS, hook },
464 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
465 { WM_SYNCPAINT, sent|wparam|optional, 4 },
466 { WM_NCPAINT, sent|wparam|optional, 1 },
467 { WM_ERASEBKGND, sent|optional },
468 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE },
469 { 0 }
471 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
472 static const struct message WmShowVisMaxPopupSeq[] = {
473 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
474 { WM_GETMINMAXINFO, sent },
475 { WM_GETTEXT, sent|optional },
476 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
477 { WM_NCCALCSIZE, sent|wparam, TRUE },
478 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
479 { WM_NCPAINT, sent|wparam|optional, 1 },
480 { WM_ERASEBKGND, sent|optional },
481 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOZORDER|0x8000 },
482 { WM_MOVE, sent|defwinproc },
483 { WM_SIZE, sent|defwinproc },
484 { 0 }
486 /* CreateWindow (for a child popup window, not initially visible) */
487 static const struct message WmCreateChildPopupSeq[] = {
488 { HCBT_CREATEWND, hook },
489 { WM_NCCREATE, sent },
490 { WM_NCCALCSIZE, sent|wparam, 0 },
491 { WM_CREATE, sent },
492 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
493 { WM_SIZE, sent },
494 { WM_MOVE, sent },
495 { 0 }
497 /* CreateWindow (for a popup window, not initially visible,
498 * which sets WS_VISIBLE in WM_CREATE handler)
500 static const struct message WmCreateInvisiblePopupSeq[] = {
501 { HCBT_CREATEWND, hook },
502 { WM_NCCREATE, sent },
503 { WM_NCCALCSIZE, sent|wparam, 0 },
504 { WM_CREATE, sent },
505 { WM_STYLECHANGING, sent },
506 { WM_STYLECHANGED, sent },
507 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
508 { WM_SIZE, sent },
509 { WM_MOVE, sent },
510 { 0 }
512 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
513 * for a popup window with WS_VISIBLE style set
515 static const struct message WmShowVisiblePopupSeq_2[] = {
516 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
517 { 0 }
519 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
520 * for a popup window with WS_VISIBLE style set
522 static const struct message WmShowVisiblePopupSeq_3[] = {
523 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
524 { HCBT_ACTIVATE, hook },
525 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
526 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
527 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
528 { WM_NCACTIVATE, sent|wparam, 1 },
529 { WM_ACTIVATE, sent|wparam, 1 },
530 { HCBT_SETFOCUS, hook },
531 { WM_KILLFOCUS, sent|parent },
532 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
533 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
534 { WM_IME_NOTIFY, sent|defwinproc|optional },
535 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
536 { WM_SETFOCUS, sent|defwinproc },
537 { 0 }
539 /* CreateWindow (for child window, not initially visible) */
540 static const struct message WmCreateChildSeq[] = {
541 { HCBT_CREATEWND, hook },
542 { WM_NCCREATE, sent },
543 /* child is inserted into parent's child list after WM_NCCREATE returns */
544 { WM_NCCALCSIZE, sent|wparam, 0 },
545 { WM_CREATE, sent },
546 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
547 { WM_SIZE, sent },
548 { WM_MOVE, sent },
549 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
550 { 0 }
552 /* CreateWindow (for maximized child window, not initially visible) */
553 static const struct message WmCreateMaximizedChildSeq[] = {
554 { HCBT_CREATEWND, hook },
555 { WM_NCCREATE, sent },
556 { WM_NCCALCSIZE, sent|wparam, 0 },
557 { WM_CREATE, sent },
558 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
559 { WM_SIZE, sent },
560 { WM_MOVE, sent },
561 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
562 { WM_GETMINMAXINFO, sent },
563 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
564 { WM_NCCALCSIZE, sent|wparam, 1 },
565 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 },
566 { WM_SIZE, sent|defwinproc },
567 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
568 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
569 { 0 }
571 /* CreateWindow (for a child window, initially visible) */
572 static const struct message WmCreateVisibleChildSeq[] = {
573 { HCBT_CREATEWND, hook },
574 { WM_NCCREATE, sent },
575 /* child is inserted into parent's child list after WM_NCCREATE returns */
576 { WM_NCCALCSIZE, sent|wparam, 0 },
577 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
578 { WM_CREATE, sent },
579 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
580 { WM_SIZE, sent },
581 { WM_MOVE, sent },
582 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
583 { WM_SHOWWINDOW, sent|wparam, 1 },
584 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
585 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
586 { WM_ERASEBKGND, sent|parent|optional },
587 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
588 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */
589 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
590 { 0 }
592 /* ShowWindow(SW_SHOW) for a not visible child window */
593 static const struct message WmShowChildSeq[] = {
594 { WM_SHOWWINDOW, sent|wparam, 1 },
595 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
596 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
597 { WM_ERASEBKGND, sent|parent|optional },
598 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
599 { 0 }
601 /* ShowWindow(SW_HIDE) for a visible child window */
602 static const struct message WmHideChildSeq[] = {
603 { WM_SHOWWINDOW, sent|wparam, 0 },
604 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
605 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
606 { WM_ERASEBKGND, sent|parent|optional },
607 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
608 { 0 }
610 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
611 * for a not visible child window
613 static const struct message WmShowChildSeq_2[] = {
614 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
615 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
616 { WM_CHILDACTIVATE, sent },
617 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
618 { 0 }
620 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
621 * for a not visible child window
623 static const struct message WmShowChildSeq_3[] = {
624 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
625 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
626 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
627 { 0 }
629 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
630 * for a visible child window with a caption
632 static const struct message WmShowChildSeq_4[] = {
633 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
634 { WM_CHILDACTIVATE, sent },
635 { 0 }
637 /* ShowWindow(SW_SHOW) for child with invisible parent */
638 static const struct message WmShowChildInvisibleParentSeq[] = {
639 { WM_SHOWWINDOW, sent|wparam, 1 },
640 { 0 }
642 /* ShowWindow(SW_HIDE) for child with invisible parent */
643 static const struct message WmHideChildInvisibleParentSeq[] = {
644 { WM_SHOWWINDOW, sent|wparam, 0 },
645 { 0 }
647 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
648 static const struct message WmShowChildInvisibleParentSeq_2[] = {
649 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
650 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
651 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
652 { 0 }
654 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
655 static const struct message WmHideChildInvisibleParentSeq_2[] = {
656 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
657 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
658 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
659 { 0 }
661 /* DestroyWindow for a visible child window */
662 static const struct message WmDestroyChildSeq[] = {
663 { HCBT_DESTROYWND, hook },
664 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
665 { WM_SHOWWINDOW, sent|wparam, 0 },
666 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
667 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
668 { WM_ERASEBKGND, sent|parent|optional },
669 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
670 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
671 { WM_KILLFOCUS, sent },
672 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
673 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
674 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
675 { WM_SETFOCUS, sent|parent },
676 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
677 { WM_DESTROY, sent },
678 { WM_DESTROY, sent|optional }, /* some other (IME?) window */
679 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */
680 { WM_NCDESTROY, sent },
681 { 0 }
683 /* DestroyWindow for a visible child window with invisible parent */
684 static const struct message WmDestroyInvisibleChildSeq[] = {
685 { HCBT_DESTROYWND, hook },
686 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
687 { WM_SHOWWINDOW, sent|wparam, 0 },
688 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
689 { WM_DESTROY, sent },
690 { WM_NCDESTROY, sent },
691 { 0 }
693 /* Moving the mouse in nonclient area */
694 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
695 { WM_NCHITTEST, sent },
696 { WM_SETCURSOR, sent },
697 { WM_NCMOUSEMOVE, posted },
698 { 0 }
700 /* Moving the mouse in client area */
701 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
702 { WM_NCHITTEST, sent },
703 { WM_SETCURSOR, sent },
704 { WM_MOUSEMOVE, posted },
705 { 0 }
707 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
708 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
709 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
710 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
711 { WM_GETMINMAXINFO, sent|defwinproc },
712 { WM_ENTERSIZEMOVE, sent|defwinproc },
713 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
714 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
715 { WM_MOVE, sent|defwinproc },
716 { WM_EXITSIZEMOVE, sent|defwinproc },
717 { 0 }
719 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
720 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
721 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
722 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
723 { WM_GETMINMAXINFO, sent|defwinproc },
724 { WM_ENTERSIZEMOVE, sent|defwinproc },
725 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
726 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
727 { WM_GETMINMAXINFO, sent|defwinproc },
728 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
729 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
730 { WM_GETTEXT, sent|defwinproc },
731 { WM_ERASEBKGND, sent|defwinproc },
732 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
733 { WM_MOVE, sent|defwinproc },
734 { WM_SIZE, sent|defwinproc },
735 { WM_EXITSIZEMOVE, sent|defwinproc },
736 { 0 }
738 /* Resizing child window with MoveWindow (32) */
739 static const struct message WmResizingChildWithMoveWindowSeq[] = {
740 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
741 { WM_NCCALCSIZE, sent|wparam, 1 },
742 { WM_ERASEBKGND, sent|optional },
743 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
744 { WM_MOVE, sent|defwinproc },
745 { WM_SIZE, sent|defwinproc },
746 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
747 { 0 }
749 /* Clicking on inactive button */
750 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
751 { WM_NCHITTEST, sent },
752 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
753 { WM_MOUSEACTIVATE, sent },
754 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
755 { WM_SETCURSOR, sent },
756 { WM_SETCURSOR, sent|parent|defwinproc },
757 { WM_LBUTTONDOWN, posted },
758 { WM_KILLFOCUS, posted|parent },
759 { WM_SETFOCUS, posted },
760 { WM_CTLCOLORBTN, posted|parent },
761 { BM_SETSTATE, posted },
762 { WM_CTLCOLORBTN, posted|parent },
763 { WM_LBUTTONUP, posted },
764 { BM_SETSTATE, posted },
765 { WM_CTLCOLORBTN, posted|parent },
766 { WM_COMMAND, posted|parent },
767 { 0 }
769 /* Reparenting a button (16/32) */
770 /* The last child (button) reparented gets topmost for its new parent. */
771 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
772 { WM_SHOWWINDOW, sent|wparam, 0 },
773 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
774 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
775 { WM_ERASEBKGND, sent|parent },
776 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
777 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
778 { WM_CHILDACTIVATE, sent },
779 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
780 { WM_MOVE, sent|defwinproc },
781 { WM_SHOWWINDOW, sent|wparam, 1 },
782 { 0 }
784 /* Creation of a custom dialog (32) */
785 static const struct message WmCreateCustomDialogSeq[] = {
786 { HCBT_CREATEWND, hook },
787 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
788 { WM_GETMINMAXINFO, sent },
789 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
790 { WM_NCCREATE, sent },
791 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
792 { WM_NCCALCSIZE, sent|wparam, 0 },
793 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
794 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
795 { WM_CREATE, sent },
796 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
797 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
798 { WM_SHOWWINDOW, sent|wparam, 1 },
799 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
800 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
801 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
802 { HCBT_ACTIVATE, hook },
803 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
805 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
807 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
808 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
810 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
812 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
813 { WM_NCACTIVATE, sent|wparam, 1 },
814 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
815 { WM_GETTEXT, sent|optional|defwinproc },
816 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
817 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
818 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
819 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
820 { WM_GETTEXT, sent|optional|defwinproc },
821 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
822 { WM_ACTIVATE, sent|wparam, 1 },
823 { WM_KILLFOCUS, sent|parent },
824 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
825 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
826 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
827 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
828 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
829 { WM_IME_NOTIFY, sent|optional|defwinproc },
830 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
831 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
832 { WM_SETFOCUS, sent },
833 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
834 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
835 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
836 { WM_NCPAINT, sent|wparam, 1 },
837 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
838 { WM_GETTEXT, sent|optional|defwinproc },
839 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
840 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
841 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
842 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
843 { WM_GETTEXT, sent|optional|defwinproc },
844 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
845 { WM_ERASEBKGND, sent },
846 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
847 { WM_CTLCOLORDLG, sent|defwinproc },
848 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
849 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
850 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
851 { WM_GETTEXT, sent|optional },
852 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
853 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
854 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
855 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
856 { WM_GETTEXT, sent|optional },
857 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
858 { WM_NCCALCSIZE, sent|optional },
859 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
860 { WM_NCPAINT, sent|optional },
861 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
862 { WM_GETTEXT, sent|optional|defwinproc },
863 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
864 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
865 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
866 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
867 { WM_GETTEXT, sent|optional|defwinproc },
868 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
869 { WM_ERASEBKGND, sent|optional },
870 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
871 { WM_CTLCOLORDLG, sent|optional|defwinproc },
872 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
873 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
874 { WM_SIZE, sent },
875 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
876 { WM_MOVE, sent },
877 { 0 }
879 /* Calling EndDialog for a custom dialog (32) */
880 static const struct message WmEndCustomDialogSeq[] = {
881 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
882 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
883 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
884 { WM_GETTEXT, sent|optional },
885 { HCBT_ACTIVATE, hook },
886 { WM_NCACTIVATE, sent|wparam, 0 },
887 { WM_GETTEXT, sent|optional|defwinproc },
888 { WM_GETTEXT, sent|optional|defwinproc },
889 { WM_ACTIVATE, sent|wparam, 0 },
890 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
891 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
892 { HCBT_SETFOCUS, hook },
893 { WM_KILLFOCUS, sent },
894 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
895 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
896 { WM_IME_NOTIFY, sent|optional },
897 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
898 { WM_SETFOCUS, sent|parent|defwinproc },
899 { 0 }
901 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
902 static const struct message WmShowCustomDialogSeq[] = {
903 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
904 { WM_SHOWWINDOW, sent|wparam, 1 },
905 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
906 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
907 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
908 { HCBT_ACTIVATE, hook },
909 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
911 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
912 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
914 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
915 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
916 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
917 { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
918 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
919 { WM_NCACTIVATE, sent|wparam, 1 },
920 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
921 { WM_ACTIVATE, sent|wparam, 1 },
923 { WM_KILLFOCUS, sent|parent },
924 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
925 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
926 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
927 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
928 { WM_IME_NOTIFY, sent|optional|defwinproc },
929 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
930 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
931 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
932 { WM_SETFOCUS, sent },
933 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
934 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
935 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
936 { WM_NCPAINT, sent|wparam, 1 },
937 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
938 { WM_ERASEBKGND, sent },
939 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
940 { WM_CTLCOLORDLG, sent|defwinproc },
942 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
943 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
944 { 0 }
946 /* Creation and destruction of a modal dialog (32) */
947 static const struct message WmModalDialogSeq[] = {
948 { WM_CANCELMODE, sent|parent },
949 { HCBT_SETFOCUS, hook },
950 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
951 { WM_KILLFOCUS, sent|parent },
952 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
953 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
954 { WM_ENABLE, sent|parent|wparam, 0 },
955 { HCBT_CREATEWND, hook },
956 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
957 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
958 { WM_SETFONT, sent },
959 { WM_INITDIALOG, sent },
960 { WM_CHANGEUISTATE, sent|optional },
961 { WM_SHOWWINDOW, sent },
962 { HCBT_ACTIVATE, hook },
963 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
964 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
965 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
966 { WM_NCACTIVATE, sent|wparam, 1 },
967 { WM_GETTEXT, sent|optional },
968 { WM_ACTIVATE, sent|wparam, 1 },
969 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
970 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
971 { WM_NCPAINT, sent },
972 { WM_GETTEXT, sent|optional },
973 { WM_ERASEBKGND, sent },
974 { WM_CTLCOLORDLG, sent },
975 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
976 { WM_GETTEXT, sent|optional },
977 { WM_NCCALCSIZE, sent|optional },
978 { WM_NCPAINT, sent|optional },
979 { WM_GETTEXT, sent|optional },
980 { WM_ERASEBKGND, sent|optional },
981 { WM_CTLCOLORDLG, sent|optional },
982 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
983 { WM_PAINT, sent|optional },
984 { WM_CTLCOLORBTN, sent },
985 { WM_ENTERIDLE, sent|parent|optional },
986 { WM_ENTERIDLE, sent|parent|optional },
987 { WM_ENTERIDLE, sent|parent|optional },
988 { WM_ENTERIDLE, sent|parent|optional },
989 { WM_ENTERIDLE, sent|parent|optional },
990 { WM_ENTERIDLE, sent|parent|optional },
991 { WM_ENTERIDLE, sent|parent|optional },
992 { WM_ENTERIDLE, sent|parent|optional },
993 { WM_ENTERIDLE, sent|parent|optional },
994 { WM_ENTERIDLE, sent|parent|optional },
995 { WM_ENTERIDLE, sent|parent|optional },
996 { WM_ENTERIDLE, sent|parent|optional },
997 { WM_ENTERIDLE, sent|parent|optional },
998 { WM_ENTERIDLE, sent|parent|optional },
999 { WM_ENTERIDLE, sent|parent|optional },
1000 { WM_ENTERIDLE, sent|parent|optional },
1001 { WM_ENTERIDLE, sent|parent|optional },
1002 { WM_ENTERIDLE, sent|parent|optional },
1003 { WM_ENTERIDLE, sent|parent|optional },
1004 { WM_ENTERIDLE, sent|parent|optional },
1005 { WM_TIMER, sent },
1006 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1007 { WM_ENABLE, sent|parent|wparam, 1 },
1008 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
1009 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1010 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1011 { WM_GETTEXT, sent|optional },
1012 { HCBT_ACTIVATE, hook },
1013 { WM_NCACTIVATE, sent|wparam, 0 },
1014 { WM_GETTEXT, sent|optional },
1015 { WM_ACTIVATE, sent|wparam, 0 },
1016 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1017 { WM_WINDOWPOSCHANGING, sent|optional },
1018 { HCBT_SETFOCUS, hook },
1019 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
1020 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1021 { WM_SETFOCUS, sent|parent|defwinproc },
1022 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
1023 { HCBT_DESTROYWND, hook },
1024 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1025 { WM_DESTROY, sent },
1026 { WM_NCDESTROY, sent },
1027 { 0 }
1029 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
1030 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
1031 /* (inside dialog proc, handling WM_INITDIALOG) */
1032 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
1033 { WM_NCCALCSIZE, sent },
1034 { WM_NCACTIVATE, sent|parent|wparam, 0 },
1035 { WM_GETTEXT, sent|defwinproc },
1036 { WM_ACTIVATE, sent|parent|wparam, 0 },
1037 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
1038 { WM_WINDOWPOSCHANGING, sent|parent },
1039 { WM_NCACTIVATE, sent|wparam, 1 },
1040 { WM_ACTIVATE, sent|wparam, 1 },
1041 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
1042 { WM_SIZE, sent|defwinproc },
1043 /* (setting focus) */
1044 { WM_SHOWWINDOW, sent|wparam, 1 },
1045 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
1046 { WM_NCPAINT, sent },
1047 { WM_GETTEXT, sent|defwinproc },
1048 { WM_ERASEBKGND, sent },
1049 { WM_CTLCOLORDLG, sent|defwinproc },
1050 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
1051 { WM_PAINT, sent },
1052 /* (bunch of WM_CTLCOLOR* for each control) */
1053 { WM_PAINT, sent|parent },
1054 { WM_ENTERIDLE, sent|parent|wparam, 0 },
1055 { WM_SETCURSOR, sent|parent },
1056 { 0 }
1058 /* SetMenu for NonVisible windows with size change*/
1059 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
1060 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1061 { WM_NCCALCSIZE, sent|wparam, 1 },
1062 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1063 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW },
1064 { WM_MOVE, sent|defwinproc },
1065 { WM_SIZE, sent|defwinproc },
1066 { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */
1067 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1068 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1069 { WM_GETTEXT, sent|optional },
1070 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
1071 { 0 }
1073 /* SetMenu for NonVisible windows with no size change */
1074 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
1075 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1076 { WM_NCCALCSIZE, sent|wparam, 1 },
1077 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1078 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1079 { 0 }
1081 /* SetMenu for Visible windows with size change */
1082 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
1083 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1084 { WM_NCCALCSIZE, sent|wparam, 1 },
1085 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1086 { WM_NCPAINT, sent }, /* wparam != 1 */
1087 { WM_GETTEXT, sent|defwinproc|optional },
1088 { WM_ERASEBKGND, sent|optional },
1089 { WM_ACTIVATE, sent|optional },
1090 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1091 { WM_MOVE, sent|defwinproc },
1092 { WM_SIZE, sent|defwinproc },
1093 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
1094 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1095 { WM_ERASEBKGND, sent|optional },
1096 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1097 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1098 { 0 }
1100 /* SetMenu for Visible windows with no size change */
1101 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
1102 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1103 { WM_NCCALCSIZE, sent|wparam, 1 },
1104 { WM_NCPAINT, sent }, /* wparam != 1 */
1105 { WM_GETTEXT, sent|defwinproc|optional },
1106 { WM_ERASEBKGND, sent|optional },
1107 { WM_ACTIVATE, sent|optional },
1108 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1109 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1110 { 0 }
1112 /* DrawMenuBar for a visible window */
1113 static const struct message WmDrawMenuBarSeq[] =
1115 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1116 { WM_NCCALCSIZE, sent|wparam, 1 },
1117 { WM_NCPAINT, sent }, /* wparam != 1 */
1118 { WM_GETTEXT, sent|defwinproc|optional },
1119 { WM_ERASEBKGND, sent|optional },
1120 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1121 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1122 { 0 }
1125 static const struct message WmSetRedrawFalseSeq[] =
1127 { WM_SETREDRAW, sent|wparam, 0 },
1128 { 0 }
1131 static const struct message WmSetRedrawTrueSeq[] =
1133 { WM_SETREDRAW, sent|wparam, 1 },
1134 { 0 }
1137 static const struct message WmEnableWindowSeq_1[] =
1139 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 },
1140 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1141 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 },
1142 { 0 }
1145 static const struct message WmEnableWindowSeq_2[] =
1147 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1148 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 },
1149 { 0 }
1152 static const struct message WmGetScrollRangeSeq[] =
1154 { SBM_GETRANGE, sent },
1155 { 0 }
1157 static const struct message WmGetScrollInfoSeq[] =
1159 { SBM_GETSCROLLINFO, sent },
1160 { 0 }
1162 static const struct message WmSetScrollRangeSeq[] =
1164 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1165 sends SBM_SETSCROLLINFO.
1167 { SBM_SETSCROLLINFO, sent },
1168 { 0 }
1170 /* SetScrollRange for a window without a non-client area */
1171 static const struct message WmSetScrollRangeHSeq_empty[] =
1173 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 },
1174 { 0 }
1176 static const struct message WmSetScrollRangeVSeq_empty[] =
1178 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 },
1179 { 0 }
1181 static const struct message WmSetScrollRangeHVSeq[] =
1183 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
1184 { WM_NCCALCSIZE, sent|wparam, 1 },
1185 { WM_GETTEXT, sent|defwinproc|optional },
1186 { WM_ERASEBKGND, sent|optional },
1187 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1188 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1189 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1190 { 0 }
1192 /* SetScrollRange for a window with a non-client area */
1193 static const struct message WmSetScrollRangeHV_NC_Seq[] =
1195 { WM_WINDOWPOSCHANGING, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
1196 { WM_NCCALCSIZE, sent|wparam, 1 },
1197 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1198 { WM_NCPAINT, sent|optional },
1199 { WM_GETTEXT, sent|defwinproc|optional },
1200 { WM_GETTEXT, sent|defwinproc|optional },
1201 { WM_ERASEBKGND, sent|optional },
1202 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
1203 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
1204 { WM_SIZE, sent|defwinproc },
1205 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1206 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1207 { WM_GETTEXT, sent|optional },
1208 { WM_GETTEXT, sent|optional },
1209 { WM_GETTEXT, sent|optional },
1210 { WM_GETTEXT, sent|optional },
1211 { 0 }
1213 /* test if we receive the right sequence of messages */
1214 /* after calling ShowWindow( SW_SHOWNA) */
1215 static const struct message WmSHOWNAChildInvisParInvis[] = {
1216 { WM_SHOWWINDOW, sent|wparam, 1 },
1217 { 0 }
1219 static const struct message WmSHOWNAChildVisParInvis[] = {
1220 { WM_SHOWWINDOW, sent|wparam, 1 },
1221 { 0 }
1223 static const struct message WmSHOWNAChildVisParVis[] = {
1224 { WM_SHOWWINDOW, sent|wparam, 1 },
1225 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
1226 { 0 }
1228 static const struct message WmSHOWNAChildInvisParVis[] = {
1229 { WM_SHOWWINDOW, sent|wparam, 1 },
1230 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER},
1231 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1232 { WM_ERASEBKGND, sent|optional },
1233 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1234 { 0 }
1236 static const struct message WmSHOWNATopVisible[] = {
1237 { WM_SHOWWINDOW, sent|wparam, 1 },
1238 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
1239 { 0 }
1241 static const struct message WmSHOWNATopInvisible[] = {
1242 { WM_SHOWWINDOW, sent|wparam, 1 },
1243 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1244 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1245 { WM_NCPAINT, sent|wparam, 1 },
1246 { WM_GETTEXT, sent|defwinproc|optional },
1247 { WM_ERASEBKGND, sent|optional },
1248 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1249 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
1250 { WM_NCPAINT, sent|wparam|optional, 1 },
1251 { WM_ERASEBKGND, sent|optional },
1252 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1253 { WM_SIZE, sent },
1254 { WM_MOVE, sent },
1255 { 0 }
1258 static int after_end_dialog;
1259 static int sequence_cnt, sequence_size;
1260 static struct message* sequence;
1261 static int log_all_parent_messages;
1263 static void add_message(const struct message *msg)
1265 if (!sequence)
1267 sequence_size = 10;
1268 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
1270 if (sequence_cnt == sequence_size)
1272 sequence_size *= 2;
1273 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
1275 assert(sequence);
1277 sequence[sequence_cnt].message = msg->message;
1278 sequence[sequence_cnt].flags = msg->flags;
1279 sequence[sequence_cnt].wParam = msg->wParam;
1280 sequence[sequence_cnt].lParam = msg->lParam;
1282 sequence_cnt++;
1285 static void flush_sequence(void)
1287 HeapFree(GetProcessHeap(), 0, sequence);
1288 sequence = 0;
1289 sequence_cnt = sequence_size = 0;
1292 #define ok_sequence( exp, contx, todo) \
1293 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
1296 static void ok_sequence_(const struct message *expected, const char *context, int todo,
1297 const char *file, int line)
1299 static const struct message end_of_sequence = { 0, 0, 0, 0 };
1300 const struct message *actual;
1301 int failcount = 0;
1303 add_message(&end_of_sequence);
1305 actual = sequence;
1307 while (expected->message && actual->message)
1309 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
1311 if (expected->message == actual->message)
1313 if (expected->flags & wparam)
1315 if (expected->wParam != actual->wParam && todo)
1317 todo_wine {
1318 failcount ++;
1319 ok_( file, line) (FALSE,
1320 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1321 context, expected->message, expected->wParam, actual->wParam);
1324 else
1325 ok_( file, line) (expected->wParam == actual->wParam,
1326 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1327 context, expected->message, expected->wParam, actual->wParam);
1329 if (expected->flags & lparam)
1330 ok_( file, line) (expected->lParam == actual->lParam,
1331 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
1332 context, expected->message, expected->lParam, actual->lParam);
1333 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
1334 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
1335 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
1336 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
1337 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
1338 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
1339 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
1340 "%s: the msg 0x%04x should have been %s\n",
1341 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
1342 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
1343 "%s: the msg 0x%04x was expected in %s\n",
1344 context, expected->message, (expected->flags & parent) ? "parent" : "child");
1345 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook),
1346 "%s: the msg 0x%04x should have been sent by a hook\n",
1347 context, expected->message);
1348 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
1349 "%s: the msg 0x%04x should have been sent by a winevent hook\n",
1350 context, expected->message);
1351 expected++;
1352 actual++;
1354 /* silently drop winevent messages if there is no support for them */
1355 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))
1356 expected++;
1357 else if (todo)
1359 failcount++;
1360 todo_wine {
1361 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1362 context, expected->message, actual->message);
1364 flush_sequence();
1365 return;
1367 else
1369 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1370 context, expected->message, actual->message);
1371 expected++;
1372 actual++;
1376 /* skip all optional trailing messages */
1377 while (expected->message && ((expected->flags & optional) ||
1378 ((expected->flags & winevent_hook) && !hEvent_hook)))
1379 expected++;
1381 if (todo)
1383 todo_wine {
1384 if (expected->message || actual->message) {
1385 failcount++;
1386 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1387 context, expected->message, actual->message);
1391 else
1393 if (expected->message || actual->message)
1394 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1395 context, expected->message, actual->message);
1397 if( todo && !failcount) /* succeeded yet marked todo */
1398 todo_wine {
1399 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
1402 flush_sequence();
1405 /******************************** MDI test **********************************/
1407 /* CreateWindow for MDI frame window, initially visible */
1408 static const struct message WmCreateMDIframeSeq[] = {
1409 { HCBT_CREATEWND, hook },
1410 { WM_GETMINMAXINFO, sent },
1411 { WM_NCCREATE, sent },
1412 { WM_NCCALCSIZE, sent|wparam, 0 },
1413 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1414 { WM_CREATE, sent },
1415 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1416 { WM_SHOWWINDOW, sent|wparam, 1 },
1417 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1418 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1419 { HCBT_ACTIVATE, hook },
1420 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1421 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1422 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
1423 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* Win9x */
1424 { WM_ACTIVATEAPP, sent|wparam, 1 },
1425 { WM_NCACTIVATE, sent|wparam, 1 },
1426 { WM_GETTEXT, sent|defwinproc|optional },
1427 { WM_ACTIVATE, sent|wparam, 1 },
1428 { HCBT_SETFOCUS, hook },
1429 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1430 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1431 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
1432 /* Win9x adds SWP_NOZORDER below */
1433 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
1434 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
1435 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1436 { WM_SIZE, sent },
1437 { WM_MOVE, sent },
1438 { 0 }
1440 /* DestroyWindow for MDI frame window, initially visible */
1441 static const struct message WmDestroyMDIframeSeq[] = {
1442 { HCBT_DESTROYWND, hook },
1443 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1444 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1445 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1446 { WM_NCACTIVATE, sent|wparam, 0 },
1447 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
1448 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
1449 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
1450 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1451 { WM_DESTROY, sent },
1452 { WM_NCDESTROY, sent },
1453 { 0 }
1455 /* CreateWindow for MDI client window, initially visible */
1456 static const struct message WmCreateMDIclientSeq[] = {
1457 { HCBT_CREATEWND, hook },
1458 { WM_NCCREATE, sent },
1459 { WM_NCCALCSIZE, sent|wparam, 0 },
1460 { WM_CREATE, sent },
1461 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1462 { WM_SIZE, sent },
1463 { WM_MOVE, sent },
1464 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
1465 { WM_SHOWWINDOW, sent|wparam, 1 },
1466 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE },
1467 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1468 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1469 { 0 }
1471 /* DestroyWindow for MDI client window, initially visible */
1472 static const struct message WmDestroyMDIclientSeq[] = {
1473 { HCBT_DESTROYWND, hook },
1474 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
1475 { WM_SHOWWINDOW, sent|wparam, 0 },
1476 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1477 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1478 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1479 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1480 { WM_DESTROY, sent },
1481 { WM_NCDESTROY, sent },
1482 { 0 }
1484 /* CreateWindow for MDI child window, initially visible */
1485 static const struct message WmCreateMDIchildVisibleSeq[] = {
1486 { HCBT_CREATEWND, hook },
1487 { WM_NCCREATE, sent },
1488 { WM_NCCALCSIZE, sent|wparam, 0 },
1489 { WM_CREATE, sent },
1490 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1491 { WM_SIZE, sent },
1492 { WM_MOVE, sent },
1493 /* Win2k sends wparam set to
1494 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1495 * while Win9x doesn't bother to set child window id according to
1496 * CLIENTCREATESTRUCT.idFirstChild
1498 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1499 { WM_SHOWWINDOW, sent|wparam, 1 },
1500 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1501 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1502 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1503 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1504 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1505 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1506 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1508 /* Win9x: message sequence terminates here. */
1510 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1511 { HCBT_SETFOCUS, hook }, /* in MDI client */
1512 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1513 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1514 { WM_SETFOCUS, sent }, /* in MDI client */
1515 { HCBT_SETFOCUS, hook },
1516 { WM_KILLFOCUS, sent }, /* in MDI client */
1517 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1518 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1519 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1520 { WM_SETFOCUS, sent|defwinproc },
1521 { WM_MDIACTIVATE, sent|defwinproc },
1522 { 0 }
1524 /* DestroyWindow for MDI child window, initially visible */
1525 static const struct message WmDestroyMDIchildVisibleSeq[] = {
1526 { HCBT_DESTROYWND, hook },
1527 /* Win2k sends wparam set to
1528 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1529 * while Win9x doesn't bother to set child window id according to
1530 * CLIENTCREATESTRUCT.idFirstChild
1532 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1533 { WM_SHOWWINDOW, sent|wparam, 0 },
1534 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1535 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1536 { WM_ERASEBKGND, sent|parent|optional },
1537 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1539 /* { WM_DESTROY, sent }
1540 * Win9x: message sequence terminates here.
1543 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1544 { WM_KILLFOCUS, sent },
1545 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1546 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1547 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1548 { WM_SETFOCUS, sent }, /* in MDI client */
1550 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1551 { WM_KILLFOCUS, sent }, /* in MDI client */
1552 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1553 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1554 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1555 { WM_SETFOCUS, sent }, /* in MDI client */
1557 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1559 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1560 { WM_KILLFOCUS, sent },
1561 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1562 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1563 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1564 { WM_SETFOCUS, sent }, /* in MDI client */
1566 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1567 { WM_KILLFOCUS, sent }, /* in MDI client */
1568 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1569 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1570 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1571 { WM_SETFOCUS, sent }, /* in MDI client */
1573 { WM_DESTROY, sent },
1575 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1576 { WM_KILLFOCUS, sent },
1577 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1578 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1579 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1580 { WM_SETFOCUS, sent }, /* in MDI client */
1582 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1583 { WM_KILLFOCUS, sent }, /* in MDI client */
1584 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1585 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1586 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1587 { WM_SETFOCUS, sent }, /* in MDI client */
1589 { WM_NCDESTROY, sent },
1590 { 0 }
1592 /* CreateWindow for MDI child window, initially invisible */
1593 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1594 { HCBT_CREATEWND, hook },
1595 { WM_NCCREATE, sent },
1596 { WM_NCCALCSIZE, sent|wparam, 0 },
1597 { WM_CREATE, sent },
1598 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1599 { WM_SIZE, sent },
1600 { WM_MOVE, sent },
1601 /* Win2k sends wparam set to
1602 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1603 * while Win9x doesn't bother to set child window id according to
1604 * CLIENTCREATESTRUCT.idFirstChild
1606 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1607 { 0 }
1609 /* DestroyWindow for MDI child window, initially invisible */
1610 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1611 { HCBT_DESTROYWND, hook },
1612 /* Win2k sends wparam set to
1613 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1614 * while Win9x doesn't bother to set child window id according to
1615 * CLIENTCREATESTRUCT.idFirstChild
1617 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1618 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1619 { WM_DESTROY, sent },
1620 { WM_NCDESTROY, sent },
1621 { 0 }
1623 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1624 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1625 { HCBT_CREATEWND, hook },
1626 { WM_NCCREATE, sent },
1627 { WM_NCCALCSIZE, sent|wparam, 0 },
1628 { WM_CREATE, sent },
1629 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1630 { WM_SIZE, sent },
1631 { WM_MOVE, sent },
1632 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1633 { WM_GETMINMAXINFO, sent },
1634 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1635 { WM_NCCALCSIZE, sent|wparam, 1 },
1636 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1637 { WM_SIZE, sent|defwinproc },
1638 /* in MDI frame */
1639 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1640 { WM_NCCALCSIZE, sent|wparam, 1 },
1641 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1642 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1643 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1644 /* Win2k sends wparam set to
1645 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1646 * while Win9x doesn't bother to set child window id according to
1647 * CLIENTCREATESTRUCT.idFirstChild
1649 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1650 { WM_SHOWWINDOW, sent|wparam, 1 },
1651 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1652 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1653 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1654 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1655 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1656 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1657 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1659 /* Win9x: message sequence terminates here. */
1661 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1662 { HCBT_SETFOCUS, hook }, /* in MDI client */
1663 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1664 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1665 { WM_SETFOCUS, sent }, /* in MDI client */
1666 { HCBT_SETFOCUS, hook },
1667 { WM_KILLFOCUS, sent }, /* in MDI client */
1668 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1669 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1670 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1671 { WM_SETFOCUS, sent|defwinproc },
1672 { WM_MDIACTIVATE, sent|defwinproc },
1673 /* in MDI frame */
1674 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1675 { WM_NCCALCSIZE, sent|wparam, 1 },
1676 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1677 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1678 { 0 }
1680 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1681 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
1682 /* restore the 1st MDI child */
1683 { WM_SETREDRAW, sent|wparam, 0 },
1684 { HCBT_MINMAX, hook },
1685 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1686 { WM_NCCALCSIZE, sent|wparam, 1 },
1687 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1688 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1689 { WM_SIZE, sent|defwinproc },
1690 /* in MDI frame */
1691 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1692 { WM_NCCALCSIZE, sent|wparam, 1 },
1693 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1694 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1695 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1696 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
1697 /* create the 2nd MDI child */
1698 { HCBT_CREATEWND, hook },
1699 { WM_NCCREATE, sent },
1700 { WM_NCCALCSIZE, sent|wparam, 0 },
1701 { WM_CREATE, sent },
1702 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1703 { WM_SIZE, sent },
1704 { WM_MOVE, sent },
1705 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1706 { WM_GETMINMAXINFO, sent },
1707 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1708 { WM_NCCALCSIZE, sent|wparam, 1 },
1709 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1710 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1711 { WM_SIZE, sent|defwinproc },
1712 /* in MDI frame */
1713 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1714 { WM_NCCALCSIZE, sent|wparam, 1 },
1715 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1716 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1717 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1718 /* Win2k sends wparam set to
1719 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1720 * while Win9x doesn't bother to set child window id according to
1721 * CLIENTCREATESTRUCT.idFirstChild
1723 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1724 { WM_SHOWWINDOW, sent|wparam, 1 },
1725 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1726 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1727 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1728 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1729 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1730 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1732 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1733 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1735 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1737 /* Win9x: message sequence terminates here. */
1739 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1740 { HCBT_SETFOCUS, hook },
1741 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
1742 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
1743 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1744 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1745 { WM_SETFOCUS, sent }, /* in MDI client */
1746 { HCBT_SETFOCUS, hook },
1747 { WM_KILLFOCUS, sent }, /* in MDI client */
1748 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1749 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1750 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1751 { WM_SETFOCUS, sent|defwinproc },
1753 { WM_MDIACTIVATE, sent|defwinproc },
1754 /* in MDI frame */
1755 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1756 { WM_NCCALCSIZE, sent|wparam, 1 },
1757 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1758 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1759 { 0 }
1761 /* WM_MDICREATE MDI child window, initially visible and maximized */
1762 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
1763 { WM_MDICREATE, sent },
1764 { HCBT_CREATEWND, hook },
1765 { WM_NCCREATE, sent },
1766 { WM_NCCALCSIZE, sent|wparam, 0 },
1767 { WM_CREATE, sent },
1768 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1769 { WM_SIZE, sent },
1770 { WM_MOVE, sent },
1771 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1772 { WM_GETMINMAXINFO, sent },
1773 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1774 { WM_NCCALCSIZE, sent|wparam, 1 },
1775 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1776 { WM_SIZE, sent|defwinproc },
1778 /* in MDI frame */
1779 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1780 { WM_NCCALCSIZE, sent|wparam, 1 },
1781 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1782 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1783 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1785 /* Win2k sends wparam set to
1786 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1787 * while Win9x doesn't bother to set child window id according to
1788 * CLIENTCREATESTRUCT.idFirstChild
1790 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1791 { WM_SHOWWINDOW, sent|wparam, 1 },
1792 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1794 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1796 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1797 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1798 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1800 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1801 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1803 /* Win9x: message sequence terminates here. */
1805 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1806 { HCBT_SETFOCUS, hook }, /* in MDI client */
1807 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1808 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1809 { WM_SETFOCUS, sent }, /* in MDI client */
1810 { HCBT_SETFOCUS, hook },
1811 { WM_KILLFOCUS, sent }, /* in MDI client */
1812 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1813 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1814 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1815 { WM_SETFOCUS, sent|defwinproc },
1817 { WM_MDIACTIVATE, sent|defwinproc },
1819 /* in 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|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1823 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1825 /* in MDI frame */
1826 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1827 { WM_NCCALCSIZE, sent|wparam, 1 },
1828 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1829 { WM_MOVE, sent|defwinproc },
1830 { WM_SIZE, sent|defwinproc },
1832 /* in MDI client */
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_NOCLIENTMOVE },
1836 { WM_SIZE, sent },
1838 /* in MDI child */
1839 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1840 { WM_NCCALCSIZE, sent|wparam, 1 },
1841 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1842 { WM_SIZE, sent|defwinproc },
1844 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1845 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1846 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */
1847 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1848 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
1850 { 0 }
1852 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1853 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
1854 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
1855 { HCBT_SYSCOMMAND, hook },
1856 { WM_CLOSE, sent|defwinproc },
1857 { WM_MDIDESTROY, sent }, /* in MDI client */
1859 /* bring the 1st MDI child to top */
1860 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
1861 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
1863 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1865 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
1866 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1867 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1869 /* maximize the 1st MDI child */
1870 { HCBT_MINMAX, hook },
1871 { WM_GETMINMAXINFO, sent|defwinproc },
1872 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
1873 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1874 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
1875 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1876 { WM_SIZE, sent|defwinproc },
1878 /* restore the 2nd MDI child */
1879 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
1880 { HCBT_MINMAX, hook },
1881 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOZORDER|0x8000 },
1882 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1884 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1886 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1887 { WM_SIZE, sent|defwinproc },
1889 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1891 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
1892 /* in MDI frame */
1893 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1894 { WM_NCCALCSIZE, sent|wparam, 1 },
1895 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1896 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1897 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1899 /* bring the 1st MDI child to top */
1900 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1901 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1902 { HCBT_SETFOCUS, hook },
1903 { WM_KILLFOCUS, sent|defwinproc },
1904 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
1905 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1906 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1907 { WM_SETFOCUS, sent }, /* in MDI client */
1908 { HCBT_SETFOCUS, hook },
1909 { WM_KILLFOCUS, sent }, /* in MDI client */
1910 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1911 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1912 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1913 { WM_SETFOCUS, sent|defwinproc },
1914 { WM_MDIACTIVATE, sent|defwinproc },
1915 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1917 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1918 { WM_SHOWWINDOW, sent|wparam, 1 },
1919 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1920 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1921 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1922 { WM_MDIREFRESHMENU, sent },
1924 { HCBT_DESTROYWND, hook },
1925 /* Win2k sends wparam set to
1926 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1927 * while Win9x doesn't bother to set child window id according to
1928 * CLIENTCREATESTRUCT.idFirstChild
1930 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1931 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
1932 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1933 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1934 { WM_ERASEBKGND, sent|parent|optional },
1935 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1937 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1938 { WM_DESTROY, sent|defwinproc },
1939 { WM_NCDESTROY, sent|defwinproc },
1940 { 0 }
1942 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1943 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
1944 { WM_MDIDESTROY, sent }, /* in MDI client */
1945 { WM_SHOWWINDOW, sent|wparam, 0 },
1946 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1947 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1948 { WM_ERASEBKGND, sent|parent|optional },
1949 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1951 { HCBT_SETFOCUS, hook },
1952 { WM_KILLFOCUS, sent },
1953 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1954 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1955 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1956 { WM_SETFOCUS, sent }, /* in MDI client */
1957 { HCBT_SETFOCUS, hook },
1958 { WM_KILLFOCUS, sent }, /* in MDI client */
1959 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1960 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1961 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1962 { WM_SETFOCUS, sent },
1964 /* in MDI child */
1965 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1966 { WM_NCCALCSIZE, sent|wparam, 1 },
1967 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1968 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1970 /* in MDI frame */
1971 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1972 { WM_NCCALCSIZE, sent|wparam, 1 },
1973 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1974 { WM_MOVE, sent|defwinproc },
1975 { WM_SIZE, sent|defwinproc },
1977 /* in MDI client */
1978 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1979 { WM_NCCALCSIZE, sent|wparam, 1 },
1980 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1981 { WM_SIZE, sent },
1983 /* in MDI child */
1984 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1985 { WM_NCCALCSIZE, sent|wparam, 1 },
1986 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1987 { WM_SIZE, sent|defwinproc },
1989 /* in MDI child */
1990 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1991 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1992 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1993 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1995 /* in MDI frame */
1996 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1997 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1998 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1999 { WM_MOVE, sent|defwinproc },
2000 { WM_SIZE, sent|defwinproc },
2002 /* in MDI client */
2003 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
2004 { WM_NCCALCSIZE, sent|wparam, 1 },
2005 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
2006 { WM_SIZE, sent },
2008 /* in MDI child */
2009 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOZORDER },
2010 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2011 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
2012 { WM_SIZE, sent|defwinproc },
2013 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2014 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
2016 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */
2018 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2019 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2020 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
2021 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2022 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
2024 /* in MDI frame */
2025 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2026 { WM_NCCALCSIZE, sent|wparam, 1 },
2027 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2028 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2030 { WM_NCACTIVATE, sent|wparam, 0 },
2031 { WM_MDIACTIVATE, sent },
2033 { HCBT_MINMAX, hook },
2034 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
2035 { WM_NCCALCSIZE, sent|wparam, 1 },
2037 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2039 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2040 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE|0x8000 },
2041 { WM_SIZE, sent|defwinproc },
2043 /* in MDI child */
2044 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2045 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2046 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2047 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2049 /* in MDI frame */
2050 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2051 { WM_NCCALCSIZE, sent|wparam, 1 },
2052 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2053 { WM_MOVE, sent|defwinproc },
2054 { WM_SIZE, sent|defwinproc },
2056 /* in MDI client */
2057 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
2058 { WM_NCCALCSIZE, sent|wparam, 1 },
2059 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
2060 { WM_SIZE, sent },
2061 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2062 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
2063 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
2064 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2065 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
2067 { HCBT_SETFOCUS, hook },
2068 { WM_KILLFOCUS, sent },
2069 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2070 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2071 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2072 { WM_SETFOCUS, sent }, /* in MDI client */
2074 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
2076 { HCBT_DESTROYWND, hook },
2077 /* Win2k sends wparam set to
2078 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2079 * while Win9x doesn't bother to set child window id according to
2080 * CLIENTCREATESTRUCT.idFirstChild
2082 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
2084 { WM_SHOWWINDOW, sent|wparam, 0 },
2085 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2086 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2087 { WM_ERASEBKGND, sent|parent|optional },
2088 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2090 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
2091 { WM_DESTROY, sent },
2092 { WM_NCDESTROY, sent },
2093 { 0 }
2095 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
2096 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
2097 { HCBT_MINMAX, hook },
2098 { WM_GETMINMAXINFO, sent },
2099 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
2100 { WM_NCCALCSIZE, sent|wparam, 1 },
2101 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2102 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2104 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2105 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
2106 { HCBT_SETFOCUS, hook },
2107 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2108 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2109 { WM_SETFOCUS, sent }, /* in MDI client */
2110 { HCBT_SETFOCUS, hook },
2111 { WM_KILLFOCUS, sent }, /* in MDI client */
2112 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2113 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2114 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2115 { WM_SETFOCUS, sent|defwinproc },
2116 { WM_MDIACTIVATE, sent|defwinproc },
2117 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2118 { WM_SIZE, sent|defwinproc },
2119 /* in MDI frame */
2120 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2121 { WM_NCCALCSIZE, sent|wparam, 1 },
2122 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2123 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2124 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2125 { 0 }
2127 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
2128 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
2129 { HCBT_MINMAX, hook },
2130 { WM_GETMINMAXINFO, sent },
2131 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
2132 { WM_NCCALCSIZE, sent|wparam, 1 },
2133 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2134 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2135 { WM_SIZE, sent|defwinproc },
2136 /* in MDI frame */
2137 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2138 { WM_NCCALCSIZE, sent|wparam, 1 },
2139 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2140 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2141 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2142 { 0 }
2144 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
2145 static const struct message WmRestoreMDIchildVisibleSeq[] = {
2146 { HCBT_MINMAX, hook },
2147 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
2148 { WM_NCCALCSIZE, sent|wparam, 1 },
2149 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2150 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2151 { WM_SIZE, sent|defwinproc },
2152 /* in MDI frame */
2153 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2154 { WM_NCCALCSIZE, sent|wparam, 1 },
2155 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2156 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2157 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2158 { 0 }
2160 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
2161 static const struct message WmRestoreMDIchildInisibleSeq[] = {
2162 { HCBT_MINMAX, hook },
2163 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
2164 { WM_NCCALCSIZE, sent|wparam, 1 },
2165 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2166 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2167 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2168 { WM_SIZE, sent|defwinproc },
2169 /* in MDI frame */
2170 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
2171 { WM_NCCALCSIZE, sent|wparam, 1 },
2172 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2173 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2174 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2175 { 0 }
2178 static HWND mdi_client;
2179 static WNDPROC old_mdi_client_proc;
2181 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2183 struct message msg;
2185 /* do not log painting messages */
2186 if (message != WM_PAINT &&
2187 message != WM_ERASEBKGND &&
2188 message != WM_NCPAINT &&
2189 message != WM_NCHITTEST &&
2190 message != WM_GETTEXT &&
2191 message != WM_MDIGETACTIVE &&
2192 message != WM_GETICON &&
2193 message != WM_DEVICECHANGE)
2195 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2197 switch (message)
2199 case WM_WINDOWPOSCHANGING:
2200 case WM_WINDOWPOSCHANGED:
2202 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2204 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2205 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2206 winpos->hwnd, winpos->hwndInsertAfter,
2207 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2209 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2210 * in the high word for internal purposes
2212 wParam = winpos->flags & 0xffff;
2213 break;
2217 msg.message = message;
2218 msg.flags = sent|wparam|lparam;
2219 msg.wParam = wParam;
2220 msg.lParam = lParam;
2221 add_message(&msg);
2224 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
2227 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2229 static long defwndproc_counter = 0;
2230 LRESULT ret;
2231 struct message msg;
2233 /* do not log painting messages */
2234 if (message != WM_PAINT &&
2235 message != WM_ERASEBKGND &&
2236 message != WM_NCPAINT &&
2237 message != WM_NCHITTEST &&
2238 message != WM_GETTEXT &&
2239 message != WM_GETICON &&
2240 message != WM_DEVICECHANGE)
2242 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2244 switch (message)
2246 case WM_WINDOWPOSCHANGING:
2247 case WM_WINDOWPOSCHANGED:
2249 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2251 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2252 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2253 winpos->hwnd, winpos->hwndInsertAfter,
2254 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2256 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2257 * in the high word for internal purposes
2259 wParam = winpos->flags & 0xffff;
2260 break;
2263 case WM_MDIACTIVATE:
2265 HWND active, client = GetParent(hwnd);
2267 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
2269 if (hwnd == (HWND)lParam) /* if we are being activated */
2270 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
2271 else
2272 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
2273 break;
2277 msg.message = message;
2278 msg.flags = sent|wparam|lparam;
2279 if (defwndproc_counter) msg.flags |= defwinproc;
2280 msg.wParam = wParam;
2281 msg.lParam = lParam;
2282 add_message(&msg);
2285 defwndproc_counter++;
2286 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
2287 defwndproc_counter--;
2289 return ret;
2292 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2294 static long defwndproc_counter = 0;
2295 LRESULT ret;
2296 struct message msg;
2298 /* do not log painting messages */
2299 if (message != WM_PAINT &&
2300 message != WM_ERASEBKGND &&
2301 message != WM_NCPAINT &&
2302 message != WM_NCHITTEST &&
2303 message != WM_GETTEXT &&
2304 message != WM_GETICON &&
2305 message != WM_DEVICECHANGE)
2307 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2309 switch (message)
2311 case WM_WINDOWPOSCHANGING:
2312 case WM_WINDOWPOSCHANGED:
2314 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2316 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2317 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2318 winpos->hwnd, winpos->hwndInsertAfter,
2319 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2321 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2322 * in the high word for internal purposes
2324 wParam = winpos->flags & 0xffff;
2325 break;
2329 msg.message = message;
2330 msg.flags = sent|wparam|lparam;
2331 if (defwndproc_counter) msg.flags |= defwinproc;
2332 msg.wParam = wParam;
2333 msg.lParam = lParam;
2334 add_message(&msg);
2337 defwndproc_counter++;
2338 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
2339 defwndproc_counter--;
2341 return ret;
2344 static BOOL mdi_RegisterWindowClasses(void)
2346 WNDCLASSA cls;
2348 cls.style = 0;
2349 cls.lpfnWndProc = mdi_frame_wnd_proc;
2350 cls.cbClsExtra = 0;
2351 cls.cbWndExtra = 0;
2352 cls.hInstance = GetModuleHandleA(0);
2353 cls.hIcon = 0;
2354 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
2355 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2356 cls.lpszMenuName = NULL;
2357 cls.lpszClassName = "MDI_frame_class";
2358 if (!RegisterClassA(&cls)) return FALSE;
2360 cls.lpfnWndProc = mdi_child_wnd_proc;
2361 cls.lpszClassName = "MDI_child_class";
2362 if (!RegisterClassA(&cls)) return FALSE;
2364 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
2365 old_mdi_client_proc = cls.lpfnWndProc;
2366 cls.hInstance = GetModuleHandleA(0);
2367 cls.lpfnWndProc = mdi_client_hook_proc;
2368 cls.lpszClassName = "MDI_client_class";
2369 if (!RegisterClassA(&cls)) assert(0);
2371 return TRUE;
2374 static void test_mdi_messages(void)
2376 MDICREATESTRUCTA mdi_cs;
2377 CLIENTCREATESTRUCT client_cs;
2378 HWND mdi_frame, mdi_child, mdi_child2, active_child;
2379 BOOL zoomed;
2380 HMENU hMenu = CreateMenu();
2382 assert(mdi_RegisterWindowClasses());
2384 flush_sequence();
2386 trace("creating MDI frame window\n");
2387 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
2388 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2389 WS_MAXIMIZEBOX | WS_VISIBLE,
2390 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2391 GetDesktopWindow(), hMenu,
2392 GetModuleHandleA(0), NULL);
2393 assert(mdi_frame);
2394 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
2396 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2397 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
2399 trace("creating MDI client window\n");
2400 client_cs.hWindowMenu = 0;
2401 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
2402 mdi_client = CreateWindowExA(0, "MDI_client_class",
2403 NULL,
2404 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
2405 0, 0, 0, 0,
2406 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
2407 assert(mdi_client);
2408 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
2410 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2411 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
2413 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2414 ok(!active_child, "wrong active MDI child %p\n", active_child);
2415 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2417 SetFocus(0);
2418 flush_sequence();
2420 trace("creating invisible MDI child window\n");
2421 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2422 WS_CHILD,
2423 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2424 mdi_client, 0, GetModuleHandleA(0), NULL);
2425 assert(mdi_child);
2427 flush_sequence();
2428 ShowWindow(mdi_child, SW_SHOWNORMAL);
2429 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
2431 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2432 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2434 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2435 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2437 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2438 ok(!active_child, "wrong active MDI child %p\n", active_child);
2439 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2441 ShowWindow(mdi_child, SW_HIDE);
2442 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
2443 flush_sequence();
2445 ShowWindow(mdi_child, SW_SHOW);
2446 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
2448 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2449 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2451 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2452 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2454 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2455 ok(!active_child, "wrong active MDI child %p\n", active_child);
2456 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2458 DestroyWindow(mdi_child);
2459 flush_sequence();
2461 trace("creating visible MDI child window\n");
2462 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2463 WS_CHILD | WS_VISIBLE,
2464 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2465 mdi_client, 0, GetModuleHandleA(0), NULL);
2466 assert(mdi_child);
2467 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE);
2469 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2470 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2472 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2473 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2475 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2476 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2477 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2478 flush_sequence();
2480 DestroyWindow(mdi_child);
2481 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2483 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2484 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2486 /* Win2k: MDI client still returns a just destroyed child as active
2487 * Win9x: MDI client returns 0
2489 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2490 ok(active_child == mdi_child || /* win2k */
2491 !active_child, /* win9x */
2492 "wrong active MDI child %p\n", active_child);
2493 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2495 flush_sequence();
2497 trace("creating invisible MDI child window\n");
2498 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2499 WS_CHILD,
2500 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2501 mdi_client, 0, GetModuleHandleA(0), NULL);
2502 assert(mdi_child2);
2503 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
2505 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
2506 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
2508 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2509 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2511 /* Win2k: MDI client still returns a just destroyed child as active
2512 * Win9x: MDI client returns mdi_child2
2514 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2515 ok(active_child == mdi_child || /* win2k */
2516 active_child == mdi_child2, /* win9x */
2517 "wrong active MDI child %p\n", active_child);
2518 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2519 flush_sequence();
2521 ShowWindow(mdi_child2, SW_MAXIMIZE);
2522 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
2524 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2525 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2527 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2528 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2529 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2530 flush_sequence();
2532 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2533 ok(GetFocus() == mdi_child2 || /* win2k */
2534 GetFocus() == 0, /* win9x */
2535 "wrong focus window %p\n", GetFocus());
2537 SetFocus(0);
2538 flush_sequence();
2540 ShowWindow(mdi_child2, SW_HIDE);
2541 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2543 ShowWindow(mdi_child2, SW_RESTORE);
2544 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
2545 flush_sequence();
2547 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2548 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2550 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2551 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2552 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2553 flush_sequence();
2555 SetFocus(0);
2556 flush_sequence();
2558 ShowWindow(mdi_child2, SW_HIDE);
2559 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2561 ShowWindow(mdi_child2, SW_SHOW);
2562 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
2564 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2565 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2567 ShowWindow(mdi_child2, SW_MAXIMIZE);
2568 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
2570 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2571 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2573 ShowWindow(mdi_child2, SW_RESTORE);
2574 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
2576 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2577 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2579 SetFocus(0);
2580 flush_sequence();
2582 ShowWindow(mdi_child2, SW_HIDE);
2583 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2585 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2586 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2588 DestroyWindow(mdi_child2);
2589 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
2591 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2592 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2594 /* test for maximized MDI children */
2595 trace("creating maximized visible MDI child window 1\n");
2596 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2597 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2598 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2599 mdi_client, 0, GetModuleHandleA(0), NULL);
2600 assert(mdi_child);
2601 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
2602 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2604 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2605 ok(GetFocus() == mdi_child || /* win2k */
2606 GetFocus() == 0, /* win9x */
2607 "wrong focus window %p\n", GetFocus());
2609 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2610 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2611 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2612 flush_sequence();
2614 trace("creating maximized visible MDI child window 2\n");
2615 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2616 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2617 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2618 mdi_client, 0, GetModuleHandleA(0), NULL);
2619 assert(mdi_child2);
2620 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2621 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2622 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2624 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2625 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2627 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2628 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2629 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2630 flush_sequence();
2632 trace("destroying maximized visible MDI child window 2\n");
2633 DestroyWindow(mdi_child2);
2634 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2636 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2638 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2639 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2641 /* Win2k: MDI client still returns a just destroyed child as active
2642 * Win9x: MDI client returns 0
2644 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2645 ok(active_child == mdi_child2 || /* win2k */
2646 !active_child, /* win9x */
2647 "wrong active MDI child %p\n", active_child);
2648 flush_sequence();
2650 ShowWindow(mdi_child, SW_MAXIMIZE);
2651 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2652 flush_sequence();
2654 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2655 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2657 trace("re-creating maximized visible MDI child window 2\n");
2658 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2659 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2660 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2661 mdi_client, 0, GetModuleHandleA(0), NULL);
2662 assert(mdi_child2);
2663 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2664 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2665 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2667 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2668 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2670 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2671 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2672 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2673 flush_sequence();
2675 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
2676 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
2677 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
2679 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2680 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2681 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2683 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2684 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2685 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2686 flush_sequence();
2688 DestroyWindow(mdi_child);
2689 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2691 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2692 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2694 /* Win2k: MDI client still returns a just destroyed child as active
2695 * Win9x: MDI client returns 0
2697 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2698 ok(active_child == mdi_child || /* win2k */
2699 !active_child, /* win9x */
2700 "wrong active MDI child %p\n", active_child);
2701 flush_sequence();
2702 /* end of test for maximized MDI children */
2704 mdi_cs.szClass = "MDI_child_Class";
2705 mdi_cs.szTitle = "MDI child";
2706 mdi_cs.hOwner = GetModuleHandleA(0);
2707 mdi_cs.x = 0;
2708 mdi_cs.y = 0;
2709 mdi_cs.cx = CW_USEDEFAULT;
2710 mdi_cs.cy = CW_USEDEFAULT;
2711 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
2712 mdi_cs.lParam = 0;
2713 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
2714 ok(mdi_child != 0, "MDI child creation failed\n");
2715 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
2717 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
2719 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2720 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2722 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
2723 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2724 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2726 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2727 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2728 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2729 flush_sequence();
2731 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
2732 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
2734 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
2735 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2736 ok(!active_child, "wrong active MDI child %p\n", active_child);
2738 SetFocus(0);
2739 flush_sequence();
2741 DestroyWindow(mdi_client);
2742 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
2744 DestroyWindow(mdi_frame);
2745 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
2747 /************************* End of MDI test **********************************/
2749 static void test_WM_SETREDRAW(HWND hwnd)
2751 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
2753 flush_sequence();
2755 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
2756 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
2758 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
2759 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
2761 flush_sequence();
2762 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
2763 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
2765 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2766 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
2768 /* restore original WS_VISIBLE state */
2769 SetWindowLongA(hwnd, GWL_STYLE, style);
2771 flush_sequence();
2774 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2776 struct message msg;
2778 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2780 /* explicitly ignore WM_GETICON message */
2781 if (message == WM_GETICON) return 0;
2783 switch (message)
2785 case WM_WINDOWPOSCHANGING:
2786 case WM_WINDOWPOSCHANGED:
2788 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2790 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2791 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2792 winpos->hwnd, winpos->hwndInsertAfter,
2793 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2795 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2796 * in the high word for internal purposes
2798 wParam = winpos->flags & 0xffff;
2799 break;
2803 msg.message = message;
2804 msg.flags = sent|wparam|lparam;
2805 msg.wParam = wParam;
2806 msg.lParam = lParam;
2807 add_message(&msg);
2809 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2810 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2811 return 0;
2814 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2816 DWORD style, exstyle;
2817 INT xmin, xmax;
2818 BOOL ret;
2820 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2821 style = GetWindowLongA(hwnd, GWL_STYLE);
2822 /* do not be confused by WS_DLGFRAME set */
2823 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2825 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2826 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2828 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2829 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2830 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2831 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
2832 else
2833 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2835 style = GetWindowLongA(hwnd, GWL_STYLE);
2836 if (set) ok(style & set, "style %08lx should be set\n", set);
2837 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2839 /* a subsequent call should do nothing */
2840 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2841 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2842 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2844 xmin = 0xdeadbeef;
2845 xmax = 0xdeadbeef;
2846 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2847 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax);
2848 ok( ret, "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
2849 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2850 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
2851 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
2854 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2856 DWORD style, exstyle;
2857 SCROLLINFO si;
2858 BOOL ret;
2860 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2861 style = GetWindowLongA(hwnd, GWL_STYLE);
2862 /* do not be confused by WS_DLGFRAME set */
2863 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2865 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2866 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2868 si.cbSize = sizeof(si);
2869 si.fMask = SIF_RANGE;
2870 si.nMin = min;
2871 si.nMax = max;
2872 SetScrollInfo(hwnd, ctl, &si, TRUE);
2873 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2874 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
2875 else
2876 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2878 style = GetWindowLongA(hwnd, GWL_STYLE);
2879 if (set) ok(style & set, "style %08lx should be set\n", set);
2880 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2882 /* a subsequent call should do nothing */
2883 SetScrollInfo(hwnd, ctl, &si, TRUE);
2884 if (style & WS_HSCROLL)
2885 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2886 else if (style & WS_VSCROLL)
2887 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2888 else
2889 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2891 si.fMask = SIF_PAGE;
2892 si.nPage = 5;
2893 SetScrollInfo(hwnd, ctl, &si, FALSE);
2894 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2896 si.fMask = SIF_POS;
2897 si.nPos = max - 1;
2898 SetScrollInfo(hwnd, ctl, &si, FALSE);
2899 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2901 si.fMask = SIF_RANGE;
2902 si.nMin = 0xdeadbeef;
2903 si.nMax = 0xdeadbeef;
2904 ret = GetScrollInfo(hwnd, ctl, &si);
2905 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2906 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2907 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
2908 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
2911 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2912 static void test_scroll_messages(HWND hwnd)
2914 SCROLLINFO si;
2915 INT min, max;
2916 BOOL ret;
2918 min = 0xdeadbeef;
2919 max = 0xdeadbeef;
2920 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2921 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2922 if (sequence->message != WmGetScrollRangeSeq[0].message)
2923 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2924 /* values of min and max are undefined */
2925 flush_sequence();
2927 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE);
2928 ok( ret, "SetScrollRange error %ld\n", GetLastError());
2929 if (sequence->message != WmSetScrollRangeSeq[0].message)
2930 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2931 flush_sequence();
2933 min = 0xdeadbeef;
2934 max = 0xdeadbeef;
2935 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2936 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2937 if (sequence->message != WmGetScrollRangeSeq[0].message)
2938 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2939 /* values of min and max are undefined */
2940 flush_sequence();
2942 si.cbSize = sizeof(si);
2943 si.fMask = SIF_RANGE;
2944 si.nMin = 20;
2945 si.nMax = 160;
2946 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2947 if (sequence->message != WmSetScrollRangeSeq[0].message)
2948 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2949 flush_sequence();
2951 si.fMask = SIF_PAGE;
2952 si.nPage = 10;
2953 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2954 if (sequence->message != WmSetScrollRangeSeq[0].message)
2955 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2956 flush_sequence();
2958 si.fMask = SIF_POS;
2959 si.nPos = 20;
2960 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2961 if (sequence->message != WmSetScrollRangeSeq[0].message)
2962 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2963 flush_sequence();
2965 si.fMask = SIF_RANGE;
2966 si.nMin = 0xdeadbeef;
2967 si.nMax = 0xdeadbeef;
2968 ret = GetScrollInfo(hwnd, SB_CTL, &si);
2969 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2970 if (sequence->message != WmGetScrollInfoSeq[0].message)
2971 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2972 /* values of min and max are undefined */
2973 flush_sequence();
2975 /* set WS_HSCROLL */
2976 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2977 /* clear WS_HSCROLL */
2978 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2980 /* set WS_HSCROLL */
2981 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2982 /* clear WS_HSCROLL */
2983 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2985 /* set WS_VSCROLL */
2986 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2987 /* clear WS_VSCROLL */
2988 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2990 /* set WS_VSCROLL */
2991 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2992 /* clear WS_VSCROLL */
2993 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2996 static void test_showwindow(void)
2998 HWND hwnd, hchild;
2999 RECT rc;
3001 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3002 100, 100, 200, 200, 0, 0, 0, NULL);
3003 ok (hwnd != 0, "Failed to create overlapped window\n");
3004 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
3005 0, 0, 10, 10, hwnd, 0, 0, NULL);
3006 ok (hchild != 0, "Failed to create child\n");
3007 flush_sequence();
3009 /* ShowWindow( SW_SHOWNA) for invisible top level window */
3010 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
3011 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
3012 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", TRUE);
3013 trace("done\n");
3015 /* ShowWindow( SW_SHOWNA) for now visible top level window */
3016 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
3017 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
3018 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE);
3019 trace("done\n");
3020 /* back to invisible */
3021 ShowWindow(hchild, SW_HIDE);
3022 ShowWindow(hwnd, SW_HIDE);
3023 flush_sequence();
3024 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
3025 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
3026 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
3027 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE);
3028 trace("done\n");
3029 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
3030 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
3031 flush_sequence();
3032 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
3033 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
3034 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE);
3035 trace("done\n");
3036 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
3037 ShowWindow( hwnd, SW_SHOW);
3038 flush_sequence();
3039 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
3040 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
3041 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE);
3042 trace("done\n");
3044 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
3045 ShowWindow( hchild, SW_HIDE);
3046 flush_sequence();
3047 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
3048 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
3049 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE);
3050 trace("done\n");
3052 SetCapture(hchild);
3053 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture());
3054 DestroyWindow(hchild);
3055 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
3057 DestroyWindow(hwnd);
3058 flush_sequence();
3060 /* Popup windows */
3061 /* Test 1:
3062 * 1. Create invisible maximized popup window.
3063 * 2. Move and resize it.
3064 * 3. Show it maximized.
3066 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
3067 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
3068 100, 100, 200, 200, 0, 0, 0, NULL);
3069 ok (hwnd != 0, "Failed to create popup window\n");
3070 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
3071 trace("done\n");
3073 GetWindowRect(hwnd, &rc);
3074 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
3075 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
3076 "Invalid maximized size before ShowWindow (%ld,%ld)-(%ld,%ld)\n",
3077 rc.left, rc.top, rc.right, rc.bottom);
3078 /* Reset window's size & position */
3079 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
3080 flush_sequence();
3082 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
3083 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
3084 ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
3085 trace("done\n");
3087 GetWindowRect(hwnd, &rc);
3088 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
3089 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
3090 "Invalid maximized size after ShowWindow (%ld,%ld)-(%ld,%ld)\n",
3091 rc.left, rc.top, rc.right, rc.bottom);
3092 DestroyWindow(hwnd);
3093 flush_sequence();
3095 /* Test 2:
3096 * 1. Create invisible maximized popup window.
3097 * 2. Show it maximized.
3099 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
3100 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
3101 100, 100, 200, 200, 0, 0, 0, NULL);
3102 ok (hwnd != 0, "Failed to create popup window\n");
3103 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
3104 trace("done\n");
3106 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
3107 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
3108 ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
3109 trace("done\n");
3110 DestroyWindow(hwnd);
3111 flush_sequence();
3113 /* Test 3:
3114 * 1. Create visible maximized popup window.
3116 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
3117 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
3118 100, 100, 200, 200, 0, 0, 0, NULL);
3119 ok (hwnd != 0, "Failed to create popup window\n");
3120 ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
3121 trace("done\n");
3122 DestroyWindow(hwnd);
3123 flush_sequence();
3125 /* Test 4:
3126 * 1. Create visible popup window.
3127 * 2. Maximize it.
3129 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
3130 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE,
3131 100, 100, 200, 200, 0, 0, 0, NULL);
3132 ok (hwnd != 0, "Failed to create popup window\n");
3133 ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", TRUE);
3134 trace("done\n");
3136 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
3137 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
3138 ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", TRUE);
3139 trace("done\n");
3140 DestroyWindow(hwnd);
3141 flush_sequence();
3144 static void test_sys_menu(HWND hwnd)
3146 HMENU hmenu;
3147 UINT state;
3149 /* test existing window without CS_NOCLOSE style */
3150 hmenu = GetSystemMenu(hwnd, FALSE);
3151 ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
3153 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3154 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3155 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
3157 EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
3158 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
3160 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3161 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3162 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state);
3164 EnableMenuItem(hmenu, SC_CLOSE, 0);
3165 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
3167 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3168 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3169 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
3171 /* test new window with CS_NOCLOSE style */
3172 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW,
3173 100, 100, 200, 200, 0, 0, 0, NULL);
3174 ok (hwnd != 0, "Failed to create overlapped window\n");
3176 hmenu = GetSystemMenu(hwnd, FALSE);
3177 ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
3179 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3180 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3182 DestroyWindow(hwnd);
3185 /* test if we receive the right sequence of messages */
3186 static void test_messages(void)
3188 HWND hwnd, hparent, hchild;
3189 HWND hchild2, hbutton;
3190 HMENU hmenu;
3191 MSG msg;
3192 DWORD ret;
3194 flush_sequence();
3196 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3197 100, 100, 200, 200, 0, 0, 0, NULL);
3198 ok (hwnd != 0, "Failed to create overlapped window\n");
3199 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
3201 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
3202 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
3203 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
3205 /* test WM_SETREDRAW on a not visible top level window */
3206 test_WM_SETREDRAW(hwnd);
3208 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3209 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
3210 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
3212 ok(GetActiveWindow() == hwnd, "window should be active\n");
3213 ok(GetFocus() == hwnd, "window should have input focus\n");
3214 ShowWindow(hwnd, SW_HIDE);
3215 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
3217 ShowWindow(hwnd, SW_SHOW);
3218 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
3220 ShowWindow(hwnd, SW_HIDE);
3221 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
3223 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
3224 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE);
3226 ShowWindow(hwnd, SW_RESTORE);
3227 /* FIXME: add ok_sequence() here */
3228 flush_sequence();
3230 ShowWindow(hwnd, SW_SHOW);
3231 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
3233 ok(GetActiveWindow() == hwnd, "window should be active\n");
3234 ok(GetFocus() == hwnd, "window should have input focus\n");
3235 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3236 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
3237 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
3238 ok(GetActiveWindow() == hwnd, "window should still be active\n");
3240 /* test WM_SETREDRAW on a visible top level window */
3241 ShowWindow(hwnd, SW_SHOW);
3242 test_WM_SETREDRAW(hwnd);
3244 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
3245 test_scroll_messages(hwnd);
3247 /* test resizing and moving */
3248 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
3249 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE );
3250 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE );
3251 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE );
3253 /* popups don't get WM_GETMINMAXINFO */
3254 SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP );
3255 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED);
3256 flush_sequence();
3257 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE );
3258 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
3260 test_sys_menu(hwnd);
3262 flush_sequence();
3263 DestroyWindow(hwnd);
3264 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
3266 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3267 100, 100, 200, 200, 0, 0, 0, NULL);
3268 ok (hparent != 0, "Failed to create parent window\n");
3269 flush_sequence();
3271 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
3272 0, 0, 10, 10, hparent, 0, 0, NULL);
3273 ok (hchild != 0, "Failed to create child window\n");
3274 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
3275 DestroyWindow(hchild);
3276 flush_sequence();
3278 /* visible child window with a caption */
3279 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
3280 WS_CHILD | WS_VISIBLE | WS_CAPTION,
3281 0, 0, 10, 10, hparent, 0, 0, NULL);
3282 ok (hchild != 0, "Failed to create child window\n");
3283 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
3285 trace("testing scroll APIs on a visible child window %p\n", hchild);
3286 test_scroll_messages(hchild);
3288 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3289 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
3291 DestroyWindow(hchild);
3292 flush_sequence();
3294 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
3295 0, 0, 10, 10, hparent, 0, 0, NULL);
3296 ok (hchild != 0, "Failed to create child window\n");
3297 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
3299 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
3300 100, 100, 50, 50, hparent, 0, 0, NULL);
3301 ok (hchild2 != 0, "Failed to create child2 window\n");
3302 flush_sequence();
3304 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
3305 0, 100, 50, 50, hchild, 0, 0, NULL);
3306 ok (hbutton != 0, "Failed to create button window\n");
3308 /* test WM_SETREDRAW on a not visible child window */
3309 test_WM_SETREDRAW(hchild);
3311 ShowWindow(hchild, SW_SHOW);
3312 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
3314 ShowWindow(hchild, SW_HIDE);
3315 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
3317 ShowWindow(hchild, SW_SHOW);
3318 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
3320 /* test WM_SETREDRAW on a visible child window */
3321 test_WM_SETREDRAW(hchild);
3323 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
3324 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
3326 ShowWindow(hchild, SW_HIDE);
3327 flush_sequence();
3328 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3329 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
3331 ShowWindow(hchild, SW_HIDE);
3332 flush_sequence();
3333 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
3334 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
3336 /* DestroyWindow sequence below expects that a child has focus */
3337 SetFocus(hchild);
3338 flush_sequence();
3340 DestroyWindow(hchild);
3341 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
3342 DestroyWindow(hchild2);
3343 DestroyWindow(hbutton);
3345 flush_sequence();
3346 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
3347 0, 0, 100, 100, hparent, 0, 0, NULL);
3348 ok (hchild != 0, "Failed to create child popup window\n");
3349 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
3350 DestroyWindow(hchild);
3352 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
3353 flush_sequence();
3354 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
3355 0, 0, 100, 100, hparent, 0, 0, NULL);
3356 ok (hchild != 0, "Failed to create popup window\n");
3357 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
3358 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3359 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
3360 flush_sequence();
3361 ShowWindow(hchild, SW_SHOW);
3362 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
3363 flush_sequence();
3364 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3365 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
3366 flush_sequence();
3367 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
3368 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
3369 DestroyWindow(hchild);
3371 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
3372 * changes nothing in message sequences.
3374 flush_sequence();
3375 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
3376 0, 0, 100, 100, hparent, 0, 0, NULL);
3377 ok (hchild != 0, "Failed to create popup window\n");
3378 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
3379 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3380 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
3381 flush_sequence();
3382 ShowWindow(hchild, SW_SHOW);
3383 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
3384 flush_sequence();
3385 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3386 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
3387 DestroyWindow(hchild);
3389 flush_sequence();
3390 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
3391 0, 0, 100, 100, hparent, 0, 0, NULL);
3392 ok(hwnd != 0, "Failed to create custom dialog window\n");
3393 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
3396 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
3397 test_scroll_messages(hwnd);
3400 flush_sequence();
3401 after_end_dialog = 1;
3402 EndDialog( hwnd, 0 );
3403 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
3405 DestroyWindow(hwnd);
3406 after_end_dialog = 0;
3408 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP,
3409 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
3410 ok(hwnd != 0, "Failed to create custom dialog window\n");
3411 flush_sequence();
3412 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
3413 ShowWindow(hwnd, SW_SHOW);
3414 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
3415 DestroyWindow(hwnd);
3417 flush_sequence();
3418 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
3419 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
3421 /* test showing child with hidden parent */
3422 ShowWindow( hparent, SW_HIDE );
3423 flush_sequence();
3425 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
3426 0, 0, 10, 10, hparent, 0, 0, NULL);
3427 ok (hchild != 0, "Failed to create child window\n");
3428 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
3430 ShowWindow( hchild, SW_SHOW );
3431 ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", FALSE);
3432 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3433 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3435 ShowWindow( hchild, SW_HIDE );
3436 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE);
3437 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
3438 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3440 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3441 ok_sequence(WmShowChildInvisibleParentSeq_2, "SetWindowPos:show child with invisible parent", FALSE);
3442 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3443 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3445 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3446 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE);
3447 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
3448 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
3450 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
3451 flush_sequence();
3452 DestroyWindow(hchild);
3453 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE);
3455 DestroyWindow(hparent);
3456 flush_sequence();
3458 /* Message sequence for SetMenu */
3459 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
3460 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
3462 hmenu = CreateMenu();
3463 ok (hmenu != 0, "Failed to create menu\n");
3464 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
3465 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3466 100, 100, 200, 200, 0, hmenu, 0, NULL);
3467 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
3468 ok (SetMenu(hwnd, 0), "SetMenu\n");
3469 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
3470 ok (SetMenu(hwnd, 0), "SetMenu\n");
3471 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
3472 ShowWindow(hwnd, SW_SHOW);
3473 UpdateWindow( hwnd );
3474 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3475 flush_sequence();
3476 ok (SetMenu(hwnd, 0), "SetMenu\n");
3477 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE);
3478 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
3479 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE);
3481 UpdateWindow( hwnd );
3482 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3483 flush_sequence();
3484 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
3485 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3486 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
3488 DestroyWindow(hwnd);
3489 flush_sequence();
3491 /* Message sequence for EnableWindow */
3492 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3493 100, 100, 200, 200, 0, 0, 0, NULL);
3494 ok (hparent != 0, "Failed to create parent window\n");
3495 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
3496 0, 0, 10, 10, hparent, 0, 0, NULL);
3497 ok (hchild != 0, "Failed to create child window\n");
3499 SetFocus(hchild);
3500 flush_sequence();
3502 EnableWindow(hparent, FALSE);
3503 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE);
3505 EnableWindow(hparent, TRUE);
3506 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(TRUE)", FALSE);
3508 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3509 flush_sequence();
3511 /* MsgWaitForMultipleObjects test */
3512 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
3513 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %lx\n", ret);
3515 PostMessageA(hparent, WM_USER, 0, 0);
3517 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
3518 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %lx\n", ret);
3520 ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
3521 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
3523 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
3524 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %lx\n", ret);
3525 /* end of MsgWaitForMultipleObjects test */
3527 /* the following test causes an exception in user.exe under win9x */
3528 if (!PostMessageW( hparent, WM_USER, 0, 0 )) return;
3529 PostMessageW( hparent, WM_USER+1, 0, 0 );
3530 /* PeekMessage(NULL) fails, but still removes the message */
3531 SetLastError(0xdeadbeef);
3532 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
3533 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */
3534 GetLastError() == 0xdeadbeef, /* NT4 */
3535 "last error is %ld\n", GetLastError() );
3536 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
3537 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
3539 DestroyWindow(hchild);
3540 DestroyWindow(hparent);
3541 flush_sequence();
3543 test_showwindow();
3546 /****************** button message test *************************/
3547 static const struct message WmSetFocusButtonSeq[] =
3549 { HCBT_SETFOCUS, hook },
3550 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3551 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3552 { WM_SETFOCUS, sent|wparam, 0 },
3553 { WM_CTLCOLORBTN, sent|defwinproc },
3554 { 0 }
3556 static const struct message WmKillFocusButtonSeq[] =
3558 { HCBT_SETFOCUS, hook },
3559 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3560 { WM_KILLFOCUS, sent|wparam, 0 },
3561 { WM_CTLCOLORBTN, sent|defwinproc },
3562 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3563 { 0 }
3565 static const struct message WmSetFocusStaticSeq[] =
3567 { HCBT_SETFOCUS, hook },
3568 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3569 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3570 { WM_SETFOCUS, sent|wparam, 0 },
3571 { WM_CTLCOLORSTATIC, sent|defwinproc },
3572 { 0 }
3574 static const struct message WmKillFocusStaticSeq[] =
3576 { HCBT_SETFOCUS, hook },
3577 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3578 { WM_KILLFOCUS, sent|wparam, 0 },
3579 { WM_CTLCOLORSTATIC, sent|defwinproc },
3580 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3581 { 0 }
3583 static const struct message WmLButtonDownSeq[] =
3585 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
3586 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
3587 { HCBT_SETFOCUS, hook },
3588 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
3589 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3590 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
3591 { WM_CTLCOLORBTN, sent|defwinproc },
3592 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
3593 { WM_CTLCOLORBTN, sent|defwinproc },
3594 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3595 { 0 }
3597 static const struct message WmLButtonUpSeq[] =
3599 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
3600 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
3601 { WM_CTLCOLORBTN, sent|defwinproc },
3602 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3603 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
3604 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
3605 { 0 }
3608 static WNDPROC old_button_proc;
3610 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3612 static long defwndproc_counter = 0;
3613 LRESULT ret;
3614 struct message msg;
3616 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3618 /* explicitly ignore WM_GETICON message */
3619 if (message == WM_GETICON) return 0;
3621 msg.message = message;
3622 msg.flags = sent|wparam|lparam;
3623 if (defwndproc_counter) msg.flags |= defwinproc;
3624 msg.wParam = wParam;
3625 msg.lParam = lParam;
3626 add_message(&msg);
3628 if (message == BM_SETSTATE)
3629 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
3631 defwndproc_counter++;
3632 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
3633 defwndproc_counter--;
3635 return ret;
3638 static void subclass_button(void)
3640 WNDCLASSA cls;
3642 if (!GetClassInfoA(0, "button", &cls)) assert(0);
3644 old_button_proc = cls.lpfnWndProc;
3646 cls.hInstance = GetModuleHandle(0);
3647 cls.lpfnWndProc = button_hook_proc;
3648 cls.lpszClassName = "my_button_class";
3649 if (!RegisterClassA(&cls)) assert(0);
3652 static void test_button_messages(void)
3654 static const struct
3656 DWORD style;
3657 DWORD dlg_code;
3658 const struct message *setfocus;
3659 const struct message *killfocus;
3660 } button[] = {
3661 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3662 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3663 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
3664 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3665 { BS_CHECKBOX, DLGC_BUTTON,
3666 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3667 { BS_AUTOCHECKBOX, DLGC_BUTTON,
3668 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3669 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3670 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3671 { BS_3STATE, DLGC_BUTTON,
3672 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3673 { BS_AUTO3STATE, DLGC_BUTTON,
3674 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3675 { BS_GROUPBOX, DLGC_STATIC,
3676 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3677 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3678 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3679 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3680 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3681 { BS_OWNERDRAW, DLGC_BUTTON,
3682 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
3684 unsigned int i;
3685 HWND hwnd;
3686 DWORD dlg_code;
3688 subclass_button();
3690 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
3692 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
3693 0, 0, 50, 14, 0, 0, 0, NULL);
3694 ok(hwnd != 0, "Failed to create button window\n");
3696 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
3697 ok(dlg_code == button[i].dlg_code, "%d: wrong dlg_code %08lx\n", i, dlg_code);
3699 ShowWindow(hwnd, SW_SHOW);
3700 UpdateWindow(hwnd);
3701 SetFocus(0);
3702 flush_sequence();
3704 trace("button style %08lx\n", button[i].style);
3705 SetFocus(hwnd);
3706 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
3708 SetFocus(0);
3709 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
3711 DestroyWindow(hwnd);
3714 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
3715 0, 0, 50, 14, 0, 0, 0, NULL);
3716 ok(hwnd != 0, "Failed to create button window\n");
3718 SetFocus(0);
3719 flush_sequence();
3721 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
3722 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
3724 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
3725 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONUP on a button", FALSE);
3726 DestroyWindow(hwnd);
3729 /************* painting message test ********************/
3731 void dump_region(HRGN hrgn)
3733 DWORD i, size;
3734 RGNDATA *data = NULL;
3735 RECT *rect;
3737 if (!hrgn)
3739 printf( "null region\n" );
3740 return;
3742 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
3743 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
3744 GetRegionData( hrgn, size, data );
3745 printf("%ld rects:", data->rdh.nCount );
3746 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
3747 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
3748 printf("\n");
3749 HeapFree( GetProcessHeap(), 0, data );
3752 static void check_update_rgn( HWND hwnd, HRGN hrgn )
3754 INT ret;
3755 RECT r1, r2;
3756 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
3757 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
3759 ret = GetUpdateRgn( hwnd, update, FALSE );
3760 ok( ret != ERROR, "GetUpdateRgn failed\n" );
3761 if (ret == NULLREGION)
3763 ok( !hrgn, "Update region shouldn't be empty\n" );
3765 else
3767 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
3769 ok( 0, "Regions are different\n" );
3770 if (winetest_debug > 0)
3772 printf( "Update region: " );
3773 dump_region( update );
3774 printf( "Wanted region: " );
3775 dump_region( hrgn );
3779 GetRgnBox( update, &r1 );
3780 GetUpdateRect( hwnd, &r2, FALSE );
3781 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
3782 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
3783 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
3785 DeleteObject( tmp );
3786 DeleteObject( update );
3789 static const struct message WmInvalidateRgn[] = {
3790 { WM_NCPAINT, sent },
3791 { WM_GETTEXT, sent|defwinproc|optional },
3792 { 0 }
3795 static const struct message WmGetUpdateRect[] = {
3796 { WM_NCPAINT, sent },
3797 { WM_GETTEXT, sent|defwinproc|optional },
3798 { WM_PAINT, sent },
3799 { 0 }
3802 static const struct message WmInvalidateFull[] = {
3803 { WM_NCPAINT, sent|wparam, 1 },
3804 { WM_GETTEXT, sent|defwinproc|optional },
3805 { 0 }
3808 static const struct message WmInvalidateErase[] = {
3809 { WM_NCPAINT, sent|wparam, 1 },
3810 { WM_GETTEXT, sent|defwinproc|optional },
3811 { WM_ERASEBKGND, sent },
3812 { 0 }
3815 static const struct message WmInvalidatePaint[] = {
3816 { WM_PAINT, sent },
3817 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3818 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3819 { 0 }
3822 static const struct message WmInvalidateErasePaint[] = {
3823 { WM_PAINT, sent },
3824 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3825 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3826 { WM_ERASEBKGND, sent|beginpaint },
3827 { 0 }
3830 static const struct message WmInvalidateErasePaint2[] = {
3831 { WM_PAINT, sent },
3832 { WM_NCPAINT, sent|beginpaint },
3833 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3834 { WM_ERASEBKGND, sent|beginpaint },
3835 { 0 }
3838 static const struct message WmErase[] = {
3839 { WM_ERASEBKGND, sent },
3840 { 0 }
3843 static const struct message WmPaint[] = {
3844 { WM_PAINT, sent },
3845 { 0 }
3848 static const struct message WmParentOnlyPaint[] = {
3849 { WM_PAINT, sent|parent },
3850 { 0 }
3853 static const struct message WmInvalidateParent[] = {
3854 { WM_NCPAINT, sent|parent },
3855 { WM_GETTEXT, sent|defwinproc|parent|optional },
3856 { WM_ERASEBKGND, sent|parent },
3857 { 0 }
3860 static const struct message WmInvalidateParentChild[] = {
3861 { WM_NCPAINT, sent|parent },
3862 { WM_GETTEXT, sent|defwinproc|parent|optional },
3863 { WM_ERASEBKGND, sent|parent },
3864 { WM_NCPAINT, sent },
3865 { WM_GETTEXT, sent|defwinproc|optional },
3866 { WM_ERASEBKGND, sent },
3867 { 0 }
3870 static const struct message WmInvalidateParentChild2[] = {
3871 { WM_ERASEBKGND, sent|parent },
3872 { WM_NCPAINT, sent },
3873 { WM_GETTEXT, sent|defwinproc|optional },
3874 { WM_ERASEBKGND, sent },
3875 { 0 }
3878 static const struct message WmParentPaint[] = {
3879 { WM_PAINT, sent|parent },
3880 { WM_PAINT, sent },
3881 { 0 }
3884 static const struct message WmParentPaintNc[] = {
3885 { WM_PAINT, sent|parent },
3886 { WM_PAINT, sent },
3887 { WM_NCPAINT, sent|beginpaint },
3888 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3889 { WM_ERASEBKGND, sent|beginpaint },
3890 { 0 }
3893 static const struct message WmChildPaintNc[] = {
3894 { WM_PAINT, sent },
3895 { WM_NCPAINT, sent|beginpaint },
3896 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3897 { WM_ERASEBKGND, sent|beginpaint },
3898 { 0 }
3901 static const struct message WmParentErasePaint[] = {
3902 { WM_PAINT, sent|parent },
3903 { WM_NCPAINT, sent|parent|beginpaint },
3904 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3905 { WM_ERASEBKGND, sent|parent|beginpaint },
3906 { WM_PAINT, sent },
3907 { WM_NCPAINT, sent|beginpaint },
3908 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3909 { WM_ERASEBKGND, sent|beginpaint },
3910 { 0 }
3913 static const struct message WmParentOnlyNcPaint[] = {
3914 { WM_PAINT, sent|parent },
3915 { WM_NCPAINT, sent|parent|beginpaint },
3916 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3917 { 0 }
3920 static const struct message WmSetParentStyle[] = {
3921 { WM_STYLECHANGING, sent|parent },
3922 { WM_STYLECHANGED, sent|parent },
3923 { 0 }
3926 static void test_paint_messages(void)
3928 BOOL ret;
3929 RECT rect;
3930 POINT pt;
3931 MSG msg;
3932 HWND hparent, hchild;
3933 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
3934 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
3935 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3936 100, 100, 200, 200, 0, 0, 0, NULL);
3937 ok (hwnd != 0, "Failed to create overlapped window\n");
3939 ShowWindow( hwnd, SW_SHOW );
3940 UpdateWindow( hwnd );
3942 /* try to flush pending X expose events */
3943 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3944 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3946 check_update_rgn( hwnd, 0 );
3947 SetRectRgn( hrgn, 10, 10, 20, 20 );
3948 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3949 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
3950 check_update_rgn( hwnd, hrgn );
3951 SetRectRgn( hrgn2, 20, 20, 30, 30 );
3952 ret = RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
3953 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
3954 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
3955 check_update_rgn( hwnd, hrgn );
3956 /* validate everything */
3957 ret = RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3958 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
3959 check_update_rgn( hwnd, 0 );
3961 /* test empty region */
3962 SetRectRgn( hrgn, 10, 10, 10, 15 );
3963 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3964 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
3965 check_update_rgn( hwnd, 0 );
3966 /* test empty rect */
3967 SetRect( &rect, 10, 10, 10, 15 );
3968 ret = RedrawWindow( hwnd, &rect, NULL, RDW_INVALIDATE );
3969 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
3970 check_update_rgn( hwnd, 0 );
3972 /* flush pending messages */
3973 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3974 flush_sequence();
3976 GetClientRect( hwnd, &rect );
3977 SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top );
3978 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
3979 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
3981 trace("testing InvalidateRect(0, NULL, FALSE)\n");
3982 SetRectEmpty( &rect );
3983 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) should fail\n");
3984 check_update_rgn( hwnd, hrgn );
3985 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3986 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3987 ok_sequence( WmPaint, "Paint", FALSE );
3988 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3989 check_update_rgn( hwnd, 0 );
3991 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
3992 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
3994 trace("testing ValidateRect(0, NULL)\n");
3995 SetRectEmpty( &rect );
3996 ok(ValidateRect(0, &rect), "ValidateRect(0, &rc) should not fail\n");
3997 check_update_rgn( hwnd, hrgn );
3998 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3999 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4000 ok_sequence( WmPaint, "Paint", FALSE );
4001 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
4002 check_update_rgn( hwnd, 0 );
4004 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
4005 SetLastError(0xdeadbeef);
4006 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n");
4007 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %ld\n", GetLastError());
4008 check_update_rgn( hwnd, 0 );
4009 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4010 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
4012 trace("testing ValidateRgn(0, NULL)\n");
4013 SetLastError(0xdeadbeef);
4014 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n");
4015 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %ld\n", GetLastError());
4016 check_update_rgn( hwnd, 0 );
4017 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4018 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
4020 /* now with frame */
4021 SetRectRgn( hrgn, -5, -5, 20, 20 );
4023 /* flush pending messages */
4024 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4026 flush_sequence();
4027 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4028 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
4030 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
4031 check_update_rgn( hwnd, hrgn );
4033 flush_sequence();
4034 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
4035 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
4037 flush_sequence();
4038 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
4039 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
4041 GetClientRect( hwnd, &rect );
4042 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
4043 check_update_rgn( hwnd, hrgn );
4045 flush_sequence();
4046 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
4047 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
4049 flush_sequence();
4050 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
4051 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
4052 check_update_rgn( hwnd, 0 );
4054 flush_sequence();
4055 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
4056 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
4057 check_update_rgn( hwnd, 0 );
4059 flush_sequence();
4060 SetRectRgn( hrgn, 0, 0, 100, 100 );
4061 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
4062 SetRectRgn( hrgn, 0, 0, 50, 100 );
4063 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
4064 SetRectRgn( hrgn, 50, 0, 100, 100 );
4065 check_update_rgn( hwnd, hrgn );
4066 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
4067 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
4068 check_update_rgn( hwnd, 0 );
4070 flush_sequence();
4071 SetRectRgn( hrgn, 0, 0, 100, 100 );
4072 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
4073 SetRectRgn( hrgn, 0, 0, 100, 50 );
4074 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
4075 ok_sequence( WmErase, "Erase", FALSE );
4076 SetRectRgn( hrgn, 0, 50, 100, 100 );
4077 check_update_rgn( hwnd, hrgn );
4079 flush_sequence();
4080 SetRectRgn( hrgn, 0, 0, 100, 100 );
4081 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
4082 SetRectRgn( hrgn, 0, 0, 50, 50 );
4083 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
4084 ok_sequence( WmPaint, "Paint", FALSE );
4086 flush_sequence();
4087 SetRectRgn( hrgn, -4, -4, -2, -2 );
4088 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4089 SetRectRgn( hrgn, -200, -200, -198, -198 );
4090 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
4091 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
4093 flush_sequence();
4094 SetRectRgn( hrgn, -4, -4, -2, -2 );
4095 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4096 SetRectRgn( hrgn, -4, -4, -3, -3 );
4097 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
4098 SetRectRgn( hrgn, 0, 0, 1, 1 );
4099 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
4100 ok_sequence( WmPaint, "Paint", FALSE );
4102 flush_sequence();
4103 SetRectRgn( hrgn, -4, -4, -1, -1 );
4104 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4105 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
4106 /* make sure no WM_PAINT was generated */
4107 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4108 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
4110 flush_sequence();
4111 SetRectRgn( hrgn, -4, -4, -1, -1 );
4112 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4113 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
4115 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
4117 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
4118 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
4119 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
4120 ret = GetUpdateRect( hwnd, &rect, FALSE );
4121 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
4122 /* this will send WM_NCPAINT and validate the non client area */
4123 ret = GetUpdateRect( hwnd, &rect, TRUE );
4124 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
4126 DispatchMessage( &msg );
4128 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
4130 DestroyWindow( hwnd );
4132 /* now test with a child window */
4134 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
4135 100, 100, 200, 200, 0, 0, 0, NULL);
4136 ok (hparent != 0, "Failed to create parent window\n");
4138 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
4139 10, 10, 100, 100, hparent, 0, 0, NULL);
4140 ok (hchild != 0, "Failed to create child window\n");
4142 ShowWindow( hparent, SW_SHOW );
4143 UpdateWindow( hparent );
4144 UpdateWindow( hchild );
4145 /* try to flush pending X expose events */
4146 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
4147 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4149 flush_sequence();
4150 log_all_parent_messages++;
4152 SetRect( &rect, 0, 0, 50, 50 );
4153 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4154 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
4155 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
4157 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4158 pt.x = pt.y = 0;
4159 MapWindowPoints( hchild, hparent, &pt, 1 );
4160 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
4161 check_update_rgn( hchild, hrgn );
4162 SetRectRgn( hrgn, 0, 0, 50, 50 );
4163 check_update_rgn( hparent, hrgn );
4164 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4165 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
4166 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
4167 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
4169 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4170 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
4172 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
4173 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4174 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
4175 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
4176 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
4178 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
4179 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
4180 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
4182 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
4183 flush_sequence();
4184 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
4185 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4186 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
4188 /* flush all paint messages */
4189 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4190 flush_sequence();
4192 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
4193 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
4194 SetRectRgn( hrgn, 0, 0, 50, 50 );
4195 check_update_rgn( hparent, hrgn );
4196 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
4197 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4198 SetRectRgn( hrgn, 0, 0, 50, 50 );
4199 check_update_rgn( hparent, hrgn );
4201 /* flush all paint messages */
4202 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4203 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
4204 flush_sequence();
4206 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
4207 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4208 SetRectRgn( hrgn, 0, 0, 50, 50 );
4209 check_update_rgn( hparent, hrgn );
4210 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
4211 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4212 SetRectRgn( hrgn2, 10, 10, 50, 50 );
4213 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
4214 check_update_rgn( hparent, hrgn );
4215 /* flush all paint messages */
4216 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4217 flush_sequence();
4219 /* same as above but parent gets completely validated */
4220 SetRect( &rect, 20, 20, 30, 30 );
4221 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4222 SetRectRgn( hrgn, 20, 20, 30, 30 );
4223 check_update_rgn( hparent, hrgn );
4224 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
4225 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4226 check_update_rgn( hparent, 0 ); /* no update region */
4227 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4228 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
4230 /* make sure RDW_VALIDATE on child doesn't have the same effect */
4231 flush_sequence();
4232 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4233 SetRectRgn( hrgn, 20, 20, 30, 30 );
4234 check_update_rgn( hparent, hrgn );
4235 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
4236 SetRectRgn( hrgn, 20, 20, 30, 30 );
4237 check_update_rgn( hparent, hrgn );
4239 /* same as above but normal WM_PAINT doesn't validate parent */
4240 flush_sequence();
4241 SetRect( &rect, 20, 20, 30, 30 );
4242 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4243 SetRectRgn( hrgn, 20, 20, 30, 30 );
4244 check_update_rgn( hparent, hrgn );
4245 /* no WM_PAINT in child while parent still pending */
4246 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4247 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
4248 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4249 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
4251 flush_sequence();
4252 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4253 /* no WM_PAINT in child while parent still pending */
4254 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4255 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
4256 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
4257 /* now that parent is valid child should get WM_PAINT */
4258 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4259 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4260 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4261 ok_sequence( WmEmptySeq, "No other message", FALSE );
4263 /* same thing with WS_CLIPCHILDREN in parent */
4264 flush_sequence();
4265 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
4266 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
4267 /* changing style invalidates non client area, but we need to invalidate something else to see it */
4268 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
4269 ok_sequence( WmEmptySeq, "No message", FALSE );
4270 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
4271 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
4273 flush_sequence();
4274 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
4275 SetRectRgn( hrgn, 20, 20, 30, 30 );
4276 check_update_rgn( hparent, hrgn );
4277 /* no WM_PAINT in child while parent still pending */
4278 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4279 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
4280 /* WM_PAINT in parent first */
4281 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4282 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
4284 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
4285 flush_sequence();
4286 SetRect( &rect, 0, 0, 30, 30 );
4287 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
4288 SetRectRgn( hrgn, 0, 0, 30, 30 );
4289 check_update_rgn( hparent, hrgn );
4290 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4291 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
4293 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
4294 flush_sequence();
4295 SetRect( &rect, -10, 0, 30, 30 );
4296 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
4297 SetRect( &rect, 0, 0, 20, 20 );
4298 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
4299 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
4300 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
4302 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
4303 flush_sequence();
4304 SetRect( &rect, -10, 0, 30, 30 );
4305 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
4306 SetRect( &rect, 0, 0, 100, 100 );
4307 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
4308 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
4309 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
4310 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4311 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
4313 /* test RDW_INTERNALPAINT behavior */
4315 flush_sequence();
4316 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
4317 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4318 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
4320 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
4321 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4322 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
4324 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
4325 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4326 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
4328 assert( GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN );
4329 UpdateWindow( hparent );
4330 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4331 flush_sequence();
4332 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
4333 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4334 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
4335 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4336 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4337 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
4339 UpdateWindow( hparent );
4340 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4341 flush_sequence();
4342 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
4343 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4344 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
4345 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4346 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4347 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
4349 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
4350 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
4351 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
4352 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4353 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
4355 assert( !(GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN) );
4356 UpdateWindow( hparent );
4357 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4358 flush_sequence();
4359 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
4360 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4361 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
4362 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4363 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4364 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
4366 UpdateWindow( hparent );
4367 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4368 flush_sequence();
4369 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
4370 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4371 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
4372 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4373 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4374 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
4376 log_all_parent_messages--;
4377 DestroyWindow( hparent );
4378 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
4380 DeleteObject( hrgn );
4381 DeleteObject( hrgn2 );
4384 struct wnd_event
4386 HWND hwnd;
4387 HANDLE event;
4390 static DWORD WINAPI thread_proc(void *param)
4392 MSG msg;
4393 struct wnd_event *wnd_event = (struct wnd_event *)param;
4395 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
4396 100, 100, 200, 200, 0, 0, 0, NULL);
4397 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
4399 SetEvent(wnd_event->event);
4401 while (GetMessage(&msg, 0, 0, 0))
4403 TranslateMessage(&msg);
4404 DispatchMessage(&msg);
4407 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
4409 return 0;
4412 static void test_interthread_messages(void)
4414 HANDLE hThread;
4415 DWORD tid;
4416 WNDPROC proc;
4417 MSG msg;
4418 char buf[256];
4419 int len, expected_len;
4420 struct wnd_event wnd_event;
4421 BOOL ret;
4423 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
4424 if (!wnd_event.event)
4426 trace("skipping interthread message test under win9x\n");
4427 return;
4430 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
4431 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4433 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4435 CloseHandle(wnd_event.event);
4437 SetLastError(0xdeadbeef);
4438 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
4439 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
4441 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
4442 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
4444 expected_len = lstrlenA("window caption text");
4445 memset(buf, 0, sizeof(buf));
4446 SetLastError(0xdeadbeef);
4447 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
4448 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
4449 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
4451 msg.hwnd = wnd_event.hwnd;
4452 msg.message = WM_GETTEXT;
4453 msg.wParam = sizeof(buf);
4454 msg.lParam = (LPARAM)buf;
4455 memset(buf, 0, sizeof(buf));
4456 SetLastError(0xdeadbeef);
4457 len = DispatchMessageA(&msg);
4458 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4459 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
4461 /* the following test causes an exception in user.exe under win9x */
4462 msg.hwnd = wnd_event.hwnd;
4463 msg.message = WM_TIMER;
4464 msg.wParam = 0;
4465 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
4466 SetLastError(0xdeadbeef);
4467 len = DispatchMessageA(&msg);
4468 ok(!len && GetLastError() == 0xdeadbeef,
4469 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
4471 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
4472 ok( ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4474 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4475 CloseHandle(hThread);
4477 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
4481 static const struct message WmVkN[] = {
4482 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4483 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4484 { WM_CHAR, wparam|lparam, 'n', 1 },
4485 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
4486 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4487 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4488 { 0 }
4490 static const struct message WmShiftVkN[] = {
4491 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
4492 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
4493 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4494 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4495 { WM_CHAR, wparam|lparam, 'N', 1 },
4496 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
4497 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4498 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4499 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
4500 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
4501 { 0 }
4503 static const struct message WmCtrlVkN[] = {
4504 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4505 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4506 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4507 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4508 { WM_CHAR, wparam|lparam, 0x000e, 1 },
4509 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
4510 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4511 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4512 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4513 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4514 { 0 }
4516 static const struct message WmCtrlVkN_2[] = {
4517 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4518 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4519 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4520 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
4521 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4522 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4523 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4524 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4525 { 0 }
4527 static const struct message WmAltVkN[] = {
4528 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4529 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4530 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
4531 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
4532 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
4533 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
4534 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
4535 { HCBT_SYSCOMMAND, hook },
4536 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4537 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4538 { 0x00AE, sent|defwinproc|optional }, /* XP */
4539 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */
4540 { WM_INITMENU, sent|defwinproc },
4541 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4542 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
4543 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
4544 { WM_CAPTURECHANGED, sent|defwinproc },
4545 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
4546 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4547 { WM_EXITMENULOOP, sent|defwinproc },
4548 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
4549 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
4550 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4551 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4552 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4553 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4554 { 0 }
4556 static const struct message WmAltVkN_2[] = {
4557 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4558 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4559 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
4560 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
4561 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4562 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4563 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4564 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4565 { 0 }
4567 static const struct message WmCtrlAltVkN[] = {
4568 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4569 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4570 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4571 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4572 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
4573 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
4574 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
4575 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4576 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4577 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4578 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4579 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4580 { 0 }
4582 static const struct message WmCtrlShiftVkN[] = {
4583 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4584 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4585 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
4586 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
4587 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4588 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 },
4589 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4590 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4591 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
4592 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
4593 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4594 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4595 { 0 }
4597 static const struct message WmCtrlAltShiftVkN[] = {
4598 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4599 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4600 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4601 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4602 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 },
4603 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 },
4604 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
4605 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 },
4606 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
4607 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4608 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 },
4609 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 },
4610 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4611 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4612 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4613 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4614 { 0 }
4616 static const struct message WmAltPressRelease[] = {
4617 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4618 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4619 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4620 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4621 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 },
4622 { HCBT_SYSCOMMAND, hook },
4623 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4624 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4625 { WM_INITMENU, sent|defwinproc },
4626 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4627 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE) },
4628 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4630 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4631 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
4632 { WM_CAPTURECHANGED, sent|defwinproc },
4633 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) },
4634 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4635 { WM_EXITMENULOOP, sent|defwinproc },
4636 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4637 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4638 { 0 }
4640 static const struct message WmAltMouseButton[] = {
4641 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4642 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4643 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
4644 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
4645 { WM_LBUTTONDOWN, wparam, MK_LBUTTON, 0 },
4646 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON, 0 },
4647 { WM_LBUTTONUP, wparam, 0, 0 },
4648 { WM_LBUTTONUP, sent|wparam, 0, 0 },
4649 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4650 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4651 { 0 }
4653 static const struct message WmF1Seq[] = {
4654 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 },
4655 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 },
4656 { 0x4d, wparam|lparam, 0, 0 },
4657 { 0x4d, sent|wparam|lparam, 0, 0 },
4658 { WM_HELP, sent|defwinproc },
4659 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 },
4660 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 },
4661 { 0 }
4664 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
4666 MSG msg;
4668 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
4670 struct message log_msg;
4672 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
4674 /* ignore some unwanted messages */
4675 if (msg.message == WM_MOUSEMOVE ||
4676 msg.message == WM_GETICON ||
4677 msg.message == WM_DEVICECHANGE)
4678 continue;
4680 log_msg.message = msg.message;
4681 log_msg.flags = wparam|lparam;
4682 log_msg.wParam = msg.wParam;
4683 log_msg.lParam = msg.lParam;
4684 add_message(&log_msg);
4686 if (!hAccel || !TranslateAccelerator(hwnd, hAccel, &msg))
4688 TranslateMessage(&msg);
4689 DispatchMessage(&msg);
4694 static void test_accelerators(void)
4696 RECT rc;
4697 SHORT state;
4698 HACCEL hAccel;
4699 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4700 100, 100, 200, 200, 0, 0, 0, NULL);
4701 BOOL ret;
4703 assert(hwnd != 0);
4704 UpdateWindow(hwnd);
4705 SetFocus(hwnd);
4706 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
4708 state = GetKeyState(VK_SHIFT);
4709 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
4710 state = GetKeyState(VK_CAPITAL);
4711 ok(state == 0, "wrong CapsLock state %04x\n", state);
4713 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
4714 assert(hAccel != 0);
4716 pump_msg_loop(hwnd, 0);
4717 flush_sequence();
4719 trace("testing VK_N press/release\n");
4720 flush_sequence();
4721 keybd_event('N', 0, 0, 0);
4722 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4723 pump_msg_loop(hwnd, hAccel);
4724 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4726 trace("testing Shift+VK_N press/release\n");
4727 flush_sequence();
4728 keybd_event(VK_SHIFT, 0, 0, 0);
4729 keybd_event('N', 0, 0, 0);
4730 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4731 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4732 pump_msg_loop(hwnd, hAccel);
4733 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4735 trace("testing Ctrl+VK_N press/release\n");
4736 flush_sequence();
4737 keybd_event(VK_CONTROL, 0, 0, 0);
4738 keybd_event('N', 0, 0, 0);
4739 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4740 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4741 pump_msg_loop(hwnd, hAccel);
4742 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
4744 trace("testing Alt+VK_N press/release\n");
4745 flush_sequence();
4746 keybd_event(VK_MENU, 0, 0, 0);
4747 keybd_event('N', 0, 0, 0);
4748 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4749 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4750 pump_msg_loop(hwnd, hAccel);
4751 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
4753 trace("testing Ctrl+Alt+VK_N press/release 1\n");
4754 flush_sequence();
4755 keybd_event(VK_CONTROL, 0, 0, 0);
4756 keybd_event(VK_MENU, 0, 0, 0);
4757 keybd_event('N', 0, 0, 0);
4758 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4759 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4760 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4761 pump_msg_loop(hwnd, hAccel);
4762 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
4764 ret = DestroyAcceleratorTable(hAccel);
4765 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4767 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
4768 assert(hAccel != 0);
4770 trace("testing VK_N press/release\n");
4771 flush_sequence();
4772 keybd_event('N', 0, 0, 0);
4773 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4774 pump_msg_loop(hwnd, hAccel);
4775 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4777 trace("testing Shift+VK_N press/release\n");
4778 flush_sequence();
4779 keybd_event(VK_SHIFT, 0, 0, 0);
4780 keybd_event('N', 0, 0, 0);
4781 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4782 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4783 pump_msg_loop(hwnd, hAccel);
4784 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4786 trace("testing Ctrl+VK_N press/release 2\n");
4787 flush_sequence();
4788 keybd_event(VK_CONTROL, 0, 0, 0);
4789 keybd_event('N', 0, 0, 0);
4790 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4791 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4792 pump_msg_loop(hwnd, hAccel);
4793 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
4795 trace("testing Alt+VK_N press/release 2\n");
4796 flush_sequence();
4797 keybd_event(VK_MENU, 0, 0, 0);
4798 keybd_event('N', 0, 0, 0);
4799 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4800 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4801 pump_msg_loop(hwnd, hAccel);
4802 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
4804 trace("testing Ctrl+Alt+VK_N press/release 2\n");
4805 flush_sequence();
4806 keybd_event(VK_CONTROL, 0, 0, 0);
4807 keybd_event(VK_MENU, 0, 0, 0);
4808 keybd_event('N', 0, 0, 0);
4809 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4810 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4811 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4812 pump_msg_loop(hwnd, hAccel);
4813 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
4815 trace("testing Ctrl+Shift+VK_N press/release\n");
4816 flush_sequence();
4817 keybd_event(VK_CONTROL, 0, 0, 0);
4818 keybd_event(VK_SHIFT, 0, 0, 0);
4819 keybd_event('N', 0, 0, 0);
4820 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4821 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4822 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4823 pump_msg_loop(hwnd, hAccel);
4824 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE);
4826 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
4827 flush_sequence();
4828 keybd_event(VK_CONTROL, 0, 0, 0);
4829 keybd_event(VK_MENU, 0, 0, 0);
4830 keybd_event(VK_SHIFT, 0, 0, 0);
4831 keybd_event('N', 0, 0, 0);
4832 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4833 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4834 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4835 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4836 pump_msg_loop(hwnd, hAccel);
4837 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE);
4839 ret = DestroyAcceleratorTable(hAccel);
4840 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4842 trace("testing Alt press/release\n");
4843 flush_sequence();
4844 keybd_event(VK_MENU, 0, 0, 0);
4845 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4846 keybd_event(VK_MENU, 0, 0, 0);
4847 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4848 pump_msg_loop(hwnd, 0);
4849 /* this test doesn't pass in Wine for managed windows */
4850 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
4852 trace("testing Alt+MouseButton press/release\n");
4853 /* first, move mouse pointer inside of the window client area */
4854 GetClientRect(hwnd, &rc);
4855 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
4856 rc.left += (rc.right - rc.left)/2;
4857 rc.top += (rc.bottom - rc.top)/2;
4858 SetCursorPos(rc.left, rc.top);
4860 pump_msg_loop(hwnd, 0);
4861 flush_sequence();
4862 keybd_event(VK_MENU, 0, 0, 0);
4863 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
4864 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
4865 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4866 pump_msg_loop(hwnd, 0);
4867 ok_sequence(WmAltMouseButton, "Alt+MouseButton press/release", FALSE);
4869 keybd_event(VK_F1, 0, 0, 0);
4870 keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0);
4871 pump_msg_loop(hwnd, 0);
4872 ok_sequence(WmF1Seq, "F1 press/release", TRUE);
4874 DestroyWindow(hwnd);
4877 /************* window procedures ********************/
4879 static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message,
4880 WPARAM wParam, LPARAM lParam)
4882 static long defwndproc_counter = 0;
4883 static long beginpaint_counter = 0;
4884 LRESULT ret;
4885 struct message msg;
4887 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4889 /* explicitly ignore WM_GETICON message */
4890 if (message == WM_GETICON) return 0;
4892 switch (message)
4894 case WM_ENABLE:
4896 LONG style = GetWindowLongA(hwnd, GWL_STYLE);
4897 ok((BOOL)wParam == !(style & WS_DISABLED),
4898 "wrong WS_DISABLED state: %d != %d\n", wParam, !(style & WS_DISABLED));
4899 break;
4902 case WM_CAPTURECHANGED:
4903 if (test_DestroyWindow_flag)
4905 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
4906 if (style & WS_CHILD)
4907 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
4908 else if (style & WS_POPUP)
4909 lParam = WND_POPUP_ID;
4910 else
4911 lParam = WND_PARENT_ID;
4913 break;
4915 case WM_NCDESTROY:
4917 HWND capture;
4919 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
4920 capture = GetCapture();
4921 if (capture)
4923 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture);
4924 trace("current capture %p, releasing...\n", capture);
4925 ReleaseCapture();
4928 /* fall through */
4929 case WM_DESTROY:
4930 if (pGetAncestor)
4931 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n");
4932 if (test_DestroyWindow_flag)
4934 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
4935 if (style & WS_CHILD)
4936 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
4937 else if (style & WS_POPUP)
4938 lParam = WND_POPUP_ID;
4939 else
4940 lParam = WND_PARENT_ID;
4942 break;
4944 /* test_accelerators() depends on this */
4945 case WM_NCHITTEST:
4946 return HTCLIENT;
4948 /* ignore */
4949 case WM_MOUSEMOVE:
4950 case WM_SETCURSOR:
4951 case WM_DEVICECHANGE:
4952 return 0;
4954 case WM_WINDOWPOSCHANGING:
4955 case WM_WINDOWPOSCHANGED:
4957 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4959 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4960 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4961 winpos->hwnd, winpos->hwndInsertAfter,
4962 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4964 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4965 * in the high word for internal purposes
4967 wParam = winpos->flags & 0xffff;
4968 break;
4972 msg.message = message;
4973 msg.flags = sent|wparam|lparam;
4974 if (defwndproc_counter) msg.flags |= defwinproc;
4975 if (beginpaint_counter) msg.flags |= beginpaint;
4976 msg.wParam = wParam;
4977 msg.lParam = lParam;
4978 add_message(&msg);
4980 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
4982 HWND parent = GetParent(hwnd);
4983 RECT rc;
4984 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
4986 GetClientRect(parent, &rc);
4987 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
4989 trace("ptReserved = (%ld,%ld)\n"
4990 "ptMaxSize = (%ld,%ld)\n"
4991 "ptMaxPosition = (%ld,%ld)\n"
4992 "ptMinTrackSize = (%ld,%ld)\n"
4993 "ptMaxTrackSize = (%ld,%ld)\n",
4994 minmax->ptReserved.x, minmax->ptReserved.y,
4995 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
4996 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
4997 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
4998 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
5000 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
5001 minmax->ptMaxSize.x, rc.right);
5002 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
5003 minmax->ptMaxSize.y, rc.bottom);
5006 if (message == WM_PAINT)
5008 PAINTSTRUCT ps;
5009 beginpaint_counter++;
5010 BeginPaint( hwnd, &ps );
5011 beginpaint_counter--;
5012 EndPaint( hwnd, &ps );
5013 return 0;
5016 defwndproc_counter++;
5017 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam)
5018 : DefWindowProcA(hwnd, message, wParam, lParam);
5019 defwndproc_counter--;
5021 return ret;
5024 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5026 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);
5029 static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5031 return MsgCheckProc (TRUE, hwnd, message, wParam, lParam);
5034 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5036 static long defwndproc_counter = 0;
5037 LRESULT ret;
5038 struct message msg;
5040 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
5042 /* explicitly ignore WM_GETICON message */
5043 if (message == WM_GETICON) return 0;
5045 msg.message = message;
5046 msg.flags = sent|wparam|lparam;
5047 if (defwndproc_counter) msg.flags |= defwinproc;
5048 msg.wParam = wParam;
5049 msg.lParam = lParam;
5050 add_message(&msg);
5052 if (message == WM_CREATE)
5054 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
5055 SetWindowLongA(hwnd, GWL_STYLE, style);
5058 defwndproc_counter++;
5059 ret = DefWindowProcA(hwnd, message, wParam, lParam);
5060 defwndproc_counter--;
5062 return ret;
5065 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5067 static long defwndproc_counter = 0;
5068 static long beginpaint_counter = 0;
5069 LRESULT ret;
5070 struct message msg;
5072 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
5074 /* explicitly ignore WM_GETICON message */
5075 if (message == WM_GETICON) return 0;
5077 if (log_all_parent_messages ||
5078 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
5079 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
5080 message == WM_ENABLE || message == WM_ENTERIDLE ||
5081 message == WM_IME_SETCONTEXT)
5083 switch (message)
5085 case WM_ERASEBKGND:
5087 RECT rc;
5088 INT ret = GetClipBox((HDC)wParam, &rc);
5090 trace("WM_ERASEBKGND: GetClipBox()=%d, (%ld,%ld-%ld,%ld)\n",
5091 ret, rc.left, rc.top, rc.right, rc.bottom);
5092 break;
5095 case WM_WINDOWPOSCHANGING:
5096 case WM_WINDOWPOSCHANGED:
5098 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
5100 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
5101 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
5102 winpos->hwnd, winpos->hwndInsertAfter,
5103 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
5105 /* Log only documented flags, win2k uses 0x1000 and 0x2000
5106 * in the high word for internal purposes
5108 wParam = winpos->flags & 0xffff;
5109 break;
5113 msg.message = message;
5114 msg.flags = sent|parent|wparam|lparam;
5115 if (defwndproc_counter) msg.flags |= defwinproc;
5116 if (beginpaint_counter) msg.flags |= beginpaint;
5117 msg.wParam = wParam;
5118 msg.lParam = lParam;
5119 add_message(&msg);
5122 if (message == WM_PAINT)
5124 PAINTSTRUCT ps;
5125 beginpaint_counter++;
5126 BeginPaint( hwnd, &ps );
5127 beginpaint_counter--;
5128 EndPaint( hwnd, &ps );
5129 return 0;
5132 defwndproc_counter++;
5133 ret = DefWindowProcA(hwnd, message, wParam, lParam);
5134 defwndproc_counter--;
5136 return ret;
5139 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5141 static long defwndproc_counter = 0;
5142 LRESULT ret;
5143 struct message msg;
5145 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
5147 /* explicitly ignore WM_GETICON message */
5148 if (message == WM_GETICON) return 0;
5150 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
5151 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
5152 if (after_end_dialog)
5153 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
5154 else
5155 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
5157 switch (message)
5159 case WM_WINDOWPOSCHANGING:
5160 case WM_WINDOWPOSCHANGED:
5162 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
5164 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
5165 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
5166 winpos->hwnd, winpos->hwndInsertAfter,
5167 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
5169 /* Log only documented flags, win2k uses 0x1000 and 0x2000
5170 * in the high word for internal purposes
5172 wParam = winpos->flags & 0xffff;
5173 break;
5177 msg.message = message;
5178 msg.flags = sent|wparam|lparam;
5179 if (defwndproc_counter) msg.flags |= defwinproc;
5180 msg.wParam = wParam;
5181 msg.lParam = lParam;
5182 add_message(&msg);
5184 defwndproc_counter++;
5185 ret = DefDlgProcA(hwnd, message, wParam, lParam);
5186 defwndproc_counter--;
5188 return ret;
5191 static BOOL RegisterWindowClasses(void)
5193 WNDCLASSA cls;
5195 cls.style = 0;
5196 cls.lpfnWndProc = MsgCheckProcA;
5197 cls.cbClsExtra = 0;
5198 cls.cbWndExtra = 0;
5199 cls.hInstance = GetModuleHandleA(0);
5200 cls.hIcon = 0;
5201 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
5202 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5203 cls.lpszMenuName = NULL;
5204 cls.lpszClassName = "TestWindowClass";
5205 if(!RegisterClassA(&cls)) return FALSE;
5207 cls.lpfnWndProc = PopupMsgCheckProcA;
5208 cls.lpszClassName = "TestPopupClass";
5209 if(!RegisterClassA(&cls)) return FALSE;
5211 cls.lpfnWndProc = ParentMsgCheckProcA;
5212 cls.lpszClassName = "TestParentClass";
5213 if(!RegisterClassA(&cls)) return FALSE;
5215 cls.lpfnWndProc = DefWindowProcA;
5216 cls.lpszClassName = "SimpleWindowClass";
5217 if(!RegisterClassA(&cls)) return FALSE;
5219 cls.style = CS_NOCLOSE;
5220 cls.lpszClassName = "NoCloseWindowClass";
5221 if(!RegisterClassA(&cls)) return FALSE;
5223 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
5224 cls.style = 0;
5225 cls.hInstance = GetModuleHandleA(0);
5226 cls.hbrBackground = 0;
5227 cls.lpfnWndProc = TestDlgProcA;
5228 cls.lpszClassName = "TestDialogClass";
5229 if(!RegisterClassA(&cls)) return FALSE;
5231 return TRUE;
5234 static HHOOK hCBT_hook;
5235 static DWORD cbt_hook_thread_id;
5237 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
5239 static const char *CBT_code_name[10] = {
5240 "HCBT_MOVESIZE",
5241 "HCBT_MINMAX",
5242 "HCBT_QS",
5243 "HCBT_CREATEWND",
5244 "HCBT_DESTROYWND",
5245 "HCBT_ACTIVATE",
5246 "HCBT_CLICKSKIPPED",
5247 "HCBT_KEYSKIPPED",
5248 "HCBT_SYSCOMMAND",
5249 "HCBT_SETFOCUS" };
5250 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
5251 HWND hwnd;
5252 char buf[256];
5254 trace("CBT: %d (%s), %08x, %08lx\n", nCode, code_name, wParam, lParam);
5256 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
5258 if (nCode == HCBT_SYSCOMMAND)
5260 struct message msg;
5262 msg.message = nCode;
5263 msg.flags = hook|wparam|lparam;
5264 msg.wParam = wParam;
5265 msg.lParam = lParam;
5266 add_message(&msg);
5268 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
5271 if (nCode == HCBT_DESTROYWND)
5273 if (test_DestroyWindow_flag)
5275 DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE);
5276 if (style & WS_CHILD)
5277 lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID);
5278 else if (style & WS_POPUP)
5279 lParam = WND_POPUP_ID;
5280 else
5281 lParam = WND_PARENT_ID;
5285 /* Log also SetFocus(0) calls */
5286 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
5288 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5290 if (!lstrcmpiA(buf, "TestWindowClass") ||
5291 !lstrcmpiA(buf, "TestParentClass") ||
5292 !lstrcmpiA(buf, "TestPopupClass") ||
5293 !lstrcmpiA(buf, "SimpleWindowClass") ||
5294 !lstrcmpiA(buf, "TestDialogClass") ||
5295 !lstrcmpiA(buf, "MDI_frame_class") ||
5296 !lstrcmpiA(buf, "MDI_client_class") ||
5297 !lstrcmpiA(buf, "MDI_child_class") ||
5298 !lstrcmpiA(buf, "my_button_class") ||
5299 !lstrcmpiA(buf, "my_edit_class") ||
5300 !lstrcmpiA(buf, "static") ||
5301 !lstrcmpiA(buf, "#32770"))
5303 struct message msg;
5305 msg.message = nCode;
5306 msg.flags = hook|wparam|lparam;
5307 msg.wParam = wParam;
5308 msg.lParam = lParam;
5309 add_message(&msg);
5312 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
5315 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
5316 DWORD event,
5317 HWND hwnd,
5318 LONG object_id,
5319 LONG child_id,
5320 DWORD thread_id,
5321 DWORD event_time)
5323 char buf[256];
5325 trace("WEH:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
5326 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
5328 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
5330 /* ignore mouse cursor events */
5331 if (object_id == OBJID_CURSOR) return;
5333 if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf)))
5335 if (!hwnd ||
5336 !lstrcmpiA(buf, "TestWindowClass") ||
5337 !lstrcmpiA(buf, "TestParentClass") ||
5338 !lstrcmpiA(buf, "TestPopupClass") ||
5339 !lstrcmpiA(buf, "SimpleWindowClass") ||
5340 !lstrcmpiA(buf, "TestDialogClass") ||
5341 !lstrcmpiA(buf, "MDI_frame_class") ||
5342 !lstrcmpiA(buf, "MDI_client_class") ||
5343 !lstrcmpiA(buf, "MDI_child_class") ||
5344 !lstrcmpiA(buf, "my_button_class") ||
5345 !lstrcmpiA(buf, "my_edit_class") ||
5346 !lstrcmpiA(buf, "static") ||
5347 !lstrcmpiA(buf, "#32770"))
5349 struct message msg;
5351 msg.message = event;
5352 msg.flags = winevent_hook|wparam|lparam;
5353 msg.wParam = object_id;
5354 msg.lParam = child_id;
5355 add_message(&msg);
5360 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
5361 static const WCHAR wszAnsi[] = {'U',0};
5363 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5365 switch (uMsg)
5367 case CB_FINDSTRINGEXACT:
5368 trace("String: %p\n", (LPCWSTR)lParam);
5369 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
5370 return 1;
5371 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
5372 return 0;
5373 return -1;
5375 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
5378 static const struct message WmGetTextLengthAfromW[] = {
5379 { WM_GETTEXTLENGTH, sent },
5380 { WM_GETTEXT, sent },
5381 { 0 }
5384 static const WCHAR testWindowClassW[] =
5385 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
5387 static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0};
5389 /* dummy window proc for WM_GETTEXTLENGTH test */
5390 static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
5392 switch(msg)
5394 case WM_GETTEXTLENGTH:
5395 return lstrlenW(dummy_window_text) + 37; /* some random length */
5396 case WM_GETTEXT:
5397 lstrcpynW( (LPWSTR)lp, dummy_window_text, wp );
5398 return lstrlenW( (LPWSTR)lp );
5399 default:
5400 return DefWindowProcW( hwnd, msg, wp, lp );
5404 static void test_message_conversion(void)
5406 static const WCHAR wszMsgConversionClass[] =
5407 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
5408 WNDCLASSW cls;
5409 LRESULT lRes;
5410 HWND hwnd;
5411 WNDPROC wndproc, newproc;
5412 BOOL ret;
5414 cls.style = 0;
5415 cls.lpfnWndProc = MsgConversionProcW;
5416 cls.cbClsExtra = 0;
5417 cls.cbWndExtra = 0;
5418 cls.hInstance = GetModuleHandleW(NULL);
5419 cls.hIcon = NULL;
5420 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
5421 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
5422 cls.lpszMenuName = NULL;
5423 cls.lpszClassName = wszMsgConversionClass;
5424 /* this call will fail on Win9x, but that doesn't matter as this test is
5425 * meaningless on those platforms */
5426 if(!RegisterClassW(&cls)) return;
5428 cls.style = 0;
5429 cls.lpfnWndProc = MsgCheckProcW;
5430 cls.cbClsExtra = 0;
5431 cls.cbWndExtra = 0;
5432 cls.hInstance = GetModuleHandleW(0);
5433 cls.hIcon = 0;
5434 cls.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
5435 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5436 cls.lpszMenuName = NULL;
5437 cls.lpszClassName = testWindowClassW;
5438 if(!RegisterClassW(&cls)) return;
5440 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
5441 100, 100, 200, 200, 0, 0, 0, NULL);
5442 ok(hwnd != NULL, "Window creation failed\n");
5444 /* {W, A} -> A */
5446 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
5447 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5448 ok(lRes == 0, "String should have been converted\n");
5449 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5450 ok(lRes == 1, "String shouldn't have been converted\n");
5452 /* {W, A} -> W */
5454 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
5455 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5456 ok(lRes == 1, "String shouldn't have been converted\n");
5457 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5458 ok(lRes == 1, "String shouldn't have been converted\n");
5460 /* Synchronous messages */
5462 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5463 ok(lRes == 0, "String should have been converted\n");
5464 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5465 ok(lRes == 1, "String shouldn't have been converted\n");
5467 /* Asynchronous messages */
5469 SetLastError(0);
5470 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5471 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5472 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5473 SetLastError(0);
5474 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5475 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5476 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5477 SetLastError(0);
5478 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5479 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5480 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5481 SetLastError(0);
5482 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5483 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5484 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5485 SetLastError(0);
5486 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5487 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5488 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5489 SetLastError(0);
5490 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5491 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5492 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5493 SetLastError(0);
5494 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
5495 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5496 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5497 SetLastError(0);
5498 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
5499 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5500 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5502 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
5504 hwnd = CreateWindowW (testWindowClassW, wszUnicode,
5505 WS_OVERLAPPEDWINDOW,
5506 100, 100, 200, 200, 0, 0, 0, NULL);
5507 assert(hwnd);
5508 flush_sequence();
5509 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0);
5510 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
5511 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
5512 "got bad length %ld\n", lRes );
5514 flush_sequence();
5515 lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ),
5516 hwnd, WM_GETTEXTLENGTH, 0, 0);
5517 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
5518 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
5519 "got bad length %ld\n", lRes );
5521 wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc );
5522 newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC );
5523 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
5524 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
5525 NULL, 0, NULL, NULL ),
5526 "got bad length %ld\n", lRes );
5528 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */
5529 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
5530 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
5531 NULL, 0, NULL, NULL ),
5532 "got bad length %ld\n", lRes );
5534 ret = DestroyWindow(hwnd);
5535 ok( ret, "DestroyWindow() error %ld\n", GetLastError());
5538 typedef struct _thread_info
5540 HWND hWnd;
5541 HANDLE handles[2];
5542 DWORD id;
5543 } thread_info;
5545 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
5549 #define TIMER_ID 0x19
5551 static DWORD WINAPI timer_thread_proc(LPVOID x)
5553 thread_info *info = x;
5554 DWORD r;
5556 r = KillTimer(info->hWnd, 0x19);
5557 ok(r,"KillTimer failed in thread\n");
5558 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
5559 ok(r,"SetTimer failed in thread\n");
5560 ok(r==TIMER_ID,"SetTimer id different\n");
5561 r = SetEvent(info->handles[0]);
5562 ok(r,"SetEvent failed in thread\n");
5563 return 0;
5566 static void test_timers(void)
5568 thread_info info;
5569 DWORD id;
5571 info.hWnd = CreateWindow ("TestWindowClass", NULL,
5572 WS_OVERLAPPEDWINDOW ,
5573 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5574 NULL, NULL, 0);
5576 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
5577 ok(info.id, "SetTimer failed\n");
5578 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
5579 info.handles[0] = CreateEvent(NULL,0,0,NULL);
5580 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
5582 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
5584 WaitForSingleObject(info.handles[1], INFINITE);
5586 CloseHandle(info.handles[0]);
5587 CloseHandle(info.handles[1]);
5589 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
5591 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
5594 /* Various win events with arbitrary parameters */
5595 static const struct message WmWinEventsSeq[] = {
5596 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
5597 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
5598 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
5599 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
5600 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
5601 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
5602 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
5603 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
5604 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
5605 /* our win event hook ignores OBJID_CURSOR events */
5606 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
5607 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
5608 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
5609 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
5610 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
5611 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
5612 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
5613 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
5614 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
5615 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
5616 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
5617 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
5618 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
5619 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
5620 { 0 }
5622 static const struct message WmWinEventCaretSeq[] = {
5623 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5624 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5625 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */
5626 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5627 { 0 }
5629 static const struct message WmWinEventCaretSeq_2[] = {
5630 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5631 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5632 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5633 { 0 }
5635 static const struct message WmWinEventAlertSeq[] = {
5636 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 },
5637 { 0 }
5639 static const struct message WmWinEventAlertSeq_2[] = {
5640 /* create window in the thread proc */
5641 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 },
5642 /* our test event */
5643 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 },
5644 { 0 }
5646 static const struct message WmGlobalHookSeq_1[] = {
5647 /* create window in the thread proc */
5648 { HCBT_CREATEWND, hook|lparam, 0, 2 },
5649 /* our test events */
5650 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 },
5651 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 },
5652 { 0 }
5654 static const struct message WmGlobalHookSeq_2[] = {
5655 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */
5656 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */
5657 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */
5658 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */
5659 { 0 }
5662 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent,
5663 DWORD event,
5664 HWND hwnd,
5665 LONG object_id,
5666 LONG child_id,
5667 DWORD thread_id,
5668 DWORD event_time)
5670 char buf[256];
5672 trace("WEH_2:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
5673 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
5675 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5677 if (!lstrcmpiA(buf, "TestWindowClass") ||
5678 !lstrcmpiA(buf, "static"))
5680 struct message msg;
5682 msg.message = event;
5683 msg.flags = winevent_hook|wparam|lparam;
5684 msg.wParam = object_id;
5685 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2);
5686 add_message(&msg);
5691 static HHOOK hCBT_global_hook;
5692 static DWORD cbt_global_hook_thread_id;
5694 static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
5696 HWND hwnd;
5697 char buf[256];
5699 trace("CBT_2: %d, %08x, %08lx\n", nCode, wParam, lParam);
5701 if (nCode == HCBT_SYSCOMMAND)
5703 struct message msg;
5705 msg.message = nCode;
5706 msg.flags = hook|wparam|lparam;
5707 msg.wParam = wParam;
5708 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
5709 add_message(&msg);
5711 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
5714 /* Log also SetFocus(0) calls */
5715 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
5717 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5719 if (!lstrcmpiA(buf, "TestWindowClass") ||
5720 !lstrcmpiA(buf, "static"))
5722 struct message msg;
5724 msg.message = nCode;
5725 msg.flags = hook|wparam|lparam;
5726 msg.wParam = wParam;
5727 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
5728 add_message(&msg);
5731 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
5734 static DWORD WINAPI win_event_global_thread_proc(void *param)
5736 HWND hwnd;
5737 MSG msg;
5738 HANDLE hevent = *(HANDLE *)param;
5739 HMODULE user32 = GetModuleHandleA("user32.dll");
5740 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
5742 assert(pNotifyWinEvent);
5744 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
5745 assert(hwnd);
5746 trace("created thread window %p\n", hwnd);
5748 *(HWND *)param = hwnd;
5750 flush_sequence();
5751 /* this event should be received only by our new hook proc,
5752 * an old one does not expect an event from another thread.
5754 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0);
5755 SetEvent(hevent);
5757 while (GetMessage(&msg, 0, 0, 0))
5759 TranslateMessage(&msg);
5760 DispatchMessage(&msg);
5762 return 0;
5765 static DWORD WINAPI cbt_global_hook_thread_proc(void *param)
5767 HWND hwnd;
5768 MSG msg;
5769 HANDLE hevent = *(HANDLE *)param;
5771 flush_sequence();
5772 /* these events should be received only by our new hook proc,
5773 * an old one does not expect an event from another thread.
5776 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
5777 assert(hwnd);
5778 trace("created thread window %p\n", hwnd);
5780 *(HWND *)param = hwnd;
5782 /* Windows doesn't like when a thread plays games with the focus,
5783 that leads to all kinds of misbehaviours and failures to activate
5784 a window. So, better keep next lines commented out.
5785 SetFocus(0);
5786 SetFocus(hwnd);*/
5788 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
5789 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
5791 SetEvent(hevent);
5793 while (GetMessage(&msg, 0, 0, 0))
5795 TranslateMessage(&msg);
5796 DispatchMessage(&msg);
5798 return 0;
5801 static void test_winevents(void)
5803 BOOL ret;
5804 MSG msg;
5805 HWND hwnd, hwnd2;
5806 UINT i;
5807 HANDLE hthread, hevent;
5808 DWORD tid;
5809 HWINEVENTHOOK hhook;
5810 const struct message *events = WmWinEventsSeq;
5811 HMODULE user32 = GetModuleHandleA("user32.dll");
5812 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
5813 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
5814 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
5816 hwnd = CreateWindowExA(0, "TestWindowClass", NULL,
5817 WS_OVERLAPPEDWINDOW,
5818 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5819 NULL, NULL, 0);
5820 assert(hwnd);
5822 /****** start of global hook test *************/
5823 hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0);
5824 assert(hCBT_global_hook);
5826 hevent = CreateEventA(NULL, 0, 0, NULL);
5827 assert(hevent);
5828 hwnd2 = (HWND)hevent;
5830 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid);
5831 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5833 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5835 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
5837 flush_sequence();
5838 /* this one should be received only by old hook proc */
5839 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
5840 /* this one should be received only by old hook proc */
5841 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
5843 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
5845 ret = UnhookWindowsHookEx(hCBT_global_hook);
5846 ok( ret, "UnhookWindowsHookEx error %ld\n", GetLastError());
5848 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5849 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5850 CloseHandle(hthread);
5851 CloseHandle(hevent);
5852 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5853 /****** end of global hook test *************/
5855 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent)
5857 ok(DestroyWindow(hwnd), "failed to destroy window\n");
5858 return;
5861 flush_sequence();
5863 #if 0 /* this test doesn't pass under Win9x */
5864 /* win2k ignores events with hwnd == 0 */
5865 SetLastError(0xdeadbeef);
5866 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
5867 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
5868 GetLastError() == 0xdeadbeef, /* Win9x */
5869 "unexpected error %ld\n", GetLastError());
5870 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
5871 #endif
5873 for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
5874 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
5876 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
5878 /****** start of event filtering test *************/
5879 hhook = (HWINEVENTHOOK)pSetWinEventHook(
5880 EVENT_OBJECT_SHOW, /* 0x8002 */
5881 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */
5882 GetModuleHandleA(0), win_event_global_hook_proc,
5883 GetCurrentProcessId(), 0,
5884 WINEVENT_INCONTEXT);
5885 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
5887 hevent = CreateEventA(NULL, 0, 0, NULL);
5888 assert(hevent);
5889 hwnd2 = (HWND)hevent;
5891 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
5892 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5894 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5896 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
5898 flush_sequence();
5899 /* this one should be received only by old hook proc */
5900 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
5901 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
5902 /* this one should be received only by old hook proc */
5903 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
5905 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
5907 ret = pUnhookWinEvent(hhook);
5908 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5910 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5911 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5912 CloseHandle(hthread);
5913 CloseHandle(hevent);
5914 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5915 /****** end of event filtering test *************/
5917 /****** start of out of context event test *************/
5918 hhook = (HWINEVENTHOOK)pSetWinEventHook(
5919 EVENT_MIN, EVENT_MAX,
5920 0, win_event_global_hook_proc,
5921 GetCurrentProcessId(), 0,
5922 WINEVENT_OUTOFCONTEXT);
5923 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
5925 hevent = CreateEventA(NULL, 0, 0, NULL);
5926 assert(hevent);
5927 hwnd2 = (HWND)hevent;
5929 flush_sequence();
5931 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
5932 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5934 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5936 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
5937 /* process pending winevent messages */
5938 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
5939 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
5941 flush_sequence();
5942 /* this one should be received only by old hook proc */
5943 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
5944 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
5945 /* this one should be received only by old hook proc */
5946 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
5948 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE);
5949 /* process pending winevent messages */
5950 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
5951 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
5953 ret = pUnhookWinEvent(hhook);
5954 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5956 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5957 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5958 CloseHandle(hthread);
5959 CloseHandle(hevent);
5960 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5961 /****** end of out of context event test *************/
5963 ok(DestroyWindow(hwnd), "failed to destroy window\n");
5966 static void test_set_hook(void)
5968 BOOL ret;
5969 HHOOK hhook;
5970 HWINEVENTHOOK hwinevent_hook;
5971 HMODULE user32 = GetModuleHandleA("user32.dll");
5972 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
5973 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
5975 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId());
5976 ok(hhook != 0, "local hook does not require hModule set to 0\n");
5977 UnhookWindowsHookEx(hhook);
5979 #if 0 /* this test doesn't pass under Win9x: BUG! */
5980 SetLastError(0xdeadbeef);
5981 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0);
5982 ok(!hhook, "global hook requires hModule != 0\n");
5983 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %ld\n", GetLastError());
5984 #endif
5986 SetLastError(0xdeadbeef);
5987 hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId());
5988 ok(!hhook, "SetWinEventHook with invalid proc should fail\n");
5989 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */
5990 GetLastError() == 0xdeadbeef, /* Win9x */
5991 "unexpected error %ld\n", GetLastError());
5993 SetLastError(0xdeadbeef);
5994 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
5995 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */
5996 GetLastError() == 0xdeadbeef, /* Win9x */
5997 "unexpected error %ld\n", GetLastError());
5999 if (!pSetWinEventHook || !pUnhookWinEvent) return;
6001 /* even process local incontext hooks require hmodule */
6002 SetLastError(0xdeadbeef);
6003 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6004 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
6005 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
6006 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
6007 GetLastError() == 0xdeadbeef, /* Win9x */
6008 "unexpected error %ld\n", GetLastError());
6010 /* even thread local incontext hooks require hmodule */
6011 SetLastError(0xdeadbeef);
6012 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6013 0, win_event_proc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT);
6014 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
6015 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
6016 GetLastError() == 0xdeadbeef, /* Win9x */
6017 "unexpected error %ld\n", GetLastError());
6019 #if 0 /* these 3 tests don't pass under Win9x */
6020 SetLastError(0xdeadbeef);
6021 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(1, 0,
6022 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
6023 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
6024 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
6026 SetLastError(0xdeadbeef);
6027 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(-1, 1,
6028 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
6029 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
6030 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
6032 SetLastError(0xdeadbeef);
6033 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6034 0, win_event_proc, 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT);
6035 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n");
6036 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %ld\n", GetLastError());
6037 #endif
6039 SetLastError(0xdeadbeef);
6040 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(0, 0,
6041 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
6042 ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
6043 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
6044 ret = pUnhookWinEvent(hwinevent_hook);
6045 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
6047 todo_wine {
6048 /* This call succeeds under win2k SP4, but fails under Wine.
6049 Does win2k test/use passed process id? */
6050 SetLastError(0xdeadbeef);
6051 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6052 0, win_event_proc, 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT);
6053 ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
6054 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
6055 ret = pUnhookWinEvent(hwinevent_hook);
6056 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
6059 SetLastError(0xdeadbeef);
6060 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n");
6061 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
6062 GetLastError() == 0xdeadbeef, /* Win9x */
6063 "unexpected error %ld\n", GetLastError());
6066 static const struct message ScrollWindowPaint1[] = {
6067 { WM_PAINT, sent },
6068 { WM_ERASEBKGND, sent|beginpaint },
6069 { 0 }
6072 static const struct message ScrollWindowPaint2[] = {
6073 { WM_PAINT, sent },
6074 { 0 }
6077 static void test_scrollwindowex(void)
6079 HWND hwnd, hchild;
6080 RECT rect={0,0,130,130};
6081 MSG msg;
6083 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll",
6084 WS_VISIBLE|WS_OVERLAPPEDWINDOW,
6085 100, 100, 200, 200, 0, 0, 0, NULL);
6086 ok (hwnd != 0, "Failed to create overlapped window\n");
6087 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
6088 WS_VISIBLE|WS_CAPTION|WS_CHILD,
6089 10, 10, 150, 150, hwnd, 0, 0, NULL);
6090 ok (hchild != 0, "Failed to create child\n");
6091 UpdateWindow(hwnd);
6092 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6093 flush_sequence();
6095 /* scroll without the child window */
6096 trace("start scroll\n");
6097 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
6098 SW_ERASE|SW_INVALIDATE);
6099 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
6100 trace("end scroll\n");
6101 flush_sequence();
6102 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6103 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
6105 /* Now without the SW_ERASE flag */
6106 trace("start scroll\n");
6107 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE);
6108 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
6109 trace("end scroll\n");
6110 flush_sequence();
6111 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6112 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", 0);
6114 /* now scroll the child window as well */
6115 trace("start scroll\n");
6116 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
6117 SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
6118 todo_wine { /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
6119 /* windows sometimes a WM_MOVE */
6120 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
6122 trace("end scroll\n");
6123 flush_sequence();
6124 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6125 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
6127 /* now scroll with ScrollWindow() */
6128 trace("start scroll with ScrollWindow\n");
6129 ScrollWindow( hwnd, 5, 5, NULL, NULL);
6130 trace("end scroll\n");
6131 flush_sequence();
6132 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6133 ok_sequence(ScrollWindowPaint1, "ScrollWindow", 0);
6135 ok(DestroyWindow(hchild), "failed to destroy window\n");
6136 ok(DestroyWindow(hwnd), "failed to destroy window\n");
6137 flush_sequence();
6140 static const struct message destroy_window_with_children[] = {
6141 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
6142 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */
6143 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */
6144 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
6145 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
6146 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
6147 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
6148 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */
6149 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
6150 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
6151 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
6152 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
6153 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
6154 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
6155 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
6156 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
6157 { 0 }
6160 static void test_DestroyWindow(void)
6162 BOOL ret;
6163 HWND parent, child1, child2, child3, child4, test;
6164 UINT child_id = WND_CHILD_ID + 1;
6166 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6167 100, 100, 200, 200, 0, 0, 0, NULL);
6168 assert(parent != 0);
6169 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
6170 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL);
6171 assert(child1 != 0);
6172 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
6173 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL);
6174 assert(child2 != 0);
6175 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
6176 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL);
6177 assert(child3 != 0);
6178 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP,
6179 0, 0, 50, 50, parent, 0, 0, NULL);
6180 assert(child4 != 0);
6182 /* test owner/parent of child2 */
6183 test = GetParent(child2);
6184 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6185 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
6186 if(pGetAncestor) {
6187 test = pGetAncestor(child2, GA_PARENT);
6188 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6190 test = GetWindow(child2, GW_OWNER);
6191 ok(!test, "wrong owner %p\n", test);
6193 test = SetParent(child2, parent);
6194 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test);
6196 /* test owner/parent of the parent */
6197 test = GetParent(parent);
6198 ok(!test, "wrong parent %p\n", test);
6199 todo_wine {
6200 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent);
6202 if(pGetAncestor) {
6203 test = pGetAncestor(parent, GA_PARENT);
6204 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6206 test = GetWindow(parent, GW_OWNER);
6207 ok(!test, "wrong owner %p\n", test);
6209 /* test owner/parent of child1 */
6210 test = GetParent(child1);
6211 ok(test == parent, "wrong parent %p\n", test);
6212 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
6213 if(pGetAncestor) {
6214 test = pGetAncestor(child1, GA_PARENT);
6215 ok(test == parent, "wrong parent %p\n", test);
6217 test = GetWindow(child1, GW_OWNER);
6218 ok(!test, "wrong owner %p\n", test);
6220 /* test owner/parent of child2 */
6221 test = GetParent(child2);
6222 ok(test == parent, "wrong parent %p\n", test);
6223 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
6224 if(pGetAncestor) {
6225 test = pGetAncestor(child2, GA_PARENT);
6226 ok(test == parent, "wrong parent %p\n", test);
6228 test = GetWindow(child2, GW_OWNER);
6229 ok(!test, "wrong owner %p\n", test);
6231 /* test owner/parent of child3 */
6232 test = GetParent(child3);
6233 ok(test == child1, "wrong parent %p\n", test);
6234 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
6235 if(pGetAncestor) {
6236 test = pGetAncestor(child3, GA_PARENT);
6237 ok(test == child1, "wrong parent %p\n", test);
6239 test = GetWindow(child3, GW_OWNER);
6240 ok(!test, "wrong owner %p\n", test);
6242 /* test owner/parent of child4 */
6243 test = GetParent(child4);
6244 ok(test == parent, "wrong parent %p\n", test);
6245 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
6246 if(pGetAncestor) {
6247 test = pGetAncestor(child4, GA_PARENT);
6248 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6250 test = GetWindow(child4, GW_OWNER);
6251 ok(test == parent, "wrong owner %p\n", test);
6253 flush_sequence();
6255 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
6256 parent, child1, child2, child3, child4);
6258 SetCapture(child4);
6259 test = GetCapture();
6260 ok(test == child4, "wrong capture window %p\n", test);
6262 test_DestroyWindow_flag = TRUE;
6263 ret = DestroyWindow(parent);
6264 ok( ret, "DestroyWindow() error %ld\n", GetLastError());
6265 test_DestroyWindow_flag = FALSE;
6266 ok_sequence(destroy_window_with_children, "destroy window with children", 0);
6268 ok(!IsWindow(parent), "parent still exists\n");
6269 ok(!IsWindow(child1), "child1 still exists\n");
6270 ok(!IsWindow(child2), "child2 still exists\n");
6271 ok(!IsWindow(child3), "child3 still exists\n");
6272 ok(!IsWindow(child4), "child4 still exists\n");
6274 test = GetCapture();
6275 ok(!test, "wrong capture window %p\n", test);
6279 static const struct message WmDispatchPaint[] = {
6280 { WM_NCPAINT, sent },
6281 { WM_GETTEXT, sent|defwinproc|optional },
6282 { WM_GETTEXT, sent|defwinproc|optional },
6283 { WM_ERASEBKGND, sent },
6284 { 0 }
6287 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6289 if (message == WM_PAINT) return 0;
6290 return MsgCheckProcA( hwnd, message, wParam, lParam );
6293 static void test_DispatchMessage(void)
6295 RECT rect;
6296 MSG msg;
6297 int count;
6298 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6299 100, 100, 200, 200, 0, 0, 0, NULL);
6300 ShowWindow( hwnd, SW_SHOW );
6301 UpdateWindow( hwnd );
6302 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6303 flush_sequence();
6304 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc );
6306 SetRect( &rect, -5, -5, 5, 5 );
6307 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
6308 count = 0;
6309 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
6311 if (msg.message != WM_PAINT) DispatchMessage( &msg );
6312 else
6314 flush_sequence();
6315 DispatchMessage( &msg );
6316 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
6317 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
6318 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE );
6319 if (++count > 10) break;
6322 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" );
6324 trace("now without DispatchMessage\n");
6325 flush_sequence();
6326 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
6327 count = 0;
6328 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
6330 if (msg.message != WM_PAINT) DispatchMessage( &msg );
6331 else
6333 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
6334 flush_sequence();
6335 /* this will send WM_NCCPAINT just like DispatchMessage does */
6336 GetUpdateRgn( hwnd, hrgn, TRUE );
6337 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
6338 DeleteObject( hrgn );
6339 GetClientRect( hwnd, &rect );
6340 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */
6341 ok( !count, "Got multiple WM_PAINTs\n" );
6342 if (++count > 10) break;
6348 static const struct message WmUser[] = {
6349 { WM_USER, sent },
6350 { 0 }
6353 struct thread_info
6355 HWND hwnd;
6356 DWORD timeout;
6357 DWORD ret;
6360 static DWORD CALLBACK send_msg_thread( LPVOID arg )
6362 struct thread_info *info = arg;
6363 info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL );
6364 if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT, "unexpected error %ld\n", GetLastError());
6365 return 0;
6368 static void wait_for_thread( HANDLE thread )
6370 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0)
6372 MSG msg;
6373 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage(&msg);
6377 static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6379 if (message == WM_USER) Sleep(200);
6380 return MsgCheckProcA( hwnd, message, wParam, lParam );
6383 static void test_SendMessageTimeout(void)
6385 MSG msg;
6386 HANDLE thread;
6387 struct thread_info info;
6388 DWORD tid;
6390 info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6391 100, 100, 200, 200, 0, 0, 0, NULL);
6392 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6393 flush_sequence();
6395 info.timeout = 1000;
6396 info.ret = 0xdeadbeef;
6397 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6398 wait_for_thread( thread );
6399 CloseHandle( thread );
6400 ok( info.ret == 1, "SendMessageTimeout failed\n" );
6401 ok_sequence( WmUser, "WmUser", FALSE );
6403 info.timeout = 1;
6404 info.ret = 0xdeadbeef;
6405 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6406 Sleep(100); /* SendMessageTimeout should timeout here */
6407 wait_for_thread( thread );
6408 CloseHandle( thread );
6409 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
6410 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
6412 /* 0 means infinite timeout */
6413 info.timeout = 0;
6414 info.ret = 0xdeadbeef;
6415 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6416 Sleep(100);
6417 wait_for_thread( thread );
6418 CloseHandle( thread );
6419 ok( info.ret == 1, "SendMessageTimeout failed\n" );
6420 ok_sequence( WmUser, "WmUser", FALSE );
6422 /* timeout is treated as signed despite the prototype */
6423 info.timeout = 0x7fffffff;
6424 info.ret = 0xdeadbeef;
6425 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6426 Sleep(100);
6427 wait_for_thread( thread );
6428 CloseHandle( thread );
6429 ok( info.ret == 1, "SendMessageTimeout failed\n" );
6430 ok_sequence( WmUser, "WmUser", FALSE );
6432 info.timeout = 0x80000000;
6433 info.ret = 0xdeadbeef;
6434 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6435 Sleep(100);
6436 wait_for_thread( thread );
6437 CloseHandle( thread );
6438 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
6439 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
6441 /* now check for timeout during message processing */
6442 SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc );
6443 info.timeout = 100;
6444 info.ret = 0xdeadbeef;
6445 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6446 wait_for_thread( thread );
6447 CloseHandle( thread );
6448 /* we should timeout but still get the message */
6449 ok( info.ret == 0, "SendMessageTimeout failed\n" );
6450 ok_sequence( WmUser, "WmUser", FALSE );
6452 DestroyWindow( info.hwnd );
6456 /****************** edit message test *************************/
6457 #define ID_EDIT 0x1234
6458 static const struct message sl_edit_setfocus[] =
6460 { HCBT_SETFOCUS, hook },
6461 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
6462 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6463 { WM_SETFOCUS, sent|wparam, 0 },
6464 { WM_CTLCOLOREDIT, sent|parent },
6465 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6466 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6467 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6468 { 0 }
6470 static const struct message ml_edit_setfocus[] =
6472 { HCBT_SETFOCUS, hook },
6473 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
6474 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6475 { WM_SETFOCUS, sent|wparam, 0 },
6476 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6477 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6478 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6479 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6480 { 0 }
6482 static const struct message sl_edit_killfocus[] =
6484 { HCBT_SETFOCUS, hook },
6485 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6486 { WM_KILLFOCUS, sent|wparam, 0 },
6487 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6488 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6489 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) },
6490 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
6491 { 0 }
6493 static const struct message sl_edit_lbutton_dblclk[] =
6495 { WM_LBUTTONDBLCLK, sent },
6496 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6497 { 0 }
6499 static const struct message sl_edit_lbutton_down[] =
6501 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
6502 { HCBT_SETFOCUS, hook },
6503 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
6504 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6505 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
6506 { WM_CTLCOLOREDIT, sent|parent },
6507 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6508 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6509 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6510 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6511 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6512 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6513 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6514 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6515 { 0 }
6517 static const struct message ml_edit_lbutton_down[] =
6519 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
6520 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6521 { HCBT_SETFOCUS, hook },
6522 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
6523 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6524 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
6525 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6526 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6527 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6528 { 0 }
6530 static const struct message sl_edit_lbutton_up[] =
6532 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6533 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6534 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6535 { WM_CAPTURECHANGED, sent|defwinproc },
6536 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6537 { 0 }
6539 static const struct message ml_edit_lbutton_up[] =
6541 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6542 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6543 { WM_CAPTURECHANGED, sent|defwinproc },
6544 { 0 }
6547 static WNDPROC old_edit_proc;
6549 static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6551 static long defwndproc_counter = 0;
6552 LRESULT ret;
6553 struct message msg;
6555 trace("edit: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
6557 /* explicitly ignore WM_GETICON message */
6558 if (message == WM_GETICON) return 0;
6560 msg.message = message;
6561 msg.flags = sent|wparam|lparam;
6562 if (defwndproc_counter) msg.flags |= defwinproc;
6563 msg.wParam = wParam;
6564 msg.lParam = lParam;
6565 add_message(&msg);
6567 defwndproc_counter++;
6568 ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam);
6569 defwndproc_counter--;
6571 return ret;
6574 static void subclass_edit(void)
6576 WNDCLASSA cls;
6578 if (!GetClassInfoA(0, "edit", &cls)) assert(0);
6580 old_edit_proc = cls.lpfnWndProc;
6582 cls.hInstance = GetModuleHandle(0);
6583 cls.lpfnWndProc = edit_hook_proc;
6584 cls.lpszClassName = "my_edit_class";
6585 if (!RegisterClassA(&cls)) assert(0);
6588 static void test_edit_messages(void)
6590 HWND hwnd, parent;
6591 DWORD dlg_code;
6593 subclass_edit();
6594 log_all_parent_messages++;
6596 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6597 100, 100, 200, 200, 0, 0, 0, NULL);
6598 ok (parent != 0, "Failed to create parent window\n");
6600 /* test single line edit */
6601 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD,
6602 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
6603 ok(hwnd != 0, "Failed to create edit window\n");
6605 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
6606 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08lx\n", dlg_code);
6608 ShowWindow(hwnd, SW_SHOW);
6609 UpdateWindow(hwnd);
6610 SetFocus(0);
6611 flush_sequence();
6613 SetFocus(hwnd);
6614 ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE);
6616 SetFocus(0);
6617 ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE);
6619 SetFocus(0);
6620 ReleaseCapture();
6621 flush_sequence();
6623 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
6624 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE);
6626 SetFocus(0);
6627 ReleaseCapture();
6628 flush_sequence();
6630 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
6631 ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE);
6633 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
6634 ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE);
6636 DestroyWindow(hwnd);
6638 /* test multiline edit */
6639 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE,
6640 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
6641 ok(hwnd != 0, "Failed to create edit window\n");
6643 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
6644 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS),
6645 "wrong dlg_code %08lx\n", dlg_code);
6647 ShowWindow(hwnd, SW_SHOW);
6648 UpdateWindow(hwnd);
6649 SetFocus(0);
6650 flush_sequence();
6652 SetFocus(hwnd);
6653 ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE);
6655 SetFocus(0);
6656 ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE);
6658 SetFocus(0);
6659 ReleaseCapture();
6660 flush_sequence();
6662 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
6663 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE);
6665 SetFocus(0);
6666 ReleaseCapture();
6667 flush_sequence();
6669 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
6670 ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE);
6672 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
6673 ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE);
6675 DestroyWindow(hwnd);
6676 DestroyWindow(parent);
6678 log_all_parent_messages--;
6681 /**************************** End of Edit test ******************************/
6683 static const struct message WmChar[] = {
6684 { WM_CHAR, sent|wparam, 'z' },
6685 { 0 }
6688 static const struct message WmKeyDownUp[] = {
6689 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x00000001 },
6690 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
6691 { 0 }
6694 static const struct message WmUserChar[] = {
6695 { WM_USER, sent },
6696 { WM_CHAR, sent|wparam, 'z' },
6697 { 0 }
6700 #define EV_START_STOP 0
6701 #define EV_SENDMSG 1
6702 #define EV_ACK 2
6704 struct thread_info_2
6706 HWND hwnd;
6707 HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
6710 static DWORD CALLBACK send_msg_thread_2(void *param)
6712 DWORD ret;
6713 struct thread_info_2 *info = param;
6715 trace("thread: waiting for start\n");
6716 WaitForSingleObject(info->hevent[EV_START_STOP], INFINITE);
6717 trace("thread: looping\n");
6719 while (1)
6721 ret = WaitForMultipleObjects(2, info->hevent, FALSE, INFINITE);
6723 switch (ret)
6725 case WAIT_OBJECT_0 + EV_START_STOP:
6726 trace("thread: exiting\n");
6727 return 0;
6729 case WAIT_OBJECT_0 + EV_SENDMSG:
6730 trace("thread: sending message\n");
6731 SendNotifyMessageA(info->hwnd, WM_USER, 0, 0);
6732 SetEvent(info->hevent[EV_ACK]);
6733 break;
6735 default:
6736 trace("unexpected return: %04lx\n", ret);
6737 assert(0);
6738 break;
6741 return 0;
6744 static void test_PeekMessage(void)
6746 MSG msg;
6747 HANDLE hthread;
6748 DWORD tid, qstatus;
6749 UINT qs_all_input = QS_ALLINPUT;
6750 UINT qs_input = QS_INPUT;
6751 struct thread_info_2 info;
6753 info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6754 100, 100, 200, 200, 0, 0, 0, NULL);
6755 ShowWindow(info.hwnd, SW_SHOW);
6756 UpdateWindow(info.hwnd);
6758 info.hevent[EV_START_STOP] = CreateEventA(NULL, 0, 0, NULL);
6759 info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL);
6760 info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL);
6762 hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid);
6764 trace("signalling to start looping\n");
6765 SetEvent(info.hevent[EV_START_STOP]);
6767 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6768 flush_sequence();
6770 SetLastError(0xdeadbeef);
6771 qstatus = GetQueueStatus(qs_all_input);
6772 if (GetLastError() == ERROR_INVALID_FLAGS)
6774 trace("QS_RAWINPUT not supported on this platform\n");
6775 qs_all_input &= ~QS_RAWINPUT;
6776 qs_input &= ~QS_RAWINPUT;
6778 ok(qstatus == 0, "wrong qstatus %08lx\n", qstatus);
6780 trace("signalling to send message\n");
6781 SetEvent(info.hevent[EV_SENDMSG]);
6782 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
6784 /* pass invalid QS_xxxx flags */
6785 SetLastError(0xdeadbeef);
6786 qstatus = GetQueueStatus(0xffffffff);
6787 ok(qstatus == 0, "GetQueueStatus should fail: %08lx\n", qstatus);
6788 ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %ld\n", GetLastError());
6790 qstatus = GetQueueStatus(qs_all_input);
6791 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE),
6792 "wrong qstatus %08lx\n", qstatus);
6794 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6795 ok_sequence(WmUser, "WmUser", FALSE);
6797 qstatus = GetQueueStatus(qs_all_input);
6798 ok(qstatus == 0, "wrong qstatus %08lx\n", qstatus);
6800 keybd_event('N', 0, 0, 0);
6801 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6802 qstatus = GetQueueStatus(qs_all_input);
6803 ok(qstatus == MAKELONG(QS_KEY, QS_KEY),
6804 "wrong qstatus %08lx\n", qstatus);
6806 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
6807 qstatus = GetQueueStatus(qs_all_input);
6808 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY),
6809 "wrong qstatus %08lx\n", qstatus);
6811 InvalidateRect(info.hwnd, NULL, FALSE);
6812 qstatus = GetQueueStatus(qs_all_input);
6813 ok(qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
6814 "wrong qstatus %08lx\n", qstatus);
6816 trace("signalling to send message\n");
6817 SetEvent(info.hevent[EV_SENDMSG]);
6818 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
6820 qstatus = GetQueueStatus(qs_all_input);
6821 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY),
6822 "wrong qstatus %08lx\n", qstatus);
6823 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16))) DispatchMessageA(&msg);
6824 ok_sequence(WmUser, "WmUser", TRUE); /* todo_wine */
6826 qstatus = GetQueueStatus(qs_all_input);
6827 todo_wine {
6828 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
6829 "wrong qstatus %08lx\n", qstatus);
6832 trace("signalling to send message\n");
6833 SetEvent(info.hevent[EV_SENDMSG]);
6834 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
6836 qstatus = GetQueueStatus(qs_all_input);
6837 todo_wine {
6838 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY),
6839 "wrong qstatus %08lx\n", qstatus);
6841 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE)) DispatchMessageA(&msg);
6842 ok_sequence(WmUser, "WmUser", FALSE);
6844 qstatus = GetQueueStatus(qs_all_input);
6845 todo_wine {
6846 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
6847 "wrong qstatus %08lx\n", qstatus);
6850 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE)) DispatchMessageA(&msg);
6851 ok_sequence(WmChar, "WmChar", TRUE); /* todo_wine */
6853 qstatus = GetQueueStatus(qs_all_input);
6854 todo_wine {
6855 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
6856 "wrong qstatus %08lx\n", qstatus);
6859 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT)) DispatchMessageA(&msg);
6860 ok_sequence(WmPaint, "WmPaint", TRUE); /* todo_wine */
6862 qstatus = GetQueueStatus(qs_all_input);
6863 todo_wine {
6864 ok(qstatus == MAKELONG(0, QS_KEY),
6865 "wrong qstatus %08lx\n", qstatus);
6868 trace("signalling to send message\n");
6869 SetEvent(info.hevent[EV_SENDMSG]);
6870 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
6872 qstatus = GetQueueStatus(qs_all_input);
6873 todo_wine {
6874 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY),
6875 "wrong qstatus %08lx\n", qstatus);
6878 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
6880 qstatus = GetQueueStatus(qs_all_input);
6881 todo_wine {
6882 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
6883 "wrong qstatus %08lx\n", qstatus);
6886 while (PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE)) DispatchMessage(&msg);
6887 ok_sequence(WmUserChar, "WmUserChar", FALSE);
6889 qstatus = GetQueueStatus(qs_all_input);
6890 todo_wine {
6891 ok(qstatus == MAKELONG(0, QS_KEY),
6892 "wrong qstatus %08lx\n", qstatus);
6895 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
6897 qstatus = GetQueueStatus(qs_all_input);
6898 todo_wine {
6899 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY),
6900 "wrong qstatus %08lx\n", qstatus);
6903 trace("signalling to send message\n");
6904 SetEvent(info.hevent[EV_SENDMSG]);
6905 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
6907 qstatus = GetQueueStatus(qs_all_input);
6908 todo_wine {
6909 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
6910 "wrong qstatus %08lx\n", qstatus);
6913 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16))) DispatchMessage(&msg);
6914 ok_sequence(WmUser, "WmUser", TRUE); /* todo_wine */
6916 qstatus = GetQueueStatus(qs_all_input);
6917 todo_wine {
6918 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
6919 "wrong qstatus %08lx\n", qstatus);
6922 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16))) DispatchMessage(&msg);
6923 ok_sequence(WmKeyDownUp, "WmKeyDownUp", TRUE); /* todo_wine */
6925 qstatus = GetQueueStatus(qs_all_input);
6926 todo_wine {
6927 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
6928 "wrong qstatus %08lx\n", qstatus);
6931 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE)) DispatchMessage(&msg);
6932 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
6934 qstatus = GetQueueStatus(qs_all_input);
6935 todo_wine {
6936 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
6937 "wrong qstatus %08lx\n", qstatus);
6940 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6941 ok_sequence(WmChar, "WmChar", TRUE); /* todo_wine */
6943 qstatus = GetQueueStatus(qs_all_input);
6944 ok(qstatus == 0,
6945 "wrong qstatus %08lx\n", qstatus);
6947 trace("signalling to exit\n");
6948 SetEvent(info.hevent[EV_START_STOP]);
6950 WaitForSingleObject(hthread, INFINITE);
6952 CloseHandle(hthread);
6953 CloseHandle(info.hevent[0]);
6954 CloseHandle(info.hevent[1]);
6955 CloseHandle(info.hevent[2]);
6957 DestroyWindow(info.hwnd);
6961 START_TEST(msg)
6963 BOOL ret;
6964 HMODULE user32 = GetModuleHandleA("user32.dll");
6965 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
6966 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
6967 FARPROC pIsWinEventHookInstalled = 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
6968 pGetAncestor = (void*) GetProcAddress(user32, "GetAncestor");
6970 if (!RegisterWindowClasses()) assert(0);
6972 if (pSetWinEventHook)
6974 hEvent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6975 GetModuleHandleA(0),
6976 win_event_proc,
6978 GetCurrentThreadId(),
6979 WINEVENT_INCONTEXT);
6980 assert(hEvent_hook);
6982 if (pIsWinEventHookInstalled)
6984 UINT event;
6985 for (event = EVENT_MIN; event <= EVENT_MAX; event++)
6986 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
6990 cbt_hook_thread_id = GetCurrentThreadId();
6991 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
6992 assert(hCBT_hook);
6994 test_winevents();
6996 /* Fix message sequences before removing 4 lines below */
6997 #if 1
6998 ret = pUnhookWinEvent(hEvent_hook);
6999 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
7000 pUnhookWinEvent = 0;
7001 hEvent_hook = 0;
7002 #endif
7004 test_PeekMessage();
7005 test_scrollwindowex();
7006 test_messages();
7007 test_mdi_messages();
7008 test_button_messages();
7009 test_paint_messages();
7010 test_interthread_messages();
7011 test_message_conversion();
7012 test_accelerators();
7013 test_timers();
7014 test_set_hook();
7015 test_DestroyWindow();
7016 test_DispatchMessage();
7017 test_SendMessageTimeout();
7018 test_edit_messages();
7020 UnhookWindowsHookEx(hCBT_hook);
7021 if (pUnhookWinEvent)
7023 ret = pUnhookWinEvent(hEvent_hook);
7024 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
7025 SetLastError(0xdeadbeef);
7026 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n");
7027 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
7028 GetLastError() == 0xdeadbeef, /* Win9x */
7029 "unexpected error %ld\n", GetLastError());