2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004, 2005 Dmitry Timoshkov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define _WIN32_WINNT 0x0500 /* For WM_CHANGEUISTATE */
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
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[] =
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 },
95 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 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 },
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 },
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 */
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 },
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 },
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 },
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 },
225 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
226 { WM_ERASEBKGND, sent|beginpaint },
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 },
243 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
244 { WM_ERASEBKGND, sent|beginpaint },
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?
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
492 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 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 },
505 { WM_STYLECHANGING, sent },
506 { WM_STYLECHANGED, sent },
507 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 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 },
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 },
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 },
546 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
549 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
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 },
558 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
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 },
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 },
579 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
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 },
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 },
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 },
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 },
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 },
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 },
637 /* ShowWindow(SW_SHOW) for child with invisible parent */
638 static const struct message WmShowChildInvisibleParentSeq[] = {
639 { WM_SHOWWINDOW, sent|wparam, 1 },
642 /* ShowWindow(SW_HIDE) for child with invisible parent */
643 static const struct message WmHideChildInvisibleParentSeq[] = {
644 { WM_SHOWWINDOW, sent|wparam, 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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
875 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 */
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 },
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 },
1125 static const struct message WmSetRedrawFalseSeq[] =
1127 { WM_SETREDRAW, sent|wparam, 0 },
1131 static const struct message WmSetRedrawTrueSeq[] =
1133 { WM_SETREDRAW, sent|wparam, 1 },
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 },
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 },
1152 static const struct message WmGetScrollRangeSeq[] =
1154 { SBM_GETRANGE, sent },
1157 static const struct message WmGetScrollInfoSeq[] =
1159 { SBM_GETSCROLLINFO, sent },
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 },
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 },
1176 static const struct message WmSetScrollRangeVSeq_empty[] =
1178 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 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 },
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 },
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 },
1219 static const struct message WmSHOWNAChildVisParInvis[] = {
1220 { WM_SHOWWINDOW, sent|wparam, 1 },
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 },
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 },
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 },
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 },
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)
1268 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
1270 if (sequence_cnt == sequence_size)
1273 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
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;
1285 static void flush_sequence(void)
1287 HeapFree(GetProcessHeap(), 0, sequence);
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;
1303 add_message(&end_of_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)
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);
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);
1354 /* silently drop winevent messages if there is no support for them */
1355 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))
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);
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);
1376 /* skip all optional trailing messages */
1377 while (expected->message && ((expected->flags & optional) ||
1378 ((expected->flags & winevent_hook) && !hEvent_hook)))
1384 if (expected->message || actual->message) {
1386 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1387 context, expected->message, actual->message);
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 */
1399 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 */
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 },
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 },
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 },
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 },
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 */
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 },
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 },
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 },
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 },
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 */
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 },
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 },
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 },
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 },
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 },
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 },
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 */
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 },
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 },
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 },
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 */
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 },
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 },
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 },
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 */
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 },
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 },
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 */
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 },
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 */
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 },
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 },
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 },
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 },
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 */
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 },
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 */
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 },
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 */
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 },
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 */
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)
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);
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;
2217 msg.message = message;
2218 msg.flags = sent|wparam|lparam;
2219 msg.wParam = wParam;
2220 msg.lParam = lParam;
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;
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);
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;
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);
2272 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
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;
2285 defwndproc_counter++;
2286 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
2287 defwndproc_counter--;
2292 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2294 static long defwndproc_counter = 0;
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);
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;
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;
2337 defwndproc_counter++;
2338 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
2339 defwndproc_counter--;
2344 static BOOL mdi_RegisterWindowClasses(void)
2349 cls.lpfnWndProc = mdi_frame_wnd_proc;
2352 cls.hInstance = GetModuleHandleA(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);
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;
2380 HMENU hMenu = CreateMenu();
2382 assert(mdi_RegisterWindowClasses());
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);
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",
2404 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
2406 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
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);
2420 trace("creating invisible MDI child window\n");
2421 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2423 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2424 mdi_client, 0, GetModuleHandleA(0), NULL);
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);
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);
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);
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);
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);
2497 trace("creating invisible MDI child window\n");
2498 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2500 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2501 mdi_client, 0, GetModuleHandleA(0), NULL);
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);
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);
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());
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);
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);
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());
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);
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);
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);
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);
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);
2650 ShowWindow(mdi_child, SW_MAXIMIZE);
2651 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
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);
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);
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);
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);
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);
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;
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);
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);
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);
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");
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);
2774 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
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;
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;
2803 msg.message = message;
2804 msg.flags = sent|wparam|lparam;
2805 msg.wParam = wParam;
2806 msg.lParam = lParam;
2809 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2810 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2814 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2816 DWORD style, exstyle;
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);
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);
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;
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;
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);
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);
2889 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2891 si.fMask = SIF_PAGE;
2893 SetScrollInfo(hwnd, ctl, &si, FALSE);
2894 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
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)
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 */
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);
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 */
2942 si.cbSize = sizeof(si);
2943 si.fMask = SIF_RANGE;
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);
2951 si.fMask = SIF_PAGE;
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);
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);
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 */
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)
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");
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);
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);
3020 /* back to invisible */
3021 ShowWindow(hchild, SW_HIDE);
3022 ShowWindow(hwnd, SW_HIDE);
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);
3029 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
3030 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
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);
3036 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
3037 ShowWindow( hwnd, SW_SHOW);
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);
3044 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
3045 ShowWindow( hchild, SW_HIDE);
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);
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);
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);
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);
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);
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);
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);
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);
3110 DestroyWindow(hwnd);
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);
3122 DestroyWindow(hwnd);
3126 * 1. Create visible popup window.
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);
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);
3140 DestroyWindow(hwnd);
3144 static void test_sys_menu(HWND hwnd)
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;
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 */
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);
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);
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");
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);
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);
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");
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);
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);
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 */
3340 DestroyWindow(hchild);
3341 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
3342 DestroyWindow(hchild2);
3343 DestroyWindow(hbutton);
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 */
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");
3361 ShowWindow(hchild, SW_SHOW);
3362 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
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);
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.
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");
3382 ShowWindow(hchild, SW_SHOW);
3383 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
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);
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);
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");
3412 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
3413 ShowWindow(hwnd, SW_SHOW);
3414 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
3415 DestroyWindow(hwnd);
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 );
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);
3452 DestroyWindow(hchild);
3453 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE);
3455 DestroyWindow(hparent);
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 );
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 );
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);
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");
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 );
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);
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 },
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 },
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 },
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 },
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 },
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 },
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;
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;
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--;
3638 static void subclass_button(void)
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)
3658 const struct message *setfocus;
3659 const struct message *killfocus;
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 }
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);
3704 trace("button style %08lx\n", button[i].style);
3706 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
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");
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)
3734 RGNDATA *data = NULL;
3739 printf( "null region\n" );
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 );
3749 HeapFree( GetProcessHeap(), 0, data );
3752 static void check_update_rgn( HWND hwnd, HRGN hrgn )
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" );
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 },
3795 static const struct message WmGetUpdateRect[] = {
3796 { WM_NCPAINT, sent },
3797 { WM_GETTEXT, sent|defwinproc|optional },
3802 static const struct message WmInvalidateFull[] = {
3803 { WM_NCPAINT, sent|wparam, 1 },
3804 { WM_GETTEXT, sent|defwinproc|optional },
3808 static const struct message WmInvalidateErase[] = {
3809 { WM_NCPAINT, sent|wparam, 1 },
3810 { WM_GETTEXT, sent|defwinproc|optional },
3811 { WM_ERASEBKGND, sent },
3815 static const struct message WmInvalidatePaint[] = {
3817 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3818 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3822 static const struct message WmInvalidateErasePaint[] = {
3824 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3825 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3826 { WM_ERASEBKGND, sent|beginpaint },
3830 static const struct message WmInvalidateErasePaint2[] = {
3832 { WM_NCPAINT, sent|beginpaint },
3833 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3834 { WM_ERASEBKGND, sent|beginpaint },
3838 static const struct message WmErase[] = {
3839 { WM_ERASEBKGND, sent },
3843 static const struct message WmPaint[] = {
3848 static const struct message WmParentOnlyPaint[] = {
3849 { WM_PAINT, sent|parent },
3853 static const struct message WmInvalidateParent[] = {
3854 { WM_NCPAINT, sent|parent },
3855 { WM_GETTEXT, sent|defwinproc|parent|optional },
3856 { WM_ERASEBKGND, sent|parent },
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 },
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 },
3878 static const struct message WmParentPaint[] = {
3879 { WM_PAINT, sent|parent },
3884 static const struct message WmParentPaintNc[] = {
3885 { WM_PAINT, sent|parent },
3887 { WM_NCPAINT, sent|beginpaint },
3888 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3889 { WM_ERASEBKGND, sent|beginpaint },
3893 static const struct message WmChildPaintNc[] = {
3895 { WM_NCPAINT, sent|beginpaint },
3896 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3897 { WM_ERASEBKGND, sent|beginpaint },
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 },
3907 { WM_NCPAINT, sent|beginpaint },
3908 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3909 { WM_ERASEBKGND, sent|beginpaint },
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 },
3920 static const struct message WmSetParentStyle[] = {
3921 { WM_STYLECHANGING, sent|parent },
3922 { WM_STYLECHANGED, sent|parent },
3926 static void test_paint_messages(void)
3931 HWND hparent, hchild;
3932 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
3933 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
3934 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3935 100, 100, 200, 200, 0, 0, 0, NULL);
3936 ok (hwnd != 0, "Failed to create overlapped window\n");
3938 ShowWindow( hwnd, SW_SHOW );
3939 UpdateWindow( hwnd );
3941 /* try to flush pending X expose events */
3942 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3943 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3945 check_update_rgn( hwnd, 0 );
3946 SetRectRgn( hrgn, 10, 10, 20, 20 );
3947 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3948 check_update_rgn( hwnd, hrgn );
3949 SetRectRgn( hrgn2, 20, 20, 30, 30 );
3950 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
3951 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
3952 check_update_rgn( hwnd, hrgn );
3953 /* validate everything */
3954 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3955 check_update_rgn( hwnd, 0 );
3957 /* flush pending messages */
3958 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3961 GetClientRect( hwnd, &rect );
3962 SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top );
3963 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
3964 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
3966 trace("testing InvalidateRect(0, NULL, FALSE)\n");
3967 SetRectEmpty( &rect );
3968 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) should fail\n");
3969 check_update_rgn( hwnd, hrgn );
3970 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3971 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3972 ok_sequence( WmPaint, "Paint", FALSE );
3973 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3974 check_update_rgn( hwnd, 0 );
3976 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
3977 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
3979 trace("testing ValidateRect(0, NULL)\n");
3980 SetRectEmpty( &rect );
3981 ok(ValidateRect(0, &rect), "ValidateRect(0, &rc) should not fail\n");
3982 check_update_rgn( hwnd, hrgn );
3983 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3984 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3985 ok_sequence( WmPaint, "Paint", FALSE );
3986 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3987 check_update_rgn( hwnd, 0 );
3989 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
3990 SetLastError(0xdeadbeef);
3991 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n");
3992 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %ld\n", GetLastError());
3993 check_update_rgn( hwnd, 0 );
3994 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3995 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
3997 trace("testing ValidateRgn(0, NULL)\n");
3998 SetLastError(0xdeadbeef);
3999 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n");
4000 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %ld\n", GetLastError());
4001 check_update_rgn( hwnd, 0 );
4002 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4003 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
4005 /* now with frame */
4006 SetRectRgn( hrgn, -5, -5, 20, 20 );
4008 /* flush pending messages */
4009 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4012 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4013 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
4015 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
4016 check_update_rgn( hwnd, hrgn );
4019 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
4020 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
4023 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
4024 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
4026 GetClientRect( hwnd, &rect );
4027 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
4028 check_update_rgn( hwnd, hrgn );
4031 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
4032 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
4035 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
4036 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
4037 check_update_rgn( hwnd, 0 );
4040 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
4041 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
4042 check_update_rgn( hwnd, 0 );
4045 SetRectRgn( hrgn, 0, 0, 100, 100 );
4046 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
4047 SetRectRgn( hrgn, 0, 0, 50, 100 );
4048 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
4049 SetRectRgn( hrgn, 50, 0, 100, 100 );
4050 check_update_rgn( hwnd, hrgn );
4051 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
4052 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
4053 check_update_rgn( hwnd, 0 );
4056 SetRectRgn( hrgn, 0, 0, 100, 100 );
4057 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
4058 SetRectRgn( hrgn, 0, 0, 100, 50 );
4059 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
4060 ok_sequence( WmErase, "Erase", FALSE );
4061 SetRectRgn( hrgn, 0, 50, 100, 100 );
4062 check_update_rgn( hwnd, hrgn );
4065 SetRectRgn( hrgn, 0, 0, 100, 100 );
4066 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
4067 SetRectRgn( hrgn, 0, 0, 50, 50 );
4068 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
4069 ok_sequence( WmPaint, "Paint", FALSE );
4072 SetRectRgn( hrgn, -4, -4, -2, -2 );
4073 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4074 SetRectRgn( hrgn, -200, -200, -198, -198 );
4075 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
4076 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
4079 SetRectRgn( hrgn, -4, -4, -2, -2 );
4080 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4081 SetRectRgn( hrgn, -4, -4, -3, -3 );
4082 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
4083 SetRectRgn( hrgn, 0, 0, 1, 1 );
4084 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
4085 ok_sequence( WmPaint, "Paint", FALSE );
4088 SetRectRgn( hrgn, -4, -4, -1, -1 );
4089 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4090 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
4091 /* make sure no WM_PAINT was generated */
4092 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4093 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
4096 SetRectRgn( hrgn, -4, -4, -1, -1 );
4097 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
4098 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
4100 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
4102 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
4103 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
4104 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
4105 ret = GetUpdateRect( hwnd, &rect, FALSE );
4106 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
4107 /* this will send WM_NCPAINT and validate the non client area */
4108 ret = GetUpdateRect( hwnd, &rect, TRUE );
4109 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
4111 DispatchMessage( &msg );
4113 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
4115 DestroyWindow( hwnd );
4117 /* now test with a child window */
4119 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
4120 100, 100, 200, 200, 0, 0, 0, NULL);
4121 ok (hparent != 0, "Failed to create parent window\n");
4123 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
4124 10, 10, 100, 100, hparent, 0, 0, NULL);
4125 ok (hchild != 0, "Failed to create child window\n");
4127 ShowWindow( hparent, SW_SHOW );
4128 UpdateWindow( hparent );
4129 UpdateWindow( hchild );
4130 /* try to flush pending X expose events */
4131 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
4132 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4135 log_all_parent_messages++;
4137 SetRect( &rect, 0, 0, 50, 50 );
4138 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4139 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
4140 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
4142 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4144 MapWindowPoints( hchild, hparent, &pt, 1 );
4145 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
4146 check_update_rgn( hchild, hrgn );
4147 SetRectRgn( hrgn, 0, 0, 50, 50 );
4148 check_update_rgn( hparent, hrgn );
4149 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4150 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
4151 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
4152 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
4154 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4155 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
4157 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
4158 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4159 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
4160 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
4161 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
4163 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
4164 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
4165 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
4167 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
4169 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
4170 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4171 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
4173 /* flush all paint messages */
4174 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4177 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
4178 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
4179 SetRectRgn( hrgn, 0, 0, 50, 50 );
4180 check_update_rgn( hparent, hrgn );
4181 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
4182 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4183 SetRectRgn( hrgn, 0, 0, 50, 50 );
4184 check_update_rgn( hparent, hrgn );
4186 /* flush all paint messages */
4187 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4188 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
4191 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
4192 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4193 SetRectRgn( hrgn, 0, 0, 50, 50 );
4194 check_update_rgn( hparent, hrgn );
4195 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
4196 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4197 SetRectRgn( hrgn2, 10, 10, 50, 50 );
4198 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
4199 check_update_rgn( hparent, hrgn );
4200 /* flush all paint messages */
4201 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4204 /* same as above but parent gets completely validated */
4205 SetRect( &rect, 20, 20, 30, 30 );
4206 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4207 SetRectRgn( hrgn, 20, 20, 30, 30 );
4208 check_update_rgn( hparent, hrgn );
4209 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
4210 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4211 check_update_rgn( hparent, 0 ); /* no update region */
4212 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4213 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
4215 /* make sure RDW_VALIDATE on child doesn't have the same effect */
4217 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4218 SetRectRgn( hrgn, 20, 20, 30, 30 );
4219 check_update_rgn( hparent, hrgn );
4220 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
4221 SetRectRgn( hrgn, 20, 20, 30, 30 );
4222 check_update_rgn( hparent, hrgn );
4224 /* same as above but normal WM_PAINT doesn't validate parent */
4226 SetRect( &rect, 20, 20, 30, 30 );
4227 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4228 SetRectRgn( hrgn, 20, 20, 30, 30 );
4229 check_update_rgn( hparent, hrgn );
4230 /* no WM_PAINT in child while parent still pending */
4231 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4232 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
4233 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4234 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
4237 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4238 /* no WM_PAINT in child while parent still pending */
4239 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4240 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
4241 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
4242 /* now that parent is valid child should get WM_PAINT */
4243 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4244 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
4245 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4246 ok_sequence( WmEmptySeq, "No other message", FALSE );
4248 /* same thing with WS_CLIPCHILDREN in parent */
4250 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
4251 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
4252 /* changing style invalidates non client area, but we need to invalidate something else to see it */
4253 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
4254 ok_sequence( WmEmptySeq, "No message", FALSE );
4255 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
4256 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
4259 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
4260 SetRectRgn( hrgn, 20, 20, 30, 30 );
4261 check_update_rgn( hparent, hrgn );
4262 /* no WM_PAINT in child while parent still pending */
4263 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4264 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
4265 /* WM_PAINT in parent first */
4266 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4267 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
4269 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
4271 SetRect( &rect, 0, 0, 30, 30 );
4272 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
4273 SetRectRgn( hrgn, 0, 0, 30, 30 );
4274 check_update_rgn( hparent, hrgn );
4275 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4276 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
4278 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
4280 SetRect( &rect, -10, 0, 30, 30 );
4281 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
4282 SetRect( &rect, 0, 0, 20, 20 );
4283 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
4284 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
4285 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
4287 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
4289 SetRect( &rect, -10, 0, 30, 30 );
4290 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
4291 SetRect( &rect, 0, 0, 100, 100 );
4292 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
4293 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
4294 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
4295 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
4296 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
4298 /* test RDW_INTERNALPAINT behavior */
4301 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
4302 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4303 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
4305 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
4306 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4307 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
4309 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
4310 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4311 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
4313 assert( GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN );
4314 UpdateWindow( hparent );
4315 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4317 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
4318 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4319 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
4320 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4321 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4322 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
4324 UpdateWindow( hparent );
4325 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4327 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
4328 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4329 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
4330 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4331 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4332 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
4334 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
4335 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
4336 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
4337 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4338 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
4340 assert( !(GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN) );
4341 UpdateWindow( hparent );
4342 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4344 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
4345 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4346 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
4347 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4348 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4349 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
4351 UpdateWindow( hparent );
4352 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4354 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
4355 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
4356 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
4357 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
4358 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
4359 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
4361 log_all_parent_messages--;
4362 DestroyWindow( hparent );
4363 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
4365 DeleteObject( hrgn );
4366 DeleteObject( hrgn2 );
4375 static DWORD WINAPI thread_proc(void *param)
4378 struct wnd_event *wnd_event = (struct wnd_event *)param;
4380 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
4381 100, 100, 200, 200, 0, 0, 0, NULL);
4382 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
4384 SetEvent(wnd_event->event);
4386 while (GetMessage(&msg, 0, 0, 0))
4388 TranslateMessage(&msg);
4389 DispatchMessage(&msg);
4392 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
4397 static void test_interthread_messages(void)
4404 int len, expected_len;
4405 struct wnd_event wnd_event;
4408 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
4409 if (!wnd_event.event)
4411 trace("skipping interthread message test under win9x\n");
4415 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
4416 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
4418 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4420 CloseHandle(wnd_event.event);
4422 SetLastError(0xdeadbeef);
4423 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
4424 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
4426 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
4427 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
4429 expected_len = lstrlenA("window caption text");
4430 memset(buf, 0, sizeof(buf));
4431 SetLastError(0xdeadbeef);
4432 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
4433 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
4434 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
4436 msg.hwnd = wnd_event.hwnd;
4437 msg.message = WM_GETTEXT;
4438 msg.wParam = sizeof(buf);
4439 msg.lParam = (LPARAM)buf;
4440 memset(buf, 0, sizeof(buf));
4441 SetLastError(0xdeadbeef);
4442 len = DispatchMessageA(&msg);
4443 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4444 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
4446 /* the following test causes an exception in user.exe under win9x */
4447 msg.hwnd = wnd_event.hwnd;
4448 msg.message = WM_TIMER;
4450 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
4451 SetLastError(0xdeadbeef);
4452 len = DispatchMessageA(&msg);
4453 ok(!len && GetLastError() == 0xdeadbeef,
4454 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
4456 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
4457 ok( ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4459 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
4460 CloseHandle(hThread);
4462 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
4466 static const struct message WmVkN[] = {
4467 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4468 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4469 { WM_CHAR, wparam|lparam, 'n', 1 },
4470 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
4471 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4472 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4475 static const struct message WmShiftVkN[] = {
4476 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
4477 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
4478 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4479 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4480 { WM_CHAR, wparam|lparam, 'N', 1 },
4481 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
4482 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4483 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4484 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
4485 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
4488 static const struct message WmCtrlVkN[] = {
4489 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4490 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4491 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4492 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
4493 { WM_CHAR, wparam|lparam, 0x000e, 1 },
4494 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
4495 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4496 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4497 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4498 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4501 static const struct message WmCtrlVkN_2[] = {
4502 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4503 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4504 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4505 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
4506 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4507 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4508 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4509 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4512 static const struct message WmAltVkN[] = {
4513 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4514 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4515 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
4516 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
4517 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
4518 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
4519 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
4520 { HCBT_SYSCOMMAND, hook },
4521 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4522 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4523 { 0x00AE, sent|defwinproc|optional }, /* XP */
4524 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */
4525 { WM_INITMENU, sent|defwinproc },
4526 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4527 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
4528 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
4529 { WM_CAPTURECHANGED, sent|defwinproc },
4530 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
4531 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4532 { WM_EXITMENULOOP, sent|defwinproc },
4533 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
4534 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
4535 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4536 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4537 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4538 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4541 static const struct message WmAltVkN_2[] = {
4542 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4543 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4544 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
4545 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
4546 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
4547 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4548 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4549 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4552 static const struct message WmCtrlAltVkN[] = {
4553 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4554 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4555 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4556 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4557 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
4558 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
4559 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
4560 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4561 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4562 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4563 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4564 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4567 static const struct message WmCtrlShiftVkN[] = {
4568 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4569 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4570 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
4571 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
4572 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
4573 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 },
4574 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
4575 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
4576 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
4577 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
4578 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4579 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4582 static const struct message WmCtrlAltShiftVkN[] = {
4583 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
4584 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
4585 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4586 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4587 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 },
4588 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 },
4589 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
4590 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 },
4591 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
4592 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
4593 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 },
4594 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 },
4595 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4596 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4597 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
4598 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
4601 static const struct message WmAltPressRelease[] = {
4602 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4603 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4604 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4605 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4606 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 },
4607 { HCBT_SYSCOMMAND, hook },
4608 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
4609 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4610 { WM_INITMENU, sent|defwinproc },
4611 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4612 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE) },
4613 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4615 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4616 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
4617 { WM_CAPTURECHANGED, sent|defwinproc },
4618 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) },
4619 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
4620 { WM_EXITMENULOOP, sent|defwinproc },
4621 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4622 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4625 static const struct message WmAltMouseButton[] = {
4626 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4627 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4628 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
4629 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
4630 { WM_LBUTTONDOWN, wparam, MK_LBUTTON, 0 },
4631 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON, 0 },
4632 { WM_LBUTTONUP, wparam, 0, 0 },
4633 { WM_LBUTTONUP, sent|wparam, 0, 0 },
4634 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4635 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4638 static const struct message WmF1Seq[] = {
4639 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 },
4640 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 },
4641 { 0x4d, wparam|lparam, 0, 0 },
4642 { 0x4d, sent|wparam|lparam, 0, 0 },
4643 { WM_HELP, sent|defwinproc },
4644 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 },
4645 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 },
4649 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
4653 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
4655 struct message log_msg;
4657 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
4659 /* ignore some unwanted messages */
4660 if (msg.message == WM_MOUSEMOVE ||
4661 msg.message == WM_GETICON ||
4662 msg.message == WM_DEVICECHANGE)
4665 log_msg.message = msg.message;
4666 log_msg.flags = wparam|lparam;
4667 log_msg.wParam = msg.wParam;
4668 log_msg.lParam = msg.lParam;
4669 add_message(&log_msg);
4671 if (!hAccel || !TranslateAccelerator(hwnd, hAccel, &msg))
4673 TranslateMessage(&msg);
4674 DispatchMessage(&msg);
4679 static void test_accelerators(void)
4684 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4685 100, 100, 200, 200, 0, 0, 0, NULL);
4691 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
4693 state = GetKeyState(VK_SHIFT);
4694 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
4695 state = GetKeyState(VK_CAPITAL);
4696 ok(state == 0, "wrong CapsLock state %04x\n", state);
4698 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
4699 assert(hAccel != 0);
4701 pump_msg_loop(hwnd, 0);
4704 trace("testing VK_N press/release\n");
4706 keybd_event('N', 0, 0, 0);
4707 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4708 pump_msg_loop(hwnd, hAccel);
4709 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4711 trace("testing Shift+VK_N press/release\n");
4713 keybd_event(VK_SHIFT, 0, 0, 0);
4714 keybd_event('N', 0, 0, 0);
4715 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4716 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4717 pump_msg_loop(hwnd, hAccel);
4718 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4720 trace("testing Ctrl+VK_N press/release\n");
4722 keybd_event(VK_CONTROL, 0, 0, 0);
4723 keybd_event('N', 0, 0, 0);
4724 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4725 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4726 pump_msg_loop(hwnd, hAccel);
4727 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
4729 trace("testing Alt+VK_N press/release\n");
4731 keybd_event(VK_MENU, 0, 0, 0);
4732 keybd_event('N', 0, 0, 0);
4733 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4734 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4735 pump_msg_loop(hwnd, hAccel);
4736 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
4738 trace("testing Ctrl+Alt+VK_N press/release 1\n");
4740 keybd_event(VK_CONTROL, 0, 0, 0);
4741 keybd_event(VK_MENU, 0, 0, 0);
4742 keybd_event('N', 0, 0, 0);
4743 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4744 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4745 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4746 pump_msg_loop(hwnd, hAccel);
4747 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
4749 ret = DestroyAcceleratorTable(hAccel);
4750 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4752 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
4753 assert(hAccel != 0);
4755 trace("testing VK_N press/release\n");
4757 keybd_event('N', 0, 0, 0);
4758 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4759 pump_msg_loop(hwnd, hAccel);
4760 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4762 trace("testing Shift+VK_N press/release\n");
4764 keybd_event(VK_SHIFT, 0, 0, 0);
4765 keybd_event('N', 0, 0, 0);
4766 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4767 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4768 pump_msg_loop(hwnd, hAccel);
4769 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4771 trace("testing Ctrl+VK_N press/release 2\n");
4773 keybd_event(VK_CONTROL, 0, 0, 0);
4774 keybd_event('N', 0, 0, 0);
4775 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4776 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4777 pump_msg_loop(hwnd, hAccel);
4778 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
4780 trace("testing Alt+VK_N press/release 2\n");
4782 keybd_event(VK_MENU, 0, 0, 0);
4783 keybd_event('N', 0, 0, 0);
4784 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4785 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4786 pump_msg_loop(hwnd, hAccel);
4787 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
4789 trace("testing Ctrl+Alt+VK_N press/release 2\n");
4791 keybd_event(VK_CONTROL, 0, 0, 0);
4792 keybd_event(VK_MENU, 0, 0, 0);
4793 keybd_event('N', 0, 0, 0);
4794 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4795 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4796 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4797 pump_msg_loop(hwnd, hAccel);
4798 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
4800 trace("testing Ctrl+Shift+VK_N press/release\n");
4802 keybd_event(VK_CONTROL, 0, 0, 0);
4803 keybd_event(VK_SHIFT, 0, 0, 0);
4804 keybd_event('N', 0, 0, 0);
4805 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4806 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4807 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4808 pump_msg_loop(hwnd, hAccel);
4809 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE);
4811 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
4813 keybd_event(VK_CONTROL, 0, 0, 0);
4814 keybd_event(VK_MENU, 0, 0, 0);
4815 keybd_event(VK_SHIFT, 0, 0, 0);
4816 keybd_event('N', 0, 0, 0);
4817 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4818 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4819 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4820 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4821 pump_msg_loop(hwnd, hAccel);
4822 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE);
4824 ret = DestroyAcceleratorTable(hAccel);
4825 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4827 trace("testing Alt press/release\n");
4829 keybd_event(VK_MENU, 0, 0, 0);
4830 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4831 keybd_event(VK_MENU, 0, 0, 0);
4832 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4833 pump_msg_loop(hwnd, 0);
4834 /* this test doesn't pass in Wine for managed windows */
4835 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
4837 trace("testing Alt+MouseButton press/release\n");
4838 /* first, move mouse pointer inside of the window client area */
4839 GetClientRect(hwnd, &rc);
4840 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
4841 rc.left += (rc.right - rc.left)/2;
4842 rc.top += (rc.bottom - rc.top)/2;
4843 SetCursorPos(rc.left, rc.top);
4845 pump_msg_loop(hwnd, 0);
4847 keybd_event(VK_MENU, 0, 0, 0);
4848 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
4849 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
4850 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4851 pump_msg_loop(hwnd, 0);
4852 ok_sequence(WmAltMouseButton, "Alt+MouseButton press/release", FALSE);
4854 keybd_event(VK_F1, 0, 0, 0);
4855 keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0);
4856 pump_msg_loop(hwnd, 0);
4857 ok_sequence(WmF1Seq, "F1 press/release", TRUE);
4859 DestroyWindow(hwnd);
4862 /************* window procedures ********************/
4864 static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message,
4865 WPARAM wParam, LPARAM lParam)
4867 static long defwndproc_counter = 0;
4868 static long beginpaint_counter = 0;
4872 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4874 /* explicitly ignore WM_GETICON message */
4875 if (message == WM_GETICON) return 0;
4881 LONG style = GetWindowLongA(hwnd, GWL_STYLE);
4882 ok((BOOL)wParam == !(style & WS_DISABLED),
4883 "wrong WS_DISABLED state: %d != %d\n", wParam, !(style & WS_DISABLED));
4887 case WM_CAPTURECHANGED:
4888 if (test_DestroyWindow_flag)
4890 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
4891 if (style & WS_CHILD)
4892 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
4893 else if (style & WS_POPUP)
4894 lParam = WND_POPUP_ID;
4896 lParam = WND_PARENT_ID;
4904 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
4905 capture = GetCapture();
4908 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture);
4909 trace("current capture %p, releasing...\n", capture);
4916 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n");
4917 if (test_DestroyWindow_flag)
4919 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
4920 if (style & WS_CHILD)
4921 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
4922 else if (style & WS_POPUP)
4923 lParam = WND_POPUP_ID;
4925 lParam = WND_PARENT_ID;
4929 /* test_accelerators() depends on this */
4936 case WM_DEVICECHANGE:
4939 case WM_WINDOWPOSCHANGING:
4940 case WM_WINDOWPOSCHANGED:
4942 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4944 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4945 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4946 winpos->hwnd, winpos->hwndInsertAfter,
4947 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4949 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4950 * in the high word for internal purposes
4952 wParam = winpos->flags & 0xffff;
4957 msg.message = message;
4958 msg.flags = sent|wparam|lparam;
4959 if (defwndproc_counter) msg.flags |= defwinproc;
4960 if (beginpaint_counter) msg.flags |= beginpaint;
4961 msg.wParam = wParam;
4962 msg.lParam = lParam;
4965 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
4967 HWND parent = GetParent(hwnd);
4969 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
4971 GetClientRect(parent, &rc);
4972 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
4974 trace("ptReserved = (%ld,%ld)\n"
4975 "ptMaxSize = (%ld,%ld)\n"
4976 "ptMaxPosition = (%ld,%ld)\n"
4977 "ptMinTrackSize = (%ld,%ld)\n"
4978 "ptMaxTrackSize = (%ld,%ld)\n",
4979 minmax->ptReserved.x, minmax->ptReserved.y,
4980 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
4981 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
4982 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
4983 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
4985 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
4986 minmax->ptMaxSize.x, rc.right);
4987 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
4988 minmax->ptMaxSize.y, rc.bottom);
4991 if (message == WM_PAINT)
4994 beginpaint_counter++;
4995 BeginPaint( hwnd, &ps );
4996 beginpaint_counter--;
4997 EndPaint( hwnd, &ps );
5001 defwndproc_counter++;
5002 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam)
5003 : DefWindowProcA(hwnd, message, wParam, lParam);
5004 defwndproc_counter--;
5009 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5011 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);
5014 static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5016 return MsgCheckProc (TRUE, hwnd, message, wParam, lParam);
5019 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5021 static long defwndproc_counter = 0;
5025 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
5027 /* explicitly ignore WM_GETICON message */
5028 if (message == WM_GETICON) return 0;
5030 msg.message = message;
5031 msg.flags = sent|wparam|lparam;
5032 if (defwndproc_counter) msg.flags |= defwinproc;
5033 msg.wParam = wParam;
5034 msg.lParam = lParam;
5037 if (message == WM_CREATE)
5039 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
5040 SetWindowLongA(hwnd, GWL_STYLE, style);
5043 defwndproc_counter++;
5044 ret = DefWindowProcA(hwnd, message, wParam, lParam);
5045 defwndproc_counter--;
5050 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5052 static long defwndproc_counter = 0;
5053 static long beginpaint_counter = 0;
5057 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
5059 /* explicitly ignore WM_GETICON message */
5060 if (message == WM_GETICON) return 0;
5062 if (log_all_parent_messages ||
5063 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
5064 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
5065 message == WM_ENABLE || message == WM_ENTERIDLE ||
5066 message == WM_IME_SETCONTEXT)
5073 INT ret = GetClipBox((HDC)wParam, &rc);
5075 trace("WM_ERASEBKGND: GetClipBox()=%d, (%ld,%ld-%ld,%ld)\n",
5076 ret, rc.left, rc.top, rc.right, rc.bottom);
5080 case WM_WINDOWPOSCHANGING:
5081 case WM_WINDOWPOSCHANGED:
5083 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
5085 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
5086 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
5087 winpos->hwnd, winpos->hwndInsertAfter,
5088 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
5090 /* Log only documented flags, win2k uses 0x1000 and 0x2000
5091 * in the high word for internal purposes
5093 wParam = winpos->flags & 0xffff;
5098 msg.message = message;
5099 msg.flags = sent|parent|wparam|lparam;
5100 if (defwndproc_counter) msg.flags |= defwinproc;
5101 if (beginpaint_counter) msg.flags |= beginpaint;
5102 msg.wParam = wParam;
5103 msg.lParam = lParam;
5107 if (message == WM_PAINT)
5110 beginpaint_counter++;
5111 BeginPaint( hwnd, &ps );
5112 beginpaint_counter--;
5113 EndPaint( hwnd, &ps );
5117 defwndproc_counter++;
5118 ret = DefWindowProcA(hwnd, message, wParam, lParam);
5119 defwndproc_counter--;
5124 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
5126 static long defwndproc_counter = 0;
5130 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
5132 /* explicitly ignore WM_GETICON message */
5133 if (message == WM_GETICON) return 0;
5135 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
5136 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
5137 if (after_end_dialog)
5138 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
5140 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
5144 case WM_WINDOWPOSCHANGING:
5145 case WM_WINDOWPOSCHANGED:
5147 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
5149 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
5150 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
5151 winpos->hwnd, winpos->hwndInsertAfter,
5152 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
5154 /* Log only documented flags, win2k uses 0x1000 and 0x2000
5155 * in the high word for internal purposes
5157 wParam = winpos->flags & 0xffff;
5162 msg.message = message;
5163 msg.flags = sent|wparam|lparam;
5164 if (defwndproc_counter) msg.flags |= defwinproc;
5165 msg.wParam = wParam;
5166 msg.lParam = lParam;
5169 defwndproc_counter++;
5170 ret = DefDlgProcA(hwnd, message, wParam, lParam);
5171 defwndproc_counter--;
5176 static BOOL RegisterWindowClasses(void)
5181 cls.lpfnWndProc = MsgCheckProcA;
5184 cls.hInstance = GetModuleHandleA(0);
5186 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
5187 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5188 cls.lpszMenuName = NULL;
5189 cls.lpszClassName = "TestWindowClass";
5190 if(!RegisterClassA(&cls)) return FALSE;
5192 cls.lpfnWndProc = PopupMsgCheckProcA;
5193 cls.lpszClassName = "TestPopupClass";
5194 if(!RegisterClassA(&cls)) return FALSE;
5196 cls.lpfnWndProc = ParentMsgCheckProcA;
5197 cls.lpszClassName = "TestParentClass";
5198 if(!RegisterClassA(&cls)) return FALSE;
5200 cls.lpfnWndProc = DefWindowProcA;
5201 cls.lpszClassName = "SimpleWindowClass";
5202 if(!RegisterClassA(&cls)) return FALSE;
5204 cls.style = CS_NOCLOSE;
5205 cls.lpszClassName = "NoCloseWindowClass";
5206 if(!RegisterClassA(&cls)) return FALSE;
5208 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
5210 cls.hInstance = GetModuleHandleA(0);
5211 cls.hbrBackground = 0;
5212 cls.lpfnWndProc = TestDlgProcA;
5213 cls.lpszClassName = "TestDialogClass";
5214 if(!RegisterClassA(&cls)) return FALSE;
5219 static HHOOK hCBT_hook;
5220 static DWORD cbt_hook_thread_id;
5222 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
5224 static const char *CBT_code_name[10] = {
5231 "HCBT_CLICKSKIPPED",
5235 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
5239 trace("CBT: %d (%s), %08x, %08lx\n", nCode, code_name, wParam, lParam);
5241 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
5243 if (nCode == HCBT_SYSCOMMAND)
5247 msg.message = nCode;
5248 msg.flags = hook|wparam|lparam;
5249 msg.wParam = wParam;
5250 msg.lParam = lParam;
5253 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
5256 if (nCode == HCBT_DESTROYWND)
5258 if (test_DestroyWindow_flag)
5260 DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE);
5261 if (style & WS_CHILD)
5262 lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID);
5263 else if (style & WS_POPUP)
5264 lParam = WND_POPUP_ID;
5266 lParam = WND_PARENT_ID;
5270 /* Log also SetFocus(0) calls */
5271 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
5273 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5275 if (!lstrcmpiA(buf, "TestWindowClass") ||
5276 !lstrcmpiA(buf, "TestParentClass") ||
5277 !lstrcmpiA(buf, "TestPopupClass") ||
5278 !lstrcmpiA(buf, "SimpleWindowClass") ||
5279 !lstrcmpiA(buf, "TestDialogClass") ||
5280 !lstrcmpiA(buf, "MDI_frame_class") ||
5281 !lstrcmpiA(buf, "MDI_client_class") ||
5282 !lstrcmpiA(buf, "MDI_child_class") ||
5283 !lstrcmpiA(buf, "my_button_class") ||
5284 !lstrcmpiA(buf, "my_edit_class") ||
5285 !lstrcmpiA(buf, "static") ||
5286 !lstrcmpiA(buf, "#32770"))
5290 msg.message = nCode;
5291 msg.flags = hook|wparam|lparam;
5292 msg.wParam = wParam;
5293 msg.lParam = lParam;
5297 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
5300 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
5310 trace("WEH:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
5311 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
5313 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
5315 /* ignore mouse cursor events */
5316 if (object_id == OBJID_CURSOR) return;
5318 if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf)))
5321 !lstrcmpiA(buf, "TestWindowClass") ||
5322 !lstrcmpiA(buf, "TestParentClass") ||
5323 !lstrcmpiA(buf, "TestPopupClass") ||
5324 !lstrcmpiA(buf, "SimpleWindowClass") ||
5325 !lstrcmpiA(buf, "TestDialogClass") ||
5326 !lstrcmpiA(buf, "MDI_frame_class") ||
5327 !lstrcmpiA(buf, "MDI_client_class") ||
5328 !lstrcmpiA(buf, "MDI_child_class") ||
5329 !lstrcmpiA(buf, "my_button_class") ||
5330 !lstrcmpiA(buf, "my_edit_class") ||
5331 !lstrcmpiA(buf, "static") ||
5332 !lstrcmpiA(buf, "#32770"))
5336 msg.message = event;
5337 msg.flags = winevent_hook|wparam|lparam;
5338 msg.wParam = object_id;
5339 msg.lParam = child_id;
5345 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
5346 static const WCHAR wszAnsi[] = {'U',0};
5348 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5352 case CB_FINDSTRINGEXACT:
5353 trace("String: %p\n", (LPCWSTR)lParam);
5354 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
5356 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
5360 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
5363 static const struct message WmGetTextLengthAfromW[] = {
5364 { WM_GETTEXTLENGTH, sent },
5365 { WM_GETTEXT, sent },
5369 static const WCHAR testWindowClassW[] =
5370 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
5372 static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0};
5374 /* dummy window proc for WM_GETTEXTLENGTH test */
5375 static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
5379 case WM_GETTEXTLENGTH:
5380 return lstrlenW(dummy_window_text) + 37; /* some random length */
5382 lstrcpynW( (LPWSTR)lp, dummy_window_text, wp );
5383 return lstrlenW( (LPWSTR)lp );
5385 return DefWindowProcW( hwnd, msg, wp, lp );
5389 static void test_message_conversion(void)
5391 static const WCHAR wszMsgConversionClass[] =
5392 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
5396 WNDPROC wndproc, newproc;
5400 cls.lpfnWndProc = MsgConversionProcW;
5403 cls.hInstance = GetModuleHandleW(NULL);
5405 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
5406 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
5407 cls.lpszMenuName = NULL;
5408 cls.lpszClassName = wszMsgConversionClass;
5409 /* this call will fail on Win9x, but that doesn't matter as this test is
5410 * meaningless on those platforms */
5411 if(!RegisterClassW(&cls)) return;
5414 cls.lpfnWndProc = MsgCheckProcW;
5417 cls.hInstance = GetModuleHandleW(0);
5419 cls.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
5420 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5421 cls.lpszMenuName = NULL;
5422 cls.lpszClassName = testWindowClassW;
5423 if(!RegisterClassW(&cls)) return;
5425 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
5426 100, 100, 200, 200, 0, 0, 0, NULL);
5427 ok(hwnd != NULL, "Window creation failed\n");
5431 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
5432 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5433 ok(lRes == 0, "String should have been converted\n");
5434 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5435 ok(lRes == 1, "String shouldn't have been converted\n");
5439 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
5440 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5441 ok(lRes == 1, "String shouldn't have been converted\n");
5442 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5443 ok(lRes == 1, "String shouldn't have been converted\n");
5445 /* Synchronous messages */
5447 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5448 ok(lRes == 0, "String should have been converted\n");
5449 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5450 ok(lRes == 1, "String shouldn't have been converted\n");
5452 /* Asynchronous messages */
5455 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5456 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5457 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5459 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5460 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5461 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5463 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5464 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5465 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5467 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5468 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5469 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5471 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5472 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5473 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5475 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
5476 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5477 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5479 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
5480 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5481 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5483 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
5484 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
5485 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
5487 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
5489 hwnd = CreateWindowW (testWindowClassW, wszUnicode,
5490 WS_OVERLAPPEDWINDOW,
5491 100, 100, 200, 200, 0, 0, 0, NULL);
5494 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0);
5495 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
5496 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
5497 "got bad length %ld\n", lRes );
5500 lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ),
5501 hwnd, WM_GETTEXTLENGTH, 0, 0);
5502 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
5503 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
5504 "got bad length %ld\n", lRes );
5506 wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc );
5507 newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC );
5508 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
5509 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
5510 NULL, 0, NULL, NULL ),
5511 "got bad length %ld\n", lRes );
5513 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */
5514 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
5515 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
5516 NULL, 0, NULL, NULL ),
5517 "got bad length %ld\n", lRes );
5519 ret = DestroyWindow(hwnd);
5520 ok( ret, "DestroyWindow() error %ld\n", GetLastError());
5523 typedef struct _thread_info
5530 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
5534 #define TIMER_ID 0x19
5536 static DWORD WINAPI timer_thread_proc(LPVOID x)
5538 thread_info *info = x;
5541 r = KillTimer(info->hWnd, 0x19);
5542 ok(r,"KillTimer failed in thread\n");
5543 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
5544 ok(r,"SetTimer failed in thread\n");
5545 ok(r==TIMER_ID,"SetTimer id different\n");
5546 r = SetEvent(info->handles[0]);
5547 ok(r,"SetEvent failed in thread\n");
5551 static void test_timers(void)
5556 info.hWnd = CreateWindow ("TestWindowClass", NULL,
5557 WS_OVERLAPPEDWINDOW ,
5558 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5561 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
5562 ok(info.id, "SetTimer failed\n");
5563 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
5564 info.handles[0] = CreateEvent(NULL,0,0,NULL);
5565 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
5567 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
5569 WaitForSingleObject(info.handles[1], INFINITE);
5571 CloseHandle(info.handles[0]);
5572 CloseHandle(info.handles[1]);
5574 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
5576 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
5579 /* Various win events with arbitrary parameters */
5580 static const struct message WmWinEventsSeq[] = {
5581 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
5582 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
5583 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
5584 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
5585 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
5586 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
5587 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
5588 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
5589 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
5590 /* our win event hook ignores OBJID_CURSOR events */
5591 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
5592 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
5593 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
5594 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
5595 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
5596 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
5597 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
5598 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
5599 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
5600 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
5601 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
5602 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
5603 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
5604 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
5607 static const struct message WmWinEventCaretSeq[] = {
5608 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5609 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5610 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */
5611 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
5614 static const struct message WmWinEventCaretSeq_2[] = {
5615 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5616 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5617 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
5620 static const struct message WmWinEventAlertSeq[] = {
5621 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 },
5624 static const struct message WmWinEventAlertSeq_2[] = {
5625 /* create window in the thread proc */
5626 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 },
5627 /* our test event */
5628 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 },
5631 static const struct message WmGlobalHookSeq_1[] = {
5632 /* create window in the thread proc */
5633 { HCBT_CREATEWND, hook|lparam, 0, 2 },
5634 /* our test events */
5635 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 },
5636 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 },
5639 static const struct message WmGlobalHookSeq_2[] = {
5640 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */
5641 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */
5642 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */
5643 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */
5647 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent,
5657 trace("WEH_2:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
5658 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
5660 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5662 if (!lstrcmpiA(buf, "TestWindowClass") ||
5663 !lstrcmpiA(buf, "static"))
5667 msg.message = event;
5668 msg.flags = winevent_hook|wparam|lparam;
5669 msg.wParam = object_id;
5670 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2);
5676 static HHOOK hCBT_global_hook;
5677 static DWORD cbt_global_hook_thread_id;
5679 static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
5684 trace("CBT_2: %d, %08x, %08lx\n", nCode, wParam, lParam);
5686 if (nCode == HCBT_SYSCOMMAND)
5690 msg.message = nCode;
5691 msg.flags = hook|wparam|lparam;
5692 msg.wParam = wParam;
5693 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
5696 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
5699 /* Log also SetFocus(0) calls */
5700 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
5702 if (GetClassNameA(hwnd, buf, sizeof(buf)))
5704 if (!lstrcmpiA(buf, "TestWindowClass") ||
5705 !lstrcmpiA(buf, "static"))
5709 msg.message = nCode;
5710 msg.flags = hook|wparam|lparam;
5711 msg.wParam = wParam;
5712 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
5716 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
5719 static DWORD WINAPI win_event_global_thread_proc(void *param)
5723 HANDLE hevent = *(HANDLE *)param;
5724 HMODULE user32 = GetModuleHandleA("user32.dll");
5725 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
5727 assert(pNotifyWinEvent);
5729 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
5731 trace("created thread window %p\n", hwnd);
5733 *(HWND *)param = hwnd;
5736 /* this event should be received only by our new hook proc,
5737 * an old one does not expect an event from another thread.
5739 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0);
5742 while (GetMessage(&msg, 0, 0, 0))
5744 TranslateMessage(&msg);
5745 DispatchMessage(&msg);
5750 static DWORD WINAPI cbt_global_hook_thread_proc(void *param)
5754 HANDLE hevent = *(HANDLE *)param;
5757 /* these events should be received only by our new hook proc,
5758 * an old one does not expect an event from another thread.
5761 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
5763 trace("created thread window %p\n", hwnd);
5765 *(HWND *)param = hwnd;
5767 /* Windows doesn't like when a thread plays games with the focus,
5768 that leads to all kinds of misbehaviours and failures to activate
5769 a window. So, better keep next lines commented out.
5773 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
5774 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
5778 while (GetMessage(&msg, 0, 0, 0))
5780 TranslateMessage(&msg);
5781 DispatchMessage(&msg);
5786 static void test_winevents(void)
5792 HANDLE hthread, hevent;
5794 HWINEVENTHOOK hhook;
5795 const struct message *events = WmWinEventsSeq;
5796 HMODULE user32 = GetModuleHandleA("user32.dll");
5797 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
5798 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
5799 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
5801 hwnd = CreateWindowExA(0, "TestWindowClass", NULL,
5802 WS_OVERLAPPEDWINDOW,
5803 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5807 /****** start of global hook test *************/
5808 hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0);
5809 assert(hCBT_global_hook);
5811 hevent = CreateEventA(NULL, 0, 0, NULL);
5813 hwnd2 = (HWND)hevent;
5815 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid);
5816 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5818 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5820 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
5823 /* this one should be received only by old hook proc */
5824 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
5825 /* this one should be received only by old hook proc */
5826 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
5828 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
5830 ret = UnhookWindowsHookEx(hCBT_global_hook);
5831 ok( ret, "UnhookWindowsHookEx error %ld\n", GetLastError());
5833 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5834 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5835 CloseHandle(hthread);
5836 CloseHandle(hevent);
5837 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5838 /****** end of global hook test *************/
5840 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent)
5842 ok(DestroyWindow(hwnd), "failed to destroy window\n");
5848 #if 0 /* this test doesn't pass under Win9x */
5849 /* win2k ignores events with hwnd == 0 */
5850 SetLastError(0xdeadbeef);
5851 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
5852 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
5853 GetLastError() == 0xdeadbeef, /* Win9x */
5854 "unexpected error %ld\n", GetLastError());
5855 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
5858 for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
5859 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
5861 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
5863 /****** start of event filtering test *************/
5864 hhook = (HWINEVENTHOOK)pSetWinEventHook(
5865 EVENT_OBJECT_SHOW, /* 0x8002 */
5866 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */
5867 GetModuleHandleA(0), win_event_global_hook_proc,
5868 GetCurrentProcessId(), 0,
5869 WINEVENT_INCONTEXT);
5870 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
5872 hevent = CreateEventA(NULL, 0, 0, NULL);
5874 hwnd2 = (HWND)hevent;
5876 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
5877 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5879 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5881 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
5884 /* this one should be received only by old hook proc */
5885 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
5886 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
5887 /* this one should be received only by old hook proc */
5888 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
5890 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
5892 ret = pUnhookWinEvent(hhook);
5893 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5895 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5896 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5897 CloseHandle(hthread);
5898 CloseHandle(hevent);
5899 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5900 /****** end of event filtering test *************/
5902 /****** start of out of context event test *************/
5903 hhook = (HWINEVENTHOOK)pSetWinEventHook(
5904 EVENT_MIN, EVENT_MAX,
5905 0, win_event_global_hook_proc,
5906 GetCurrentProcessId(), 0,
5907 WINEVENT_OUTOFCONTEXT);
5908 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
5910 hevent = CreateEventA(NULL, 0, 0, NULL);
5912 hwnd2 = (HWND)hevent;
5916 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
5917 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5919 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5921 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
5922 /* process pending winevent messages */
5923 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
5924 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
5927 /* this one should be received only by old hook proc */
5928 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
5929 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
5930 /* this one should be received only by old hook proc */
5931 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
5933 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE);
5934 /* process pending winevent messages */
5935 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
5936 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
5938 ret = pUnhookWinEvent(hhook);
5939 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
5941 PostThreadMessageA(tid, WM_QUIT, 0, 0);
5942 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5943 CloseHandle(hthread);
5944 CloseHandle(hevent);
5945 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
5946 /****** end of out of context event test *************/
5948 ok(DestroyWindow(hwnd), "failed to destroy window\n");
5951 static void test_set_hook(void)
5955 HWINEVENTHOOK hwinevent_hook;
5956 HMODULE user32 = GetModuleHandleA("user32.dll");
5957 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
5958 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
5960 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId());
5961 ok(hhook != 0, "local hook does not require hModule set to 0\n");
5962 UnhookWindowsHookEx(hhook);
5964 #if 0 /* this test doesn't pass under Win9x: BUG! */
5965 SetLastError(0xdeadbeef);
5966 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0);
5967 ok(!hhook, "global hook requires hModule != 0\n");
5968 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %ld\n", GetLastError());
5971 SetLastError(0xdeadbeef);
5972 hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId());
5973 ok(!hhook, "SetWinEventHook with invalid proc should fail\n");
5974 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */
5975 GetLastError() == 0xdeadbeef, /* Win9x */
5976 "unexpected error %ld\n", GetLastError());
5978 SetLastError(0xdeadbeef);
5979 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
5980 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */
5981 GetLastError() == 0xdeadbeef, /* Win9x */
5982 "unexpected error %ld\n", GetLastError());
5984 if (!pSetWinEventHook || !pUnhookWinEvent) return;
5986 /* even process local incontext hooks require hmodule */
5987 SetLastError(0xdeadbeef);
5988 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
5989 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
5990 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
5991 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
5992 GetLastError() == 0xdeadbeef, /* Win9x */
5993 "unexpected error %ld\n", GetLastError());
5995 /* even thread local incontext hooks require hmodule */
5996 SetLastError(0xdeadbeef);
5997 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
5998 0, win_event_proc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT);
5999 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
6000 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
6001 GetLastError() == 0xdeadbeef, /* Win9x */
6002 "unexpected error %ld\n", GetLastError());
6004 #if 0 /* these 3 tests don't pass under Win9x */
6005 SetLastError(0xdeadbeef);
6006 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(1, 0,
6007 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
6008 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
6009 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
6011 SetLastError(0xdeadbeef);
6012 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(-1, 1,
6013 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
6014 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
6015 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
6017 SetLastError(0xdeadbeef);
6018 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6019 0, win_event_proc, 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT);
6020 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n");
6021 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %ld\n", GetLastError());
6024 SetLastError(0xdeadbeef);
6025 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(0, 0,
6026 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
6027 ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
6028 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
6029 ret = pUnhookWinEvent(hwinevent_hook);
6030 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
6033 /* This call succeeds under win2k SP4, but fails under Wine.
6034 Does win2k test/use passed process id? */
6035 SetLastError(0xdeadbeef);
6036 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6037 0, win_event_proc, 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT);
6038 ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
6039 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
6040 ret = pUnhookWinEvent(hwinevent_hook);
6041 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
6044 SetLastError(0xdeadbeef);
6045 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n");
6046 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
6047 GetLastError() == 0xdeadbeef, /* Win9x */
6048 "unexpected error %ld\n", GetLastError());
6051 static const struct message ScrollWindowPaint1[] = {
6053 { WM_ERASEBKGND, sent|beginpaint },
6057 static const struct message ScrollWindowPaint2[] = {
6062 static void test_scrollwindowex(void)
6065 RECT rect={0,0,130,130};
6068 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll",
6069 WS_VISIBLE|WS_OVERLAPPEDWINDOW,
6070 100, 100, 200, 200, 0, 0, 0, NULL);
6071 ok (hwnd != 0, "Failed to create overlapped window\n");
6072 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
6073 WS_VISIBLE|WS_CAPTION|WS_CHILD,
6074 10, 10, 150, 150, hwnd, 0, 0, NULL);
6075 ok (hchild != 0, "Failed to create child\n");
6077 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6080 /* scroll without the child window */
6081 trace("start scroll\n");
6082 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
6083 SW_ERASE|SW_INVALIDATE);
6084 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
6085 trace("end scroll\n");
6087 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6088 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
6090 /* Now without the SW_ERASE flag */
6091 trace("start scroll\n");
6092 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE);
6093 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
6094 trace("end scroll\n");
6096 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6097 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", 0);
6099 /* now scroll the child window as well */
6100 trace("start scroll\n");
6101 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
6102 SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
6103 todo_wine { /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
6104 /* windows sometimes a WM_MOVE */
6105 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
6107 trace("end scroll\n");
6109 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6110 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
6112 /* now scroll with ScrollWindow() */
6113 trace("start scroll with ScrollWindow\n");
6114 ScrollWindow( hwnd, 5, 5, NULL, NULL);
6115 trace("end scroll\n");
6117 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6118 ok_sequence(ScrollWindowPaint1, "ScrollWindow", 0);
6120 ok(DestroyWindow(hchild), "failed to destroy window\n");
6121 ok(DestroyWindow(hwnd), "failed to destroy window\n");
6125 static const struct message destroy_window_with_children[] = {
6126 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
6127 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */
6128 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */
6129 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
6130 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
6131 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
6132 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
6133 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */
6134 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
6135 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
6136 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
6137 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
6138 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
6139 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
6140 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
6141 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
6145 static void test_DestroyWindow(void)
6148 HWND parent, child1, child2, child3, child4, test;
6149 UINT child_id = WND_CHILD_ID + 1;
6151 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6152 100, 100, 200, 200, 0, 0, 0, NULL);
6153 assert(parent != 0);
6154 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
6155 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL);
6156 assert(child1 != 0);
6157 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
6158 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL);
6159 assert(child2 != 0);
6160 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
6161 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL);
6162 assert(child3 != 0);
6163 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP,
6164 0, 0, 50, 50, parent, 0, 0, NULL);
6165 assert(child4 != 0);
6167 /* test owner/parent of child2 */
6168 test = GetParent(child2);
6169 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6170 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
6172 test = pGetAncestor(child2, GA_PARENT);
6173 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6175 test = GetWindow(child2, GW_OWNER);
6176 ok(!test, "wrong owner %p\n", test);
6178 test = SetParent(child2, parent);
6179 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test);
6181 /* test owner/parent of the parent */
6182 test = GetParent(parent);
6183 ok(!test, "wrong parent %p\n", test);
6185 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent);
6188 test = pGetAncestor(parent, GA_PARENT);
6189 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6191 test = GetWindow(parent, GW_OWNER);
6192 ok(!test, "wrong owner %p\n", test);
6194 /* test owner/parent of child1 */
6195 test = GetParent(child1);
6196 ok(test == parent, "wrong parent %p\n", test);
6197 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
6199 test = pGetAncestor(child1, GA_PARENT);
6200 ok(test == parent, "wrong parent %p\n", test);
6202 test = GetWindow(child1, GW_OWNER);
6203 ok(!test, "wrong owner %p\n", test);
6205 /* test owner/parent of child2 */
6206 test = GetParent(child2);
6207 ok(test == parent, "wrong parent %p\n", test);
6208 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
6210 test = pGetAncestor(child2, GA_PARENT);
6211 ok(test == parent, "wrong parent %p\n", test);
6213 test = GetWindow(child2, GW_OWNER);
6214 ok(!test, "wrong owner %p\n", test);
6216 /* test owner/parent of child3 */
6217 test = GetParent(child3);
6218 ok(test == child1, "wrong parent %p\n", test);
6219 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
6221 test = pGetAncestor(child3, GA_PARENT);
6222 ok(test == child1, "wrong parent %p\n", test);
6224 test = GetWindow(child3, GW_OWNER);
6225 ok(!test, "wrong owner %p\n", test);
6227 /* test owner/parent of child4 */
6228 test = GetParent(child4);
6229 ok(test == parent, "wrong parent %p\n", test);
6230 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
6232 test = pGetAncestor(child4, GA_PARENT);
6233 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
6235 test = GetWindow(child4, GW_OWNER);
6236 ok(test == parent, "wrong owner %p\n", test);
6240 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
6241 parent, child1, child2, child3, child4);
6244 test = GetCapture();
6245 ok(test == child4, "wrong capture window %p\n", test);
6247 test_DestroyWindow_flag = TRUE;
6248 ret = DestroyWindow(parent);
6249 ok( ret, "DestroyWindow() error %ld\n", GetLastError());
6250 test_DestroyWindow_flag = FALSE;
6251 ok_sequence(destroy_window_with_children, "destroy window with children", 0);
6253 ok(!IsWindow(parent), "parent still exists\n");
6254 ok(!IsWindow(child1), "child1 still exists\n");
6255 ok(!IsWindow(child2), "child2 still exists\n");
6256 ok(!IsWindow(child3), "child3 still exists\n");
6257 ok(!IsWindow(child4), "child4 still exists\n");
6259 test = GetCapture();
6260 ok(!test, "wrong capture window %p\n", test);
6264 static const struct message WmDispatchPaint[] = {
6265 { WM_NCPAINT, sent },
6266 { WM_GETTEXT, sent|defwinproc|optional },
6267 { WM_GETTEXT, sent|defwinproc|optional },
6268 { WM_ERASEBKGND, sent },
6272 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6274 if (message == WM_PAINT) return 0;
6275 return MsgCheckProcA( hwnd, message, wParam, lParam );
6278 static void test_DispatchMessage(void)
6283 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6284 100, 100, 200, 200, 0, 0, 0, NULL);
6285 ShowWindow( hwnd, SW_SHOW );
6286 UpdateWindow( hwnd );
6287 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6289 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc );
6291 SetRect( &rect, -5, -5, 5, 5 );
6292 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
6294 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
6296 if (msg.message != WM_PAINT) DispatchMessage( &msg );
6300 DispatchMessage( &msg );
6301 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
6302 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
6303 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE );
6304 if (++count > 10) break;
6307 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" );
6309 trace("now without DispatchMessage\n");
6311 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
6313 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
6315 if (msg.message != WM_PAINT) DispatchMessage( &msg );
6318 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
6320 /* this will send WM_NCCPAINT just like DispatchMessage does */
6321 GetUpdateRgn( hwnd, hrgn, TRUE );
6322 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
6323 DeleteObject( hrgn );
6324 GetClientRect( hwnd, &rect );
6325 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */
6326 ok( !count, "Got multiple WM_PAINTs\n" );
6327 if (++count > 10) break;
6333 static const struct message WmUser[] = {
6345 static DWORD CALLBACK send_msg_thread( LPVOID arg )
6347 struct thread_info *info = arg;
6348 info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL );
6349 if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT, "unexpected error %ld\n", GetLastError());
6353 static void wait_for_thread( HANDLE thread )
6355 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0)
6358 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage(&msg);
6362 static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6364 if (message == WM_USER) Sleep(200);
6365 return MsgCheckProcA( hwnd, message, wParam, lParam );
6368 static void test_SendMessageTimeout(void)
6372 struct thread_info info;
6375 info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6376 100, 100, 200, 200, 0, 0, 0, NULL);
6377 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
6380 info.timeout = 1000;
6381 info.ret = 0xdeadbeef;
6382 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6383 wait_for_thread( thread );
6384 CloseHandle( thread );
6385 ok( info.ret == 1, "SendMessageTimeout failed\n" );
6386 ok_sequence( WmUser, "WmUser", FALSE );
6389 info.ret = 0xdeadbeef;
6390 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6391 Sleep(100); /* SendMessageTimeout should timeout here */
6392 wait_for_thread( thread );
6393 CloseHandle( thread );
6394 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
6395 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
6397 /* 0 means infinite timeout */
6399 info.ret = 0xdeadbeef;
6400 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6402 wait_for_thread( thread );
6403 CloseHandle( thread );
6404 ok( info.ret == 1, "SendMessageTimeout failed\n" );
6405 ok_sequence( WmUser, "WmUser", FALSE );
6407 /* timeout is treated as signed despite the prototype */
6408 info.timeout = 0x7fffffff;
6409 info.ret = 0xdeadbeef;
6410 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6412 wait_for_thread( thread );
6413 CloseHandle( thread );
6414 ok( info.ret == 1, "SendMessageTimeout failed\n" );
6415 ok_sequence( WmUser, "WmUser", FALSE );
6417 info.timeout = 0x80000000;
6418 info.ret = 0xdeadbeef;
6419 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6421 wait_for_thread( thread );
6422 CloseHandle( thread );
6423 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
6424 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
6426 /* now check for timeout during message processing */
6427 SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc );
6429 info.ret = 0xdeadbeef;
6430 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
6431 wait_for_thread( thread );
6432 CloseHandle( thread );
6433 /* we should timeout but still get the message */
6434 ok( info.ret == 0, "SendMessageTimeout failed\n" );
6435 ok_sequence( WmUser, "WmUser", FALSE );
6437 DestroyWindow( info.hwnd );
6441 /****************** edit message test *************************/
6442 #define ID_EDIT 0x1234
6443 static const struct message sl_edit_setfocus[] =
6445 { HCBT_SETFOCUS, hook },
6446 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
6447 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6448 { WM_SETFOCUS, sent|wparam, 0 },
6449 { WM_CTLCOLOREDIT, sent|parent },
6450 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6451 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6452 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6455 static const struct message ml_edit_setfocus[] =
6457 { HCBT_SETFOCUS, hook },
6458 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
6459 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6460 { WM_SETFOCUS, sent|wparam, 0 },
6461 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6462 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6463 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6464 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6467 static const struct message sl_edit_killfocus[] =
6469 { HCBT_SETFOCUS, hook },
6470 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6471 { WM_KILLFOCUS, sent|wparam, 0 },
6472 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6473 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6474 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) },
6475 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
6478 static const struct message sl_edit_lbutton_dblclk[] =
6480 { WM_LBUTTONDBLCLK, sent },
6481 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6484 static const struct message sl_edit_lbutton_down[] =
6486 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
6487 { HCBT_SETFOCUS, hook },
6488 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
6489 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6490 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
6491 { WM_CTLCOLOREDIT, sent|parent },
6492 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6493 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6494 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6495 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6496 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6497 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6498 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6499 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6502 static const struct message ml_edit_lbutton_down[] =
6504 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
6505 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6506 { HCBT_SETFOCUS, hook },
6507 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
6508 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6509 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
6510 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6511 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6512 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
6515 static const struct message sl_edit_lbutton_up[] =
6517 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6518 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6519 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6520 { WM_CAPTURECHANGED, sent|defwinproc },
6521 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
6524 static const struct message ml_edit_lbutton_up[] =
6526 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6527 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6528 { WM_CAPTURECHANGED, sent|defwinproc },
6532 static WNDPROC old_edit_proc;
6534 static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6536 static long defwndproc_counter = 0;
6540 trace("edit: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
6542 /* explicitly ignore WM_GETICON message */
6543 if (message == WM_GETICON) return 0;
6545 msg.message = message;
6546 msg.flags = sent|wparam|lparam;
6547 if (defwndproc_counter) msg.flags |= defwinproc;
6548 msg.wParam = wParam;
6549 msg.lParam = lParam;
6552 defwndproc_counter++;
6553 ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam);
6554 defwndproc_counter--;
6559 static void subclass_edit(void)
6563 if (!GetClassInfoA(0, "edit", &cls)) assert(0);
6565 old_edit_proc = cls.lpfnWndProc;
6567 cls.hInstance = GetModuleHandle(0);
6568 cls.lpfnWndProc = edit_hook_proc;
6569 cls.lpszClassName = "my_edit_class";
6570 if (!RegisterClassA(&cls)) assert(0);
6573 static void test_edit_messages(void)
6579 log_all_parent_messages++;
6581 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6582 100, 100, 200, 200, 0, 0, 0, NULL);
6583 ok (parent != 0, "Failed to create parent window\n");
6585 /* test single line edit */
6586 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD,
6587 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
6588 ok(hwnd != 0, "Failed to create edit window\n");
6590 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
6591 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08lx\n", dlg_code);
6593 ShowWindow(hwnd, SW_SHOW);
6599 ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE);
6602 ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE);
6608 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
6609 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE);
6615 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
6616 ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE);
6618 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
6619 ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE);
6621 DestroyWindow(hwnd);
6623 /* test multiline edit */
6624 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE,
6625 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
6626 ok(hwnd != 0, "Failed to create edit window\n");
6628 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
6629 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS),
6630 "wrong dlg_code %08lx\n", dlg_code);
6632 ShowWindow(hwnd, SW_SHOW);
6638 ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE);
6641 ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE);
6647 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
6648 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE);
6654 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
6655 ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE);
6657 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
6658 ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE);
6660 DestroyWindow(hwnd);
6661 DestroyWindow(parent);
6663 log_all_parent_messages--;
6666 /**************************** End of Edit test ******************************/
6671 HMODULE user32 = GetModuleHandleA("user32.dll");
6672 FARPROC pSetWinEventHook = GetProcAddress(user32, "SetWinEventHook");
6673 FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
6674 FARPROC pIsWinEventHookInstalled = 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
6675 pGetAncestor = (void*) GetProcAddress(user32, "GetAncestor");
6677 if (!RegisterWindowClasses()) assert(0);
6679 if (pSetWinEventHook)
6681 hEvent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
6682 GetModuleHandleA(0),
6685 GetCurrentThreadId(),
6686 WINEVENT_INCONTEXT);
6687 assert(hEvent_hook);
6689 if (pIsWinEventHookInstalled)
6692 for (event = EVENT_MIN; event <= EVENT_MAX; event++)
6693 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
6697 cbt_hook_thread_id = GetCurrentThreadId();
6698 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
6703 /* Fix message sequences before removing 4 lines below */
6705 ret = pUnhookWinEvent(hEvent_hook);
6706 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
6707 pUnhookWinEvent = 0;
6711 test_scrollwindowex();
6713 test_mdi_messages();
6714 test_button_messages();
6715 test_paint_messages();
6716 test_interthread_messages();
6717 test_message_conversion();
6718 test_accelerators();
6721 test_DestroyWindow();
6722 test_DispatchMessage();
6723 test_SendMessageTimeout();
6724 test_edit_messages();
6726 UnhookWindowsHookEx(hCBT_hook);
6727 if (pUnhookWinEvent)
6729 ret = pUnhookWinEvent(hEvent_hook);
6730 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
6731 SetLastError(0xdeadbeef);
6732 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n");
6733 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
6734 GetLastError() == 0xdeadbeef, /* Win9x */
6735 "unexpected error %ld\n", GetLastError());