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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define _WIN32_WINNT 0x0501 /* For WM_CHANGEUISTATE,QS_RAWINPUT */
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
42 #define SWP_STATECHANGED 0x8000
44 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
47 #define WM_SYSTIMER 0x0118
50 #define WND_PARENT_ID 1
51 #define WND_POPUP_ID 2
52 #define WND_CHILD_ID 3
54 #ifndef WM_LBTRACKPOINT
55 #define WM_LBTRACKPOINT 0x0131
58 /* encoded DRAWITEMSTRUCT into an LPARAM */
65 UINT type : 4; /* ODT_* flags */
66 UINT ctl_id : 4; /* Control ID */
67 UINT item_id : 4; /* Menu item ID */
68 UINT action : 4; /* ODA_* flags */
69 UINT state : 16; /* ODS_* flags */
75 static BOOL test_DestroyWindow_flag;
76 static HWINEVENTHOOK hEvent_hook;
78 static void dump_winpos_flags(UINT flags);
80 static const WCHAR testWindowClassW[] =
81 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
84 FIXME: add tests for these
85 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
86 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
87 WS_THICKFRAME: thick border
88 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
89 WS_BORDER (default for overlapped windows): single black border
90 none (default for child (and popup?) windows): no border
107 UINT message; /* the WM_* code */
108 msg_flags_t flags; /* message props */
109 WPARAM wParam; /* expected value of wParam */
110 LPARAM lParam; /* expected value of lParam */
113 /* Empty message sequence */
114 static const struct message WmEmptySeq[] =
118 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
119 static const struct message WmCreateOverlappedSeq[] = {
120 { HCBT_CREATEWND, hook },
121 { WM_GETMINMAXINFO, sent },
122 { WM_NCCREATE, sent },
123 { WM_NCCALCSIZE, sent|wparam, 0 },
124 { 0x0093, sent|defwinproc|optional },
125 { 0x0094, sent|defwinproc|optional },
126 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
128 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
131 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
132 * for a not visible overlapped window.
134 static const struct message WmSWP_ShowOverlappedSeq[] = {
135 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
136 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
137 { WM_NCPAINT, sent|wparam|optional, 1 },
138 { WM_GETTEXT, sent|defwinproc|optional },
139 { WM_ERASEBKGND, sent|optional },
140 { HCBT_ACTIVATE, hook },
141 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
142 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
143 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
144 { WM_ACTIVATEAPP, sent|wparam, 1 },
145 { WM_NCACTIVATE, sent|wparam, 1 },
146 { WM_GETTEXT, sent|defwinproc|optional },
147 { WM_ACTIVATE, sent|wparam, 1 },
148 { HCBT_SETFOCUS, hook },
149 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
150 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
151 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
152 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
153 { WM_NCPAINT, sent|wparam|optional, 1 },
154 { WM_GETTEXT, sent|defwinproc|optional },
155 { WM_ERASEBKGND, sent|optional },
156 /* Win9x adds SWP_NOZORDER below */
157 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
158 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
159 { WM_NCPAINT, sent|wparam|optional, 1 },
160 { WM_ERASEBKGND, sent|optional },
161 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
164 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
165 * for a visible overlapped window.
167 static const struct message WmSWP_HideOverlappedSeq[] = {
168 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
169 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
170 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
174 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
175 * for a visible overlapped window.
177 static const struct message WmSWP_ResizeSeq[] = {
178 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE },
179 { WM_GETMINMAXINFO, sent|defwinproc },
180 { WM_NCCALCSIZE, sent|wparam, TRUE },
181 { WM_NCPAINT, sent|optional },
182 { WM_GETTEXT, sent|defwinproc|optional },
183 { WM_ERASEBKGND, sent|optional },
184 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE },
185 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
186 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
187 { WM_NCPAINT, sent|optional },
188 { WM_GETTEXT, sent|defwinproc|optional },
189 { WM_ERASEBKGND, sent|optional },
190 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
191 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
195 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
196 * for a visible popup window.
198 static const struct message WmSWP_ResizePopupSeq[] = {
199 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE },
200 { WM_GETMINMAXINFO, sent|defwinproc|optional }, /* Win9x */
201 { WM_NCCALCSIZE, sent|wparam, TRUE },
202 { WM_NCPAINT, sent|optional },
203 { WM_GETTEXT, sent|defwinproc|optional },
204 { WM_ERASEBKGND, sent|optional },
205 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE },
206 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
207 { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
208 { WM_NCPAINT, sent|optional },
209 { WM_GETTEXT, sent|defwinproc|optional },
210 { WM_ERASEBKGND, sent|optional },
211 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
215 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
216 * for a visible overlapped window.
218 static const struct message WmSWP_MoveSeq[] = {
219 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE },
220 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOCLIENTSIZE },
221 { WM_MOVE, sent|defwinproc|wparam, 0 },
222 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
225 /* Resize with SetWindowPos(SWP_NOZORDER)
226 * for a visible overlapped window
227 * SWP_NOZORDER is stripped by the logging code
229 static const struct message WmSWP_ResizeNoZOrder[] = {
230 { WM_WINDOWPOSCHANGING, sent|wparam, 0/*SWP_NOZORDER*/ },
231 { WM_GETMINMAXINFO, sent|defwinproc },
232 { WM_NCCALCSIZE, sent|wparam, 1 },
233 { WM_NCPAINT, sent },
234 { WM_GETTEXT, sent|defwinproc|optional },
235 { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */
236 { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE },
237 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
238 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */
239 { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */
240 { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */
241 { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */
242 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
243 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
247 /* Switch visible mdi children */
248 static const struct message WmSwitchChild[] = {
249 /* Switch MDI child */
250 { WM_MDIACTIVATE, sent },/* in the MDI client */
251 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */
252 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
253 { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */
254 /* Deactivate 2nd MDI child */
255 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */
256 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */
257 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
258 /* Preparing for maximize and maximaze the 1st MDI child */
259 { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */
260 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */
261 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */
262 { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
263 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 }, /* in the 1st MDI child */
264 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */
265 /* Lock redraw 2nd MDI child */
266 { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */
267 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA },
268 /* Restore 2nd MDI child */
269 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000 },/* in the 2nd MDI child */
270 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */
271 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */
272 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 }, /* in the 2nd MDI child */
273 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */
274 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */
275 /* Redraw 2nd MDI child */
276 { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */
277 /* Redraw MDI frame */
278 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },/* in MDI frame */
279 { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */
280 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in MDI frame */
281 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */
282 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
283 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
284 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */
285 { HCBT_SETFOCUS, hook },
286 { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */
287 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },/* in the 1st MDI child */
288 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
289 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
290 { WM_SETFOCUS, sent },/* in the MDI client */
291 { HCBT_SETFOCUS, hook },
292 { WM_KILLFOCUS, sent },/* in the MDI client */
293 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
294 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, /* in the 1st MDI child */
295 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
296 { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */
297 { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */
298 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* in the 1st MDI child */
302 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
303 SWP_NOZORDER|SWP_FRAMECHANGED)
304 * for a visible overlapped window with WS_CLIPCHILDREN style set.
306 static const struct message WmSWP_FrameChanged_clip[] = {
307 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED },
308 { WM_NCCALCSIZE, sent|wparam|parent, 1 },
309 { WM_NCPAINT, sent|parent }, /* wparam != 1 */
310 { WM_GETTEXT, sent|parent|defwinproc|optional },
311 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
312 { WM_NCPAINT, sent }, /* wparam != 1 */
313 { WM_ERASEBKGND, sent },
314 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
315 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
319 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
320 SWP_NOZORDER|SWP_FRAMECHANGED)
321 * for a visible overlapped window.
323 static const struct message WmSWP_FrameChangedDeferErase[] = {
324 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED },
325 { WM_NCCALCSIZE, sent|wparam|parent, 1 },
326 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
327 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
328 { WM_PAINT, sent|parent },
329 { WM_NCPAINT, sent|beginpaint|parent }, /* wparam != 1 */
330 { WM_GETTEXT, sent|beginpaint|parent|defwinproc|optional },
332 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
333 { WM_ERASEBKGND, sent|beginpaint },
337 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
338 SWP_NOZORDER|SWP_FRAMECHANGED)
339 * for a visible overlapped window without WS_CLIPCHILDREN style set.
341 static const struct message WmSWP_FrameChanged_noclip[] = {
342 { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED },
343 { WM_NCCALCSIZE, sent|wparam|parent, 1 },
344 { WM_NCPAINT, sent|parent }, /* wparam != 1 */
345 { WM_GETTEXT, sent|parent|defwinproc|optional },
346 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
347 { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
348 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
350 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
351 { WM_ERASEBKGND, sent|beginpaint },
355 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
356 static const struct message WmShowOverlappedSeq[] = {
357 { WM_SHOWWINDOW, sent|wparam, 1 },
358 { WM_NCPAINT, sent|wparam|optional, 1 },
359 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
360 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
361 { WM_NCPAINT, sent|wparam|optional, 1 },
362 { WM_GETTEXT, sent|defwinproc|optional },
363 { WM_ERASEBKGND, sent|optional },
364 { HCBT_ACTIVATE, hook },
365 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
366 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
367 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
368 { WM_NCPAINT, sent|wparam|optional, 1 },
369 { WM_ACTIVATEAPP, sent|wparam, 1 },
370 { WM_NCACTIVATE, sent|wparam, 1 },
371 { WM_GETTEXT, sent|defwinproc|optional },
372 { WM_ACTIVATE, sent|wparam, 1 },
373 { HCBT_SETFOCUS, hook },
374 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
375 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
376 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
377 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
378 { WM_NCPAINT, sent|wparam|optional, 1 },
379 { WM_GETTEXT, sent|defwinproc|optional },
380 { WM_ERASEBKGND, sent|optional },
381 /* Win9x adds SWP_NOZORDER below */
382 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
383 { WM_NCCALCSIZE, sent|optional },
384 { WM_NCPAINT, sent|optional },
385 { WM_ERASEBKGND, sent|optional },
386 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
387 * messages. Does that mean that CreateWindow doesn't set initial
388 * window dimensions for overlapped windows?
395 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
396 static const struct message WmShowMaxOverlappedSeq[] = {
397 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
398 { WM_GETMINMAXINFO, sent },
399 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
400 { WM_GETMINMAXINFO, sent|defwinproc },
401 { WM_NCCALCSIZE, sent|wparam, TRUE },
402 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
403 { HCBT_ACTIVATE, hook },
404 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
405 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
406 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
407 { WM_ACTIVATEAPP, sent|wparam, 1 },
408 { WM_NCACTIVATE, sent|wparam, 1 },
409 { WM_GETTEXT, sent|defwinproc|optional },
410 { WM_ACTIVATE, sent|wparam, 1 },
411 { HCBT_SETFOCUS, hook },
412 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
413 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
414 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
415 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
416 { WM_NCPAINT, sent|wparam|optional, 1 },
417 { WM_GETTEXT, sent|defwinproc|optional },
418 { WM_ERASEBKGND, sent|optional },
419 /* Win9x adds SWP_NOZORDER below */
420 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
421 { WM_MOVE, sent|defwinproc },
422 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
423 { WM_NCCALCSIZE, sent|optional },
424 { WM_NCPAINT, sent|optional },
425 { WM_ERASEBKGND, sent|optional },
426 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
427 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
430 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
431 static const struct message WmShowMinOverlappedSeq[] = {
432 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
433 { HCBT_SETFOCUS, hook },
434 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
435 { WM_KILLFOCUS, sent },
436 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
437 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 },
438 { WM_GETTEXT, sent|optional },
439 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCOPYBITS|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED },
440 { WM_GETMINMAXINFO, sent|defwinproc },
441 { WM_NCCALCSIZE, sent|wparam, TRUE },
442 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
443 { WM_NCPAINT, sent },
444 { WM_GETTEXT, sent|defwinproc|optional },
445 { WM_WINDOWPOSCHANGED, sent },
446 { WM_MOVE, sent|defwinproc },
447 { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
448 { WM_NCCALCSIZE, sent|optional },
449 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
450 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
451 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
452 { WM_NCACTIVATE, sent|wparam, 0 },
453 { WM_GETTEXT, sent|defwinproc|optional },
454 { WM_ACTIVATE, sent },
455 { WM_ACTIVATEAPP, sent|wparam, 0 },
458 /* ShowWindow(SW_HIDE) for a visible overlapped window */
459 static const struct message WmHideOverlappedSeq[] = {
460 { WM_SHOWWINDOW, sent|wparam, 0 },
461 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
462 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
463 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
464 { WM_SIZE, sent|optional }, /* XP doesn't send it */
465 { WM_MOVE, sent|optional }, /* XP doesn't send it */
466 { WM_NCACTIVATE, sent|wparam, 0 },
467 { WM_ACTIVATE, sent|wparam, 0 },
468 { WM_ACTIVATEAPP, sent|wparam, 0 },
469 { WM_KILLFOCUS, sent|wparam, 0 },
470 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
471 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 },
474 /* DestroyWindow for a visible overlapped window */
475 static const struct message WmDestroyOverlappedSeq[] = {
476 { HCBT_DESTROYWND, hook },
477 { 0x0090, sent|optional },
478 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
479 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
480 { 0x0090, sent|optional },
481 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
482 { WM_NCACTIVATE, sent|wparam, 0 },
483 { WM_ACTIVATE, sent|wparam, 0 },
484 { WM_ACTIVATEAPP, sent|wparam, 0 },
485 { WM_KILLFOCUS, sent|wparam, 0 },
486 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
487 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 },
488 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
489 { WM_DESTROY, sent },
490 { WM_NCDESTROY, sent },
493 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
494 static const struct message WmCreateMaxPopupSeq[] = {
495 { HCBT_CREATEWND, hook },
496 { WM_NCCREATE, sent },
497 { WM_NCCALCSIZE, sent|wparam, 0 },
499 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
500 { WM_SIZE, sent|wparam, SIZE_RESTORED },
502 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
503 { WM_GETMINMAXINFO, sent },
504 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000 },
505 { WM_NCCALCSIZE, sent|wparam, TRUE },
506 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|0x8000 },
507 { WM_MOVE, sent|defwinproc },
508 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
509 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
510 { WM_SHOWWINDOW, sent|wparam, 1 },
511 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
512 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
513 { HCBT_ACTIVATE, hook },
514 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
515 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
516 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
517 { WM_ACTIVATEAPP, sent|wparam, 1 },
518 { WM_NCACTIVATE, sent|wparam, 1 },
519 { WM_ACTIVATE, sent|wparam, 1 },
520 { HCBT_SETFOCUS, hook },
521 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
522 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
523 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
524 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
525 { WM_SYNCPAINT, sent|wparam|optional, 4 },
526 { WM_NCPAINT, sent|wparam|optional, 1 },
527 { WM_ERASEBKGND, sent|optional },
528 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE },
531 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
532 static const struct message WmCreateInvisibleMaxPopupSeq[] = {
533 { HCBT_CREATEWND, hook },
534 { WM_NCCREATE, sent },
535 { WM_NCCALCSIZE, sent|wparam, 0 },
537 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
538 { WM_SIZE, sent|wparam, SIZE_RESTORED },
540 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
541 { WM_GETMINMAXINFO, sent },
542 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000 },
543 { WM_NCCALCSIZE, sent|wparam, TRUE },
544 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|0x8000 },
545 { WM_MOVE, sent|defwinproc },
546 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
547 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
550 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
551 static const struct message WmShowMaxPopupResizedSeq[] = {
552 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
553 { WM_GETMINMAXINFO, sent },
554 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
555 { WM_NCCALCSIZE, sent|wparam, TRUE },
556 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
557 { HCBT_ACTIVATE, hook },
558 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
559 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
560 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
561 { WM_ACTIVATEAPP, sent|wparam, 1 },
562 { WM_NCACTIVATE, sent|wparam, 1 },
563 { WM_ACTIVATE, sent|wparam, 1 },
564 { HCBT_SETFOCUS, hook },
565 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
566 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
567 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
568 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
569 { WM_NCPAINT, sent|wparam|optional, 1 },
570 { WM_ERASEBKGND, sent|optional },
571 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE },
572 /* WinNT4.0 sends WM_MOVE */
573 { WM_MOVE, sent|defwinproc|optional },
574 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
575 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
578 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
579 static const struct message WmShowMaxPopupSeq[] = {
580 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
581 { WM_GETMINMAXINFO, sent },
582 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
583 { WM_NCCALCSIZE, sent|wparam, TRUE },
584 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
585 { HCBT_ACTIVATE, hook },
586 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
587 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
588 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
589 { WM_ACTIVATEAPP, sent|wparam, 1 },
590 { WM_NCACTIVATE, sent|wparam, 1 },
591 { WM_ACTIVATE, sent|wparam, 1 },
592 { HCBT_SETFOCUS, hook },
593 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
594 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
595 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
596 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
597 { WM_SYNCPAINT, sent|wparam|optional, 4 },
598 { WM_NCPAINT, sent|wparam|optional, 1 },
599 { WM_ERASEBKGND, sent|optional },
600 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE },
601 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
604 /* CreateWindow(WS_VISIBLE) for popup window */
605 static const struct message WmCreatePopupSeq[] = {
606 { HCBT_CREATEWND, hook },
607 { WM_NCCREATE, sent },
608 { WM_NCCALCSIZE, sent|wparam, 0 },
610 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
611 { WM_SIZE, sent|wparam, SIZE_RESTORED },
613 { WM_SHOWWINDOW, sent|wparam, 1 },
614 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
615 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
616 { HCBT_ACTIVATE, hook },
617 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
618 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
619 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
620 { WM_NCPAINT, sent|wparam|optional, 1 },
621 { WM_ERASEBKGND, sent|optional },
622 { WM_ACTIVATEAPP, sent|wparam, 1 },
623 { WM_NCACTIVATE, sent|wparam, 1 },
624 { WM_ACTIVATE, sent|wparam, 1 },
625 { HCBT_SETFOCUS, hook },
626 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
627 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
628 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
629 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
630 { WM_SYNCPAINT, sent|wparam|optional, 4 },
631 { WM_NCPAINT, sent|wparam|optional, 1 },
632 { WM_ERASEBKGND, sent|optional },
633 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE },
636 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
637 static const struct message WmShowVisMaxPopupSeq[] = {
638 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
639 { WM_GETMINMAXINFO, sent },
640 { WM_GETTEXT, sent|optional },
641 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
642 { WM_NCCALCSIZE, sent|wparam, TRUE },
643 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
644 { WM_NCPAINT, sent|wparam|optional, 1 },
645 { WM_ERASEBKGND, sent|optional },
646 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|0x8000 },
647 { WM_MOVE, sent|defwinproc },
648 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
649 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
652 /* CreateWindow (for a child popup window, not initially visible) */
653 static const struct message WmCreateChildPopupSeq[] = {
654 { HCBT_CREATEWND, hook },
655 { WM_NCCREATE, sent },
656 { WM_NCCALCSIZE, sent|wparam, 0 },
658 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
659 { WM_SIZE, sent|wparam, SIZE_RESTORED },
663 /* CreateWindow (for a popup window, not initially visible,
664 * which sets WS_VISIBLE in WM_CREATE handler)
666 static const struct message WmCreateInvisiblePopupSeq[] = {
667 { HCBT_CREATEWND, hook },
668 { WM_NCCREATE, sent },
669 { WM_NCCALCSIZE, sent|wparam, 0 },
671 { WM_STYLECHANGING, sent },
672 { WM_STYLECHANGED, sent },
673 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
674 { WM_SIZE, sent|wparam, SIZE_RESTORED },
678 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
679 * for a popup window with WS_VISIBLE style set
681 static const struct message WmShowVisiblePopupSeq_2[] = {
682 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
685 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
686 * for a popup window with WS_VISIBLE style set
688 static const struct message WmShowVisiblePopupSeq_3[] = {
689 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
690 { HCBT_ACTIVATE, hook },
691 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
692 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
693 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
694 { WM_NCACTIVATE, sent|wparam, 1 },
695 { WM_ACTIVATE, sent|wparam, 1 },
696 { HCBT_SETFOCUS, hook },
697 { WM_KILLFOCUS, sent|parent },
698 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
699 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
700 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
701 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
702 { WM_SETFOCUS, sent|defwinproc },
705 /* CreateWindow (for child window, not initially visible) */
706 static const struct message WmCreateChildSeq[] = {
707 { HCBT_CREATEWND, hook },
708 { WM_NCCREATE, sent },
709 /* child is inserted into parent's child list after WM_NCCREATE returns */
710 { WM_NCCALCSIZE, sent|wparam, 0 },
712 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
713 { WM_SIZE, sent|wparam, SIZE_RESTORED },
715 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
718 /* CreateWindow (for maximized child window, not initially visible) */
719 static const struct message WmCreateMaximizedChildSeq[] = {
720 { HCBT_CREATEWND, hook },
721 { WM_NCCREATE, sent },
722 { WM_NCCALCSIZE, sent|wparam, 0 },
724 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
725 { WM_SIZE, sent|wparam, SIZE_RESTORED },
727 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
728 { WM_GETMINMAXINFO, sent },
729 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
730 { WM_NCCALCSIZE, sent|wparam, 1 },
731 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 },
732 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
733 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
734 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
737 /* CreateWindow (for a child window, initially visible) */
738 static const struct message WmCreateVisibleChildSeq[] = {
739 { HCBT_CREATEWND, hook },
740 { WM_NCCREATE, sent },
741 /* child is inserted into parent's child list after WM_NCCREATE returns */
742 { WM_NCCALCSIZE, sent|wparam, 0 },
743 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
745 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
746 { WM_SIZE, sent|wparam, SIZE_RESTORED },
748 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
749 { WM_SHOWWINDOW, sent|wparam, 1 },
750 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
751 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
752 { WM_ERASEBKGND, sent|parent|optional },
753 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
754 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */
755 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
758 /* ShowWindow(SW_SHOW) for a not visible child window */
759 static const struct message WmShowChildSeq[] = {
760 { WM_SHOWWINDOW, sent|wparam, 1 },
761 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
762 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
763 { WM_ERASEBKGND, sent|parent|optional },
764 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
767 /* ShowWindow(SW_HIDE) for a visible child window */
768 static const struct message WmHideChildSeq[] = {
769 { WM_SHOWWINDOW, sent|wparam, 0 },
770 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
771 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
772 { WM_ERASEBKGND, sent|parent|optional },
773 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
776 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
777 static const struct message WmHideChildSeq2[] = {
778 { WM_SHOWWINDOW, sent|wparam, 0 },
779 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
780 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
781 { WM_ERASEBKGND, sent|parent },
782 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
785 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
786 * for a not visible child window
788 static const struct message WmShowChildSeq_2[] = {
789 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
790 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
791 { WM_CHILDACTIVATE, sent },
792 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
795 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
796 * for a not visible child window
798 static const struct message WmShowChildSeq_3[] = {
799 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
800 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
801 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
804 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
805 * for a visible child window with a caption
807 static const struct message WmShowChildSeq_4[] = {
808 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
809 { WM_CHILDACTIVATE, sent },
812 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
813 static const struct message WmShowChildInvisibleParentSeq_1[] = {
814 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
815 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|0x8000 },
816 { WM_NCCALCSIZE, sent|wparam, 1 },
817 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
818 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|0x8000 },
819 { WM_MOVE, sent|defwinproc },
820 { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
821 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
822 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
823 /* FIXME: Wine creates an icon/title window while Windows doesn't */
824 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE },
825 { WM_GETTEXT, sent|optional },
828 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
829 static const struct message WmShowChildInvisibleParentSeq_1r[] = {
830 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
833 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
834 static const struct message WmShowChildInvisibleParentSeq_2[] = {
835 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
836 { WM_GETMINMAXINFO, sent },
837 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
838 { WM_NCCALCSIZE, sent|wparam, 1 },
839 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
840 { WM_CHILDACTIVATE, sent },
841 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 },
842 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
843 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
846 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
847 static const struct message WmShowChildInvisibleParentSeq_2r[] = {
848 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
851 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
852 static const struct message WmShowChildInvisibleParentSeq_3[] = {
853 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED },
854 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
855 { WM_NCCALCSIZE, sent|wparam, 1 },
856 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
857 { WM_CHILDACTIVATE, sent },
858 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|0x8000 },
859 { WM_MOVE, sent|defwinproc },
860 { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
861 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
862 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
863 /* FIXME: Wine creates an icon/title window while Windows doesn't */
864 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE },
865 { WM_GETTEXT, sent|optional },
868 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
869 static const struct message WmShowChildInvisibleParentSeq_3r[] = {
870 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED },
873 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
874 static const struct message WmShowChildInvisibleParentSeq_4[] = {
875 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE },
876 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|0x8000 },
877 { WM_NCCALCSIZE, sent|wparam, 1 },
878 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
879 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|0x8000 },
880 { WM_MOVE, sent|defwinproc },
881 { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
882 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
883 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
884 /* FIXME: Wine creates an icon/title window while Windows doesn't */
885 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE },
886 { WM_GETTEXT, sent|optional },
889 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
890 static const struct message WmShowChildInvisibleParentSeq_4r[] = {
891 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE },
894 /* ShowWindow(SW_SHOW) for child with invisible parent */
895 static const struct message WmShowChildInvisibleParentSeq_5[] = {
896 { WM_SHOWWINDOW, sent|wparam, 1 },
899 /* ShowWindow(SW_HIDE) for child with invisible parent */
900 static const struct message WmHideChildInvisibleParentSeq[] = {
901 { WM_SHOWWINDOW, sent|wparam, 0 },
904 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
905 static const struct message WmShowChildInvisibleParentSeq_6[] = {
906 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
907 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
908 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
911 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
912 static const struct message WmHideChildInvisibleParentSeq_2[] = {
913 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
914 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
915 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
918 /* DestroyWindow for a visible child window */
919 static const struct message WmDestroyChildSeq[] = {
920 { HCBT_DESTROYWND, hook },
921 { 0x0090, sent|optional },
922 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
923 { WM_SHOWWINDOW, sent|wparam, 0 },
924 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
925 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
926 { WM_ERASEBKGND, sent|parent|optional },
927 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
928 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
929 { WM_KILLFOCUS, sent },
930 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
931 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
932 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
933 { WM_SETFOCUS, sent|parent },
934 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
935 { WM_DESTROY, sent },
936 { WM_DESTROY, sent|optional }, /* some other (IME?) window */
937 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */
938 { WM_NCDESTROY, sent },
941 /* DestroyWindow for a visible child window with invisible parent */
942 static const struct message WmDestroyInvisibleChildSeq[] = {
943 { HCBT_DESTROYWND, hook },
944 { 0x0090, sent|optional },
945 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
946 { WM_SHOWWINDOW, sent|wparam, 0 },
947 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
948 { WM_DESTROY, sent },
949 { WM_NCDESTROY, sent },
952 /* Moving the mouse in nonclient area */
953 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
954 { WM_NCHITTEST, sent },
955 { WM_SETCURSOR, sent },
956 { WM_NCMOUSEMOVE, posted },
959 /* Moving the mouse in client area */
960 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
961 { WM_NCHITTEST, sent },
962 { WM_SETCURSOR, sent },
963 { WM_MOUSEMOVE, posted },
966 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
967 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
968 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
969 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
970 { WM_GETMINMAXINFO, sent|defwinproc },
971 { WM_ENTERSIZEMOVE, sent|defwinproc },
972 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
973 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
974 { WM_MOVE, sent|defwinproc },
975 { WM_EXITSIZEMOVE, sent|defwinproc },
978 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
979 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
980 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
981 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
982 { WM_GETMINMAXINFO, sent|defwinproc },
983 { WM_ENTERSIZEMOVE, sent|defwinproc },
984 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
985 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
986 { WM_GETMINMAXINFO, sent|defwinproc },
987 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
988 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
989 { WM_GETTEXT, sent|defwinproc },
990 { WM_ERASEBKGND, sent|defwinproc },
991 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
992 { WM_MOVE, sent|defwinproc },
993 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
994 { WM_EXITSIZEMOVE, sent|defwinproc },
997 /* Resizing child window with MoveWindow (32) */
998 static const struct message WmResizingChildWithMoveWindowSeq[] = {
999 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
1000 { WM_NCCALCSIZE, sent|wparam, 1 },
1001 { WM_ERASEBKGND, sent|parent|optional },
1002 { WM_ERASEBKGND, sent|optional },
1003 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE },
1004 { WM_MOVE, sent|defwinproc },
1005 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
1006 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1009 /* Clicking on inactive button */
1010 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
1011 { WM_NCHITTEST, sent },
1012 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
1013 { WM_MOUSEACTIVATE, sent },
1014 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
1015 { WM_SETCURSOR, sent },
1016 { WM_SETCURSOR, sent|parent|defwinproc },
1017 { WM_LBUTTONDOWN, posted },
1018 { WM_KILLFOCUS, posted|parent },
1019 { WM_SETFOCUS, posted },
1020 { WM_CTLCOLORBTN, posted|parent },
1021 { BM_SETSTATE, posted },
1022 { WM_CTLCOLORBTN, posted|parent },
1023 { WM_LBUTTONUP, posted },
1024 { BM_SETSTATE, posted },
1025 { WM_CTLCOLORBTN, posted|parent },
1026 { WM_COMMAND, posted|parent },
1029 /* Reparenting a button (16/32) */
1030 /* The last child (button) reparented gets topmost for its new parent. */
1031 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
1032 { WM_SHOWWINDOW, sent|wparam, 0 },
1033 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE },
1034 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1035 { WM_ERASEBKGND, sent|parent },
1036 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE },
1037 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE },
1038 { WM_CHILDACTIVATE, sent },
1039 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW },
1040 { WM_MOVE, sent|defwinproc },
1041 { WM_SHOWWINDOW, sent|wparam, 1 },
1044 /* Creation of a custom dialog (32) */
1045 static const struct message WmCreateCustomDialogSeq[] = {
1046 { HCBT_CREATEWND, hook },
1047 { WM_GETMINMAXINFO, sent },
1048 { WM_NCCREATE, sent },
1049 { WM_NCCALCSIZE, sent|wparam, 0 },
1050 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1051 { WM_CREATE, sent },
1052 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1053 { WM_SHOWWINDOW, sent|wparam, 1 },
1054 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1055 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1056 { HCBT_ACTIVATE, hook },
1057 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1060 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1062 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
1064 { WM_NCACTIVATE, sent|wparam, 1 },
1065 { WM_GETTEXT, sent|optional|defwinproc },
1066 { WM_GETTEXT, sent|optional|defwinproc },
1067 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
1068 { WM_ACTIVATE, sent|wparam, 1 },
1069 { WM_KILLFOCUS, sent|parent },
1070 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
1071 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1072 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
1073 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1074 { WM_SETFOCUS, sent },
1075 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
1076 { WM_NCPAINT, sent|wparam, 1 },
1077 { WM_GETTEXT, sent|optional|defwinproc },
1078 { WM_GETTEXT, sent|optional|defwinproc },
1079 { WM_ERASEBKGND, sent },
1080 { WM_CTLCOLORDLG, sent|defwinproc },
1081 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1082 { WM_GETTEXT, sent|optional },
1083 { WM_GETTEXT, sent|optional },
1084 { WM_NCCALCSIZE, sent|optional },
1085 { WM_NCPAINT, sent|optional },
1086 { WM_GETTEXT, sent|optional|defwinproc },
1087 { WM_GETTEXT, sent|optional|defwinproc },
1088 { WM_ERASEBKGND, sent|optional },
1089 { WM_CTLCOLORDLG, sent|optional|defwinproc },
1090 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1091 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1095 /* Calling EndDialog for a custom dialog (32) */
1096 static const struct message WmEndCustomDialogSeq[] = {
1097 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1098 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1099 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1100 { WM_GETTEXT, sent|optional },
1101 { HCBT_ACTIVATE, hook },
1102 { WM_NCACTIVATE, sent|wparam, 0 },
1103 { WM_GETTEXT, sent|optional|defwinproc },
1104 { WM_GETTEXT, sent|optional|defwinproc },
1105 { WM_ACTIVATE, sent|wparam, 0 },
1106 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1107 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1108 { HCBT_SETFOCUS, hook },
1109 { WM_KILLFOCUS, sent },
1110 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1111 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
1112 { WM_IME_NOTIFY, sent|wparam|optional, 1 },
1113 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1114 { WM_SETFOCUS, sent|parent|defwinproc },
1117 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1118 static const struct message WmShowCustomDialogSeq[] = {
1119 { WM_SHOWWINDOW, sent|wparam, 1 },
1120 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1121 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1122 { HCBT_ACTIVATE, hook },
1123 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1125 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1127 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
1128 { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
1129 { WM_NCACTIVATE, sent|wparam, 1 },
1130 { WM_ACTIVATE, sent|wparam, 1 },
1132 { WM_KILLFOCUS, sent|parent },
1133 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
1134 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1135 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
1136 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1137 { WM_SETFOCUS, sent },
1138 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
1139 { WM_NCPAINT, sent|wparam, 1 },
1140 { WM_ERASEBKGND, sent },
1141 { WM_CTLCOLORDLG, sent|defwinproc },
1142 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1145 /* Creation and destruction of a modal dialog (32) */
1146 static const struct message WmModalDialogSeq[] = {
1147 { WM_CANCELMODE, sent|parent },
1148 { HCBT_SETFOCUS, hook },
1149 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1150 { WM_KILLFOCUS, sent|parent },
1151 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
1152 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1153 { WM_ENABLE, sent|parent|wparam, 0 },
1154 { HCBT_CREATEWND, hook },
1155 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1156 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1157 { WM_SETFONT, sent },
1158 { WM_INITDIALOG, sent },
1159 { WM_CHANGEUISTATE, sent|optional },
1160 { WM_UPDATEUISTATE, sent|optional },
1161 { WM_SHOWWINDOW, sent },
1162 { HCBT_ACTIVATE, hook },
1163 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1164 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1165 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
1166 { WM_NCACTIVATE, sent|wparam, 1 },
1167 { WM_GETTEXT, sent|optional },
1168 { WM_ACTIVATE, sent|wparam, 1 },
1169 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
1170 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1171 { WM_NCPAINT, sent },
1172 { WM_GETTEXT, sent|optional },
1173 { WM_ERASEBKGND, sent },
1174 { WM_CTLCOLORDLG, sent },
1175 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1176 { WM_GETTEXT, sent|optional },
1177 { WM_NCCALCSIZE, sent|optional },
1178 { WM_NCPAINT, sent|optional },
1179 { WM_GETTEXT, sent|optional },
1180 { WM_ERASEBKGND, sent|optional },
1181 { WM_CTLCOLORDLG, sent|optional },
1182 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1183 { WM_PAINT, sent|optional },
1184 { WM_CTLCOLORBTN, sent },
1185 { WM_ENTERIDLE, sent|parent|optional },
1186 { WM_ENTERIDLE, sent|parent|optional },
1187 { WM_ENTERIDLE, sent|parent|optional },
1188 { WM_ENTERIDLE, sent|parent|optional },
1189 { WM_ENTERIDLE, sent|parent|optional },
1190 { WM_ENTERIDLE, sent|parent|optional },
1191 { WM_ENTERIDLE, sent|parent|optional },
1192 { WM_ENTERIDLE, sent|parent|optional },
1193 { WM_ENTERIDLE, sent|parent|optional },
1194 { WM_ENTERIDLE, sent|parent|optional },
1195 { WM_ENTERIDLE, sent|parent|optional },
1196 { WM_ENTERIDLE, sent|parent|optional },
1197 { WM_ENTERIDLE, sent|parent|optional },
1198 { WM_ENTERIDLE, sent|parent|optional },
1199 { WM_ENTERIDLE, sent|parent|optional },
1200 { WM_ENTERIDLE, sent|parent|optional },
1201 { WM_ENTERIDLE, sent|parent|optional },
1202 { WM_ENTERIDLE, sent|parent|optional },
1203 { WM_ENTERIDLE, sent|parent|optional },
1204 { WM_ENTERIDLE, sent|parent|optional },
1206 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1207 { WM_ENABLE, sent|parent|wparam, 1 },
1208 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
1209 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1210 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1211 { WM_GETTEXT, sent|optional },
1212 { HCBT_ACTIVATE, hook },
1213 { WM_NCACTIVATE, sent|wparam, 0 },
1214 { WM_GETTEXT, sent|optional },
1215 { WM_ACTIVATE, sent|wparam, 0 },
1216 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1217 { WM_WINDOWPOSCHANGING, sent|optional },
1218 { HCBT_SETFOCUS, hook },
1219 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
1220 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1221 { WM_SETFOCUS, sent|parent|defwinproc },
1222 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
1223 { HCBT_DESTROYWND, hook },
1224 { 0x0090, sent|optional },
1225 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1226 { WM_DESTROY, sent },
1227 { WM_NCDESTROY, sent },
1230 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
1231 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
1232 /* (inside dialog proc, handling WM_INITDIALOG) */
1233 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
1234 { WM_NCCALCSIZE, sent },
1235 { WM_NCACTIVATE, sent|parent|wparam, 0 },
1236 { WM_GETTEXT, sent|defwinproc },
1237 { WM_ACTIVATE, sent|parent|wparam, 0 },
1238 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
1239 { WM_WINDOWPOSCHANGING, sent|parent },
1240 { WM_NCACTIVATE, sent|wparam, 1 },
1241 { WM_ACTIVATE, sent|wparam, 1 },
1242 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
1243 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
1244 /* (setting focus) */
1245 { WM_SHOWWINDOW, sent|wparam, 1 },
1246 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
1247 { WM_NCPAINT, sent },
1248 { WM_GETTEXT, sent|defwinproc },
1249 { WM_ERASEBKGND, sent },
1250 { WM_CTLCOLORDLG, sent|defwinproc },
1251 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
1253 /* (bunch of WM_CTLCOLOR* for each control) */
1254 { WM_PAINT, sent|parent },
1255 { WM_ENTERIDLE, sent|parent|wparam, 0 },
1256 { WM_SETCURSOR, sent|parent },
1259 /* SetMenu for NonVisible windows with size change*/
1260 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
1261 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1262 { WM_NCCALCSIZE, sent|wparam, 1 },
1263 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1264 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW },
1265 { WM_MOVE, sent|defwinproc },
1266 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
1267 { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */
1268 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1269 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1270 { WM_GETTEXT, sent|optional },
1271 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
1274 /* SetMenu for NonVisible windows with no size change */
1275 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
1276 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1277 { WM_NCCALCSIZE, sent|wparam, 1 },
1278 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1279 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1282 /* SetMenu for Visible windows with size change */
1283 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
1284 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1285 { WM_NCCALCSIZE, sent|wparam, 1 },
1286 { 0x0093, sent|defwinproc|optional },
1287 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1288 { WM_NCPAINT, sent }, /* wparam != 1 */
1289 { 0x0093, sent|defwinproc|optional },
1290 { 0x0093, sent|defwinproc|optional },
1291 { 0x0091, sent|defwinproc|optional },
1292 { 0x0092, sent|defwinproc|optional },
1293 { WM_GETTEXT, sent|defwinproc|optional },
1294 { WM_ERASEBKGND, sent|optional },
1295 { WM_ACTIVATE, sent|optional },
1296 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1297 { WM_MOVE, sent|defwinproc },
1298 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
1299 { 0x0093, sent|optional },
1300 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
1301 { 0x0093, sent|defwinproc|optional },
1302 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1303 { 0x0093, sent|defwinproc|optional },
1304 { 0x0093, sent|defwinproc|optional },
1305 { 0x0091, sent|defwinproc|optional },
1306 { 0x0092, sent|defwinproc|optional },
1307 { WM_ERASEBKGND, sent|optional },
1308 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1309 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1312 /* SetMenu for Visible windows with no size change */
1313 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
1314 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1315 { WM_NCCALCSIZE, sent|wparam, 1 },
1316 { WM_NCPAINT, sent }, /* wparam != 1 */
1317 { WM_GETTEXT, sent|defwinproc|optional },
1318 { WM_ERASEBKGND, sent|optional },
1319 { WM_ACTIVATE, sent|optional },
1320 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1321 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1324 /* DrawMenuBar for a visible window */
1325 static const struct message WmDrawMenuBarSeq[] =
1327 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1328 { WM_NCCALCSIZE, sent|wparam, 1 },
1329 { 0x0093, sent|defwinproc|optional },
1330 { WM_NCPAINT, sent }, /* wparam != 1 */
1331 { 0x0093, sent|defwinproc|optional },
1332 { 0x0093, sent|defwinproc|optional },
1333 { 0x0091, sent|defwinproc|optional },
1334 { 0x0092, sent|defwinproc|optional },
1335 { WM_GETTEXT, sent|defwinproc|optional },
1336 { WM_ERASEBKGND, sent|optional },
1337 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1338 { 0x0093, sent|optional },
1339 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1343 static const struct message WmSetRedrawFalseSeq[] =
1345 { WM_SETREDRAW, sent|wparam, 0 },
1349 static const struct message WmSetRedrawTrueSeq[] =
1351 { WM_SETREDRAW, sent|wparam, 1 },
1355 static const struct message WmEnableWindowSeq_1[] =
1357 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 },
1358 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1359 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 },
1363 static const struct message WmEnableWindowSeq_2[] =
1365 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1366 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 },
1370 static const struct message WmGetScrollRangeSeq[] =
1372 { SBM_GETRANGE, sent },
1375 static const struct message WmGetScrollInfoSeq[] =
1377 { SBM_GETSCROLLINFO, sent },
1380 static const struct message WmSetScrollRangeSeq[] =
1382 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1383 sends SBM_SETSCROLLINFO.
1385 { SBM_SETSCROLLINFO, sent },
1388 /* SetScrollRange for a window without a non-client area */
1389 static const struct message WmSetScrollRangeHSeq_empty[] =
1391 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 },
1394 static const struct message WmSetScrollRangeVSeq_empty[] =
1396 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 },
1399 static const struct message WmSetScrollRangeHVSeq[] =
1401 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE },
1402 { WM_NCCALCSIZE, sent|wparam, 1 },
1403 { WM_GETTEXT, sent|defwinproc|optional },
1404 { WM_ERASEBKGND, sent|optional },
1405 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1406 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1407 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1410 /* SetScrollRange for a window with a non-client area */
1411 static const struct message WmSetScrollRangeHV_NC_Seq[] =
1413 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE },
1414 { WM_NCCALCSIZE, sent|wparam, 1 },
1415 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1416 { WM_NCPAINT, sent|optional },
1417 { WM_STYLECHANGING, sent|defwinproc|optional },
1418 { WM_STYLECHANGED, sent|defwinproc|optional },
1419 { WM_STYLECHANGING, sent|defwinproc|optional },
1420 { WM_STYLECHANGED, sent|defwinproc|optional },
1421 { WM_STYLECHANGING, sent|defwinproc|optional },
1422 { WM_STYLECHANGED, sent|defwinproc|optional },
1423 { WM_STYLECHANGING, sent|defwinproc|optional },
1424 { WM_STYLECHANGED, sent|defwinproc|optional },
1425 { WM_GETTEXT, sent|defwinproc|optional },
1426 { WM_GETTEXT, sent|defwinproc|optional },
1427 { WM_ERASEBKGND, sent|optional },
1428 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
1429 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTMOVE },
1430 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
1431 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1432 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1433 { WM_GETTEXT, sent|optional },
1434 { WM_GETTEXT, sent|optional },
1435 { WM_GETTEXT, sent|optional },
1436 { WM_GETTEXT, sent|optional },
1439 /* test if we receive the right sequence of messages */
1440 /* after calling ShowWindow( SW_SHOWNA) */
1441 static const struct message WmSHOWNAChildInvisParInvis[] = {
1442 { WM_SHOWWINDOW, sent|wparam, 1 },
1445 static const struct message WmSHOWNAChildVisParInvis[] = {
1446 { WM_SHOWWINDOW, sent|wparam, 1 },
1449 static const struct message WmSHOWNAChildVisParVis[] = {
1450 { WM_SHOWWINDOW, sent|wparam, 1 },
1451 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
1454 static const struct message WmSHOWNAChildInvisParVis[] = {
1455 { WM_SHOWWINDOW, sent|wparam, 1 },
1456 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1457 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1458 { WM_ERASEBKGND, sent|optional },
1459 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOCLIENTMOVE },
1462 static const struct message WmSHOWNATopVisible[] = {
1463 { WM_SHOWWINDOW, sent|wparam, 1 },
1464 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
1467 static const struct message WmSHOWNATopInvisible[] = {
1468 { WM_SHOWWINDOW, sent|wparam, 1 },
1469 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1470 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1471 { WM_NCPAINT, sent|wparam, 1 },
1472 { WM_GETTEXT, sent|defwinproc|optional },
1473 { WM_ERASEBKGND, sent|optional },
1474 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1475 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
1476 { WM_NCPAINT, sent|wparam|optional, 1 },
1477 { WM_ERASEBKGND, sent|optional },
1478 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1479 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1484 static int after_end_dialog, test_def_id;
1485 static int sequence_cnt, sequence_size;
1486 static struct message* sequence;
1487 static int log_all_parent_messages;
1489 /* user32 functions */
1490 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
1491 static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG);
1492 static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD);
1493 static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*);
1494 static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK);
1495 /* kernel32 functions */
1496 static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
1498 static void init_procs(void)
1500 HMODULE user32 = GetModuleHandleA("user32.dll");
1501 HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
1503 #define GET_PROC(dll, func) \
1504 p ## func = (void*)GetProcAddress(dll, #func); \
1506 trace("GetProcAddress(%s) failed\n", #func); \
1509 GET_PROC(user32, GetAncestor)
1510 GET_PROC(user32, NotifyWinEvent)
1511 GET_PROC(user32, SetWinEventHook)
1512 GET_PROC(user32, TrackMouseEvent)
1513 GET_PROC(user32, UnhookWinEvent)
1515 GET_PROC(kernel32, GetCPInfoExA)
1520 static void add_message(const struct message *msg)
1525 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
1527 if (sequence_cnt == sequence_size)
1530 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
1534 sequence[sequence_cnt].message = msg->message;
1535 sequence[sequence_cnt].flags = msg->flags;
1536 sequence[sequence_cnt].wParam = msg->wParam;
1537 sequence[sequence_cnt].lParam = msg->lParam;
1542 /* try to make sure pending X events have been processed before continuing */
1543 static void flush_events(void)
1547 int min_timeout = 50;
1548 DWORD time = GetTickCount() + diff;
1552 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
1553 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
1554 diff = time - GetTickCount();
1559 static void flush_sequence(void)
1561 HeapFree(GetProcessHeap(), 0, sequence);
1563 sequence_cnt = sequence_size = 0;
1566 #define ok_sequence( exp, contx, todo) \
1567 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
1570 static void ok_sequence_(const struct message *expected, const char *context, int todo,
1571 const char *file, int line)
1573 static const struct message end_of_sequence = { 0, 0, 0, 0 };
1574 const struct message *actual;
1577 add_message(&end_of_sequence);
1581 while (expected->message && actual->message)
1583 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
1585 if (expected->message == actual->message)
1587 if (expected->flags & wparam)
1589 if (expected->wParam != actual->wParam && todo)
1593 ok_( file, line) (FALSE,
1594 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
1595 context, expected->message, expected->wParam, actual->wParam);
1599 ok_( file, line) (expected->wParam == actual->wParam,
1600 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
1601 context, expected->message, expected->wParam, actual->wParam);
1603 if (expected->flags & lparam)
1605 if (expected->lParam != actual->lParam && todo)
1609 ok_( file, line) (FALSE,
1610 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
1611 context, expected->message, expected->lParam, actual->lParam);
1615 ok_( file, line) (expected->lParam == actual->lParam,
1616 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
1617 context, expected->message, expected->lParam, actual->lParam);
1619 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo)
1623 ok_( file, line) (FALSE,
1624 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
1625 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
1629 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
1630 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
1631 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
1632 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
1633 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
1634 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
1635 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
1636 "%s: the msg 0x%04x should have been %s\n",
1637 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
1638 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
1639 "%s: the msg 0x%04x was expected in %s\n",
1640 context, expected->message, (expected->flags & parent) ? "parent" : "child");
1641 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook),
1642 "%s: the msg 0x%04x should have been sent by a hook\n",
1643 context, expected->message);
1644 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
1645 "%s: the msg 0x%04x should have been sent by a winevent hook\n",
1646 context, expected->message);
1650 /* silently drop winevent messages if there is no support for them */
1651 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))
1657 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1658 context, expected->message, actual->message);
1665 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1666 context, expected->message, actual->message);
1672 /* skip all optional trailing messages */
1673 while (expected->message && ((expected->flags & optional) ||
1674 ((expected->flags & winevent_hook) && !hEvent_hook)))
1680 if (expected->message || actual->message) {
1682 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1683 context, expected->message, actual->message);
1689 if (expected->message || actual->message)
1690 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1691 context, expected->message, actual->message);
1693 if( todo && !failcount) /* succeeded yet marked todo */
1695 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
1701 /******************************** MDI test **********************************/
1703 /* CreateWindow for MDI frame window, initially visible */
1704 static const struct message WmCreateMDIframeSeq[] = {
1705 { HCBT_CREATEWND, hook },
1706 { WM_GETMINMAXINFO, sent },
1707 { WM_NCCREATE, sent },
1708 { WM_NCCALCSIZE, sent|wparam, 0 },
1709 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1710 { WM_CREATE, sent },
1711 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1712 { WM_SHOWWINDOW, sent|wparam, 1 },
1713 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1714 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1715 { HCBT_ACTIVATE, hook },
1716 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1717 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1718 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* XP */
1719 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, /* Win9x doesn't send it */
1720 { WM_NCACTIVATE, sent|wparam, 1 },
1721 { WM_GETTEXT, sent|defwinproc|optional },
1722 { WM_ACTIVATE, sent|wparam, 1 },
1723 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x */
1724 { HCBT_SETFOCUS, hook },
1725 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1726 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
1727 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1728 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
1729 /* Win9x adds SWP_NOZORDER below */
1730 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1731 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
1732 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1733 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1737 /* DestroyWindow for MDI frame window, initially visible */
1738 static const struct message WmDestroyMDIframeSeq[] = {
1739 { HCBT_DESTROYWND, hook },
1740 { 0x0090, sent|optional },
1741 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1742 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1743 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
1744 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1745 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */
1746 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
1747 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
1748 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
1749 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1750 { WM_DESTROY, sent },
1751 { WM_NCDESTROY, sent },
1754 /* CreateWindow for MDI client window, initially visible */
1755 static const struct message WmCreateMDIclientSeq[] = {
1756 { HCBT_CREATEWND, hook },
1757 { WM_NCCREATE, sent },
1758 { WM_NCCALCSIZE, sent|wparam, 0 },
1759 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
1760 { WM_CREATE, sent },
1761 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
1762 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1763 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1765 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
1766 { WM_SHOWWINDOW, sent|wparam, 1 },
1767 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1768 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1769 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1772 /* ShowWindow(SW_SHOW) for MDI client window */
1773 static const struct message WmShowMDIclientSeq[] = {
1774 { WM_SHOWWINDOW, sent|wparam, 1 },
1775 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1776 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1777 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1780 /* ShowWindow(SW_HIDE) for MDI client window */
1781 static const struct message WmHideMDIclientSeq[] = {
1782 { WM_SHOWWINDOW, sent|wparam, 0 },
1783 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1784 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */
1785 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */
1786 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1789 /* DestroyWindow for MDI client window, initially visible */
1790 static const struct message WmDestroyMDIclientSeq[] = {
1791 { HCBT_DESTROYWND, hook },
1792 { 0x0090, sent|optional },
1793 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
1794 { WM_SHOWWINDOW, sent|wparam, 0 },
1795 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1796 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1797 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1798 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1799 { WM_DESTROY, sent },
1800 { WM_NCDESTROY, sent },
1803 /* CreateWindow for MDI child window, initially visible */
1804 static const struct message WmCreateMDIchildVisibleSeq[] = {
1805 { HCBT_CREATEWND, hook },
1806 { WM_NCCREATE, sent },
1807 { WM_NCCALCSIZE, sent|wparam, 0 },
1808 { WM_CREATE, sent },
1809 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1810 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1812 /* Win2k sends wparam set to
1813 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1814 * while Win9x doesn't bother to set child window id according to
1815 * CLIENTCREATESTRUCT.idFirstChild
1817 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1818 { WM_SHOWWINDOW, sent|wparam, 1 },
1819 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1820 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1821 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1822 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1823 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1824 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1825 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1827 /* Win9x: message sequence terminates here. */
1829 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1830 { HCBT_SETFOCUS, hook }, /* in MDI client */
1831 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1832 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
1833 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1834 { WM_SETFOCUS, sent }, /* in MDI client */
1835 { HCBT_SETFOCUS, hook },
1836 { WM_KILLFOCUS, sent }, /* in MDI client */
1837 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1838 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1839 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1840 { WM_SETFOCUS, sent|defwinproc },
1841 { WM_MDIACTIVATE, sent|defwinproc },
1844 /* CreateWindow for MDI child window with invisible parent */
1845 static const struct message WmCreateMDIchildInvisibleParentSeq[] = {
1846 { HCBT_CREATEWND, hook },
1847 { WM_GETMINMAXINFO, sent },
1848 { WM_NCCREATE, sent },
1849 { WM_NCCALCSIZE, sent|wparam, 0 },
1850 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
1851 { WM_CREATE, sent },
1852 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1853 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1855 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1856 { WM_SHOWWINDOW, sent|wparam, 1 },
1857 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
1858 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1859 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1860 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1862 /* Win9x: message sequence terminates here. */
1864 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1865 { HCBT_SETFOCUS, hook }, /* in MDI client */
1866 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1867 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
1868 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1869 { WM_SETFOCUS, sent }, /* in MDI client */
1870 { HCBT_SETFOCUS, hook },
1871 { WM_KILLFOCUS, sent }, /* in MDI client */
1872 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1873 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1874 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1875 { WM_SETFOCUS, sent|defwinproc },
1876 { WM_MDIACTIVATE, sent|defwinproc },
1879 /* DestroyWindow for MDI child window, initially visible */
1880 static const struct message WmDestroyMDIchildVisibleSeq[] = {
1881 { HCBT_DESTROYWND, hook },
1882 /* Win2k sends wparam set to
1883 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1884 * while Win9x doesn't bother to set child window id according to
1885 * CLIENTCREATESTRUCT.idFirstChild
1887 { 0x0090, sent|optional },
1888 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1889 { WM_SHOWWINDOW, sent|wparam, 0 },
1890 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1891 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1892 { WM_ERASEBKGND, sent|parent|optional },
1893 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1895 /* { WM_DESTROY, sent }
1896 * Win9x: message sequence terminates here.
1899 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1900 { WM_KILLFOCUS, sent },
1901 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1902 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1903 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1904 { WM_SETFOCUS, sent }, /* in MDI client */
1906 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1907 { WM_KILLFOCUS, sent }, /* in MDI client */
1908 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1909 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1910 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1911 { WM_SETFOCUS, sent }, /* in MDI client */
1913 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1915 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1916 { WM_KILLFOCUS, sent },
1917 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1918 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1919 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1920 { WM_SETFOCUS, sent }, /* in MDI client */
1922 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1923 { WM_KILLFOCUS, sent }, /* in MDI client */
1924 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1925 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1926 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1927 { WM_SETFOCUS, sent }, /* in MDI client */
1929 { WM_DESTROY, sent },
1931 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1932 { WM_KILLFOCUS, sent },
1933 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1934 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1935 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1936 { WM_SETFOCUS, sent }, /* in MDI client */
1938 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1939 { WM_KILLFOCUS, sent }, /* in MDI client */
1940 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1941 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1942 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1943 { WM_SETFOCUS, sent }, /* in MDI client */
1945 { WM_NCDESTROY, sent },
1948 /* CreateWindow for MDI child window, initially invisible */
1949 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1950 { HCBT_CREATEWND, hook },
1951 { WM_NCCREATE, sent },
1952 { WM_NCCALCSIZE, sent|wparam, 0 },
1953 { WM_CREATE, sent },
1954 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1955 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1957 /* Win2k sends wparam set to
1958 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1959 * while Win9x doesn't bother to set child window id according to
1960 * CLIENTCREATESTRUCT.idFirstChild
1962 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1965 /* DestroyWindow for MDI child window, initially invisible */
1966 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1967 { HCBT_DESTROYWND, hook },
1968 /* Win2k sends wparam set to
1969 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1970 * while Win9x doesn't bother to set child window id according to
1971 * CLIENTCREATESTRUCT.idFirstChild
1973 { 0x0090, sent|optional },
1974 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1975 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1976 { WM_DESTROY, sent },
1977 { WM_NCDESTROY, sent },
1978 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
1979 { WM_PARENTNOTIFY, sent|wparam|optional, WM_DESTROY }, /* MDI client */
1982 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1983 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1984 { HCBT_CREATEWND, hook },
1985 { WM_NCCREATE, sent },
1986 { WM_NCCALCSIZE, sent|wparam, 0 },
1987 { WM_CREATE, sent },
1988 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1989 { WM_SIZE, sent|wparam, SIZE_RESTORED },
1991 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1992 { WM_GETMINMAXINFO, sent },
1993 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1994 { WM_NCCALCSIZE, sent|wparam, 1 },
1995 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1996 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
1998 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1999 { WM_NCCALCSIZE, sent|wparam, 1 },
2000 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2001 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2002 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2003 /* Win2k sends wparam set to
2004 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2005 * while Win9x doesn't bother to set child window id according to
2006 * CLIENTCREATESTRUCT.idFirstChild
2008 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2009 { WM_SHOWWINDOW, sent|wparam, 1 },
2010 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2011 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2012 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2013 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
2014 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
2015 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2016 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2018 /* Win9x: message sequence terminates here. */
2020 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
2021 { HCBT_SETFOCUS, hook }, /* in MDI client */
2022 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2023 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
2024 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2025 { WM_SETFOCUS, sent }, /* in MDI client */
2026 { HCBT_SETFOCUS, hook },
2027 { WM_KILLFOCUS, sent }, /* in MDI client */
2028 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2029 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2030 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2031 { WM_SETFOCUS, sent|defwinproc },
2032 { WM_MDIACTIVATE, sent|defwinproc },
2034 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2035 { WM_NCCALCSIZE, sent|wparam, 1 },
2036 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2037 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2040 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
2041 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
2042 /* restore the 1st MDI child */
2043 { WM_SETREDRAW, sent|wparam, 0 },
2044 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL },
2045 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
2046 { WM_NCCALCSIZE, sent|wparam, 1 },
2047 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2048 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2049 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2051 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2052 { WM_NCCALCSIZE, sent|wparam, 1 },
2053 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2054 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2055 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2056 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
2057 /* create the 2nd MDI child */
2058 { HCBT_CREATEWND, hook },
2059 { WM_NCCREATE, sent },
2060 { WM_NCCALCSIZE, sent|wparam, 0 },
2061 { WM_CREATE, sent },
2062 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2063 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2065 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2066 { WM_GETMINMAXINFO, sent },
2067 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
2068 { WM_NCCALCSIZE, sent|wparam, 1 },
2069 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2070 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2071 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2073 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2074 { WM_NCCALCSIZE, sent|wparam, 1 },
2075 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2076 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2077 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2078 /* Win2k sends wparam set to
2079 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2080 * while Win9x doesn't bother to set child window id according to
2081 * CLIENTCREATESTRUCT.idFirstChild
2083 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2084 { WM_SHOWWINDOW, sent|wparam, 1 },
2085 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2086 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2087 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2088 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
2089 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
2090 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2092 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
2093 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
2095 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2097 /* Win9x: message sequence terminates here. */
2099 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
2100 { HCBT_SETFOCUS, hook },
2101 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
2102 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
2103 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2104 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2105 { WM_SETFOCUS, sent }, /* in MDI client */
2106 { HCBT_SETFOCUS, hook },
2107 { WM_KILLFOCUS, sent }, /* in MDI client */
2108 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2109 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2110 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2111 { WM_SETFOCUS, sent|defwinproc },
2113 { WM_MDIACTIVATE, sent|defwinproc },
2115 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2116 { WM_NCCALCSIZE, sent|wparam, 1 },
2117 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2118 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2121 /* WM_MDICREATE MDI child window, initially visible and maximized */
2122 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
2123 { WM_MDICREATE, sent },
2124 { HCBT_CREATEWND, hook },
2125 { WM_NCCREATE, sent },
2126 { WM_NCCALCSIZE, sent|wparam, 0 },
2127 { WM_CREATE, sent },
2128 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2129 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2131 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2132 { WM_GETMINMAXINFO, sent },
2133 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
2134 { WM_NCCALCSIZE, sent|wparam, 1 },
2135 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2136 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2139 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2140 { WM_NCCALCSIZE, sent|wparam, 1 },
2141 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2142 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2143 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2145 /* Win2k sends wparam set to
2146 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2147 * while Win9x doesn't bother to set child window id according to
2148 * CLIENTCREATESTRUCT.idFirstChild
2150 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2151 { WM_SHOWWINDOW, sent|wparam, 1 },
2152 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2154 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2156 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2157 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
2158 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
2160 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2161 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2163 /* Win9x: message sequence terminates here. */
2165 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
2166 { WM_SETFOCUS, sent|optional }, /* in MDI client */
2167 { HCBT_SETFOCUS, hook }, /* in MDI client */
2168 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2169 { WM_IME_NOTIFY, sent|wparam|optional, 2 },
2170 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
2171 { WM_SETFOCUS, sent|optional }, /* in MDI client */
2172 { HCBT_SETFOCUS, hook|optional },
2173 { WM_KILLFOCUS, sent }, /* in MDI client */
2174 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2175 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2176 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2177 { WM_SETFOCUS, sent|defwinproc },
2179 { WM_MDIACTIVATE, sent|defwinproc },
2182 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2183 { WM_NCCALCSIZE, sent|wparam, 1 },
2184 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2185 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
2188 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2189 { WM_NCCALCSIZE, sent|wparam, 1 },
2190 { 0x0093, sent|defwinproc|optional },
2191 { 0x0093, sent|defwinproc|optional },
2192 { 0x0093, sent|defwinproc|optional },
2193 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2194 { WM_MOVE, sent|defwinproc },
2195 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2198 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
2199 { WM_NCCALCSIZE, sent|wparam, 1 },
2200 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE },
2201 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2204 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
2205 { WM_NCCALCSIZE, sent|wparam, 1 },
2206 { 0x0093, sent|optional },
2207 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE },
2208 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2210 { 0x0093, sent|optional },
2211 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2212 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
2213 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */
2214 { 0x0093, sent|defwinproc|optional },
2215 { 0x0093, sent|defwinproc|optional },
2216 { 0x0093, sent|defwinproc|optional },
2217 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2218 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
2222 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
2223 static const struct message WmCreateMDIchildInvisibleMaxSeq4[] = {
2224 { HCBT_CREATEWND, hook },
2225 { WM_GETMINMAXINFO, sent },
2226 { WM_NCCREATE, sent },
2227 { WM_NCCALCSIZE, sent|wparam, 0 },
2228 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
2229 { WM_CREATE, sent },
2230 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2231 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2233 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2234 { WM_GETMINMAXINFO, sent },
2235 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
2236 { WM_GETMINMAXINFO, sent|defwinproc },
2237 { WM_NCCALCSIZE, sent|wparam, 1 },
2238 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|0x8000 },
2239 { WM_MOVE, sent|defwinproc },
2240 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2242 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2243 { WM_NCCALCSIZE, sent|wparam, 1 },
2244 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2245 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2246 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI child */
2247 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2248 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2249 /* Win2k sends wparam set to
2250 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2251 * while Win9x doesn't bother to set child window id according to
2252 * CLIENTCREATESTRUCT.idFirstChild
2254 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2257 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
2258 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
2259 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
2260 { HCBT_SYSCOMMAND, hook },
2261 { WM_CLOSE, sent|defwinproc },
2262 { WM_MDIDESTROY, sent }, /* in MDI client */
2264 /* bring the 1st MDI child to top */
2265 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
2266 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
2268 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2270 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
2271 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
2272 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
2274 /* maximize the 1st MDI child */
2275 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2276 { WM_GETMINMAXINFO, sent|defwinproc },
2277 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
2278 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
2279 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
2280 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2281 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2283 /* restore the 2nd MDI child */
2284 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
2285 { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA },
2286 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
2287 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
2289 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2291 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2292 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2294 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2296 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
2298 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2299 { WM_NCCALCSIZE, sent|wparam, 1 },
2300 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2301 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2302 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2304 /* bring the 1st MDI child to top */
2305 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2306 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
2307 { HCBT_SETFOCUS, hook },
2308 { WM_KILLFOCUS, sent|defwinproc },
2309 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
2310 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2311 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2312 { WM_SETFOCUS, sent }, /* in MDI client */
2313 { HCBT_SETFOCUS, hook },
2314 { WM_KILLFOCUS, sent }, /* in MDI client */
2315 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2316 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2317 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2318 { WM_SETFOCUS, sent|defwinproc },
2319 { WM_MDIACTIVATE, sent|defwinproc },
2320 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2322 /* apparently ShowWindow(SW_SHOW) on an MDI client */
2323 { WM_SHOWWINDOW, sent|wparam, 1 },
2324 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2325 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2326 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2327 { WM_MDIREFRESHMENU, sent },
2329 { HCBT_DESTROYWND, hook },
2330 /* Win2k sends wparam set to
2331 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2332 * while Win9x doesn't bother to set child window id according to
2333 * CLIENTCREATESTRUCT.idFirstChild
2335 { 0x0090, sent|defwinproc|optional },
2336 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
2337 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
2338 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2339 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2340 { WM_ERASEBKGND, sent|parent|optional },
2341 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2343 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
2344 { WM_DESTROY, sent|defwinproc },
2345 { WM_NCDESTROY, sent|defwinproc },
2348 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
2349 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
2350 { WM_MDIDESTROY, sent }, /* in MDI client */
2351 { WM_SHOWWINDOW, sent|wparam, 0 },
2352 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2353 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2354 { WM_ERASEBKGND, sent|parent|optional },
2355 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2357 { HCBT_SETFOCUS, hook },
2358 { WM_KILLFOCUS, sent },
2359 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2360 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2361 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2362 { WM_SETFOCUS, sent }, /* in MDI client */
2363 { HCBT_SETFOCUS, hook },
2364 { WM_KILLFOCUS, sent }, /* in MDI client */
2365 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2366 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2367 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2368 { WM_SETFOCUS, sent },
2371 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2372 { WM_NCCALCSIZE, sent|wparam, 1 },
2373 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2374 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2377 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2378 { WM_NCCALCSIZE, sent|wparam, 1 },
2379 { 0x0093, sent|defwinproc|optional },
2380 { 0x0093, sent|defwinproc|optional },
2381 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2382 { WM_MOVE, sent|defwinproc },
2383 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2386 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
2387 { WM_NCCALCSIZE, sent|wparam, 1 },
2388 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE },
2389 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2392 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
2393 { WM_NCCALCSIZE, sent|wparam, 1 },
2394 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
2395 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2398 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2399 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2400 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2401 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2404 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2405 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2406 { 0x0093, sent|defwinproc|optional },
2407 { 0x0093, sent|defwinproc|optional },
2408 { 0x0093, sent|defwinproc|optional },
2409 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2410 { WM_MOVE, sent|defwinproc },
2411 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2414 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
2415 { WM_NCCALCSIZE, sent|wparam, 1 },
2416 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE },
2417 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2420 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE },
2421 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2422 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
2423 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2424 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2425 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
2427 { 0x0093, sent|defwinproc|optional },
2428 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */
2429 { 0x0093, sent|defwinproc|optional },
2430 { 0x0093, sent|defwinproc|optional },
2431 { 0x0093, sent|defwinproc|optional },
2432 { 0x0093, sent|optional },
2434 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2435 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2436 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
2437 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2438 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
2441 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2442 { WM_NCCALCSIZE, sent|wparam, 1 },
2443 { 0x0093, sent|defwinproc|optional },
2444 { 0x0093, sent|defwinproc|optional },
2445 { 0x0093, sent|defwinproc|optional },
2446 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2447 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2448 { 0x0093, sent|optional },
2450 { WM_NCACTIVATE, sent|wparam, 0 },
2451 { WM_MDIACTIVATE, sent },
2453 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL },
2454 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
2455 { WM_NCCALCSIZE, sent|wparam, 1 },
2457 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2459 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2460 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOCLIENTMOVE|0x8000 },
2461 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2464 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2465 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2466 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2467 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2470 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2471 { WM_NCCALCSIZE, sent|wparam, 1 },
2472 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2473 { WM_MOVE, sent|defwinproc },
2474 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2477 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
2478 { WM_NCCALCSIZE, sent|wparam, 1 },
2479 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE },
2480 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2481 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2482 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
2483 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
2484 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2485 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
2487 { HCBT_SETFOCUS, hook },
2488 { WM_KILLFOCUS, sent },
2489 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2490 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2491 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2492 { WM_SETFOCUS, sent }, /* in MDI client */
2494 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
2496 { HCBT_DESTROYWND, hook },
2497 /* Win2k sends wparam set to
2498 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2499 * while Win9x doesn't bother to set child window id according to
2500 * CLIENTCREATESTRUCT.idFirstChild
2502 { 0x0090, sent|optional },
2503 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
2505 { WM_SHOWWINDOW, sent|wparam, 0 },
2506 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2507 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2508 { WM_ERASEBKGND, sent|parent|optional },
2509 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2511 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
2512 { WM_DESTROY, sent },
2513 { WM_NCDESTROY, sent },
2516 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
2517 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
2518 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2519 { WM_GETMINMAXINFO, sent },
2520 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
2521 { WM_NCCALCSIZE, sent|wparam, 1 },
2522 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2523 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2525 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2526 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
2527 { HCBT_SETFOCUS, hook },
2528 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2529 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2530 { WM_SETFOCUS, sent }, /* in MDI client */
2531 { HCBT_SETFOCUS, hook },
2532 { WM_KILLFOCUS, sent }, /* in MDI client */
2533 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2534 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2535 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2536 { WM_SETFOCUS, sent|defwinproc },
2537 { WM_MDIACTIVATE, sent|defwinproc },
2538 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2539 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2541 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2542 { WM_NCCALCSIZE, sent|wparam, 1 },
2543 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2544 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2545 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2548 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
2549 static const struct message WmMaximizeMDIchildInvisibleSeq2[] = {
2550 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2551 { WM_GETMINMAXINFO, sent },
2552 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
2553 { WM_GETMINMAXINFO, sent|defwinproc },
2554 { WM_NCCALCSIZE, sent|wparam, 1 },
2555 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2556 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2558 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2559 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
2560 { HCBT_SETFOCUS, hook },
2561 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2562 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2563 { WM_SETFOCUS, sent }, /* in MDI client */
2564 { HCBT_SETFOCUS, hook },
2565 { WM_KILLFOCUS, sent }, /* in MDI client */
2566 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2567 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2568 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2569 { WM_SETFOCUS, sent|defwinproc },
2570 { WM_MDIACTIVATE, sent|defwinproc },
2571 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2572 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2575 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
2576 static const struct message WmMaximizeMDIchildInvisibleParentSeq[] = {
2577 { WM_MDIMAXIMIZE, sent }, /* in MDI client */
2578 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2579 { WM_GETMINMAXINFO, sent },
2580 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
2581 { WM_GETMINMAXINFO, sent|defwinproc },
2582 { WM_NCCALCSIZE, sent|wparam, 1 },
2583 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP doesn't send it */
2584 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2585 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOREDRAW|0x8000 },
2586 { WM_MOVE, sent|defwinproc },
2587 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2589 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2590 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2591 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2592 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 },
2593 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
2594 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */
2596 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2597 { WM_NCCALCSIZE, sent|wparam, 1 },
2598 { 0x0093, sent|defwinproc|optional },
2599 { 0x0094, sent|defwinproc|optional },
2600 { 0x0094, sent|defwinproc|optional },
2601 { 0x0094, sent|defwinproc|optional },
2602 { 0x0094, sent|defwinproc|optional },
2603 { 0x0093, sent|defwinproc|optional },
2604 { 0x0093, sent|defwinproc|optional },
2605 { 0x0091, sent|defwinproc|optional },
2606 { 0x0092, sent|defwinproc|optional },
2607 { 0x0092, sent|defwinproc|optional },
2608 { 0x0092, sent|defwinproc|optional },
2609 { 0x0092, sent|defwinproc|optional },
2610 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2611 { WM_MOVE, sent|defwinproc },
2612 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2613 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame win2000 */
2615 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
2616 { WM_NCCALCSIZE, sent|wparam, 1 },
2617 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
2618 { WM_SIZE, sent|wparam, SIZE_RESTORED },
2620 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE },
2621 { WM_GETMINMAXINFO, sent|defwinproc },
2622 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
2623 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
2624 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2625 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child win2000 */
2626 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 },
2627 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
2628 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
2629 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */
2631 { 0x0093, sent|optional },
2632 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
2633 { 0x0093, sent|defwinproc|optional },
2634 { 0x0093, sent|defwinproc|optional },
2635 { 0x0093, sent|defwinproc|optional },
2636 { 0x0091, sent|defwinproc|optional },
2637 { 0x0092, sent|defwinproc|optional },
2638 { 0x0092, sent|defwinproc|optional },
2639 { 0x0092, sent|defwinproc|optional },
2640 { 0x0092, sent|defwinproc|optional },
2641 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */
2642 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */
2643 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
2646 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
2647 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
2648 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
2649 { WM_GETMINMAXINFO, sent },
2650 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
2651 { WM_NCCALCSIZE, sent|wparam, 1 },
2652 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2653 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2654 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
2656 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2657 { WM_NCCALCSIZE, sent|wparam, 1 },
2658 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2659 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2660 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2663 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
2664 static const struct message WmRestoreMDIchildVisibleSeq[] = {
2665 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE },
2666 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
2667 { WM_NCCALCSIZE, sent|wparam, 1 },
2668 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2669 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2670 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2672 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2673 { WM_NCCALCSIZE, sent|wparam, 1 },
2674 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2675 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2676 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2679 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
2680 static const struct message WmRestoreMDIchildVisibleSeq_2[] = {
2681 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE },
2682 { WM_QUERYOPEN, sent|wparam|lparam, 0, 0 },
2683 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
2684 { WM_NCCALCSIZE, sent|wparam, 1 },
2685 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2686 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_NOCLIENTSIZE|0x8000 },
2687 { WM_MOVE, sent|defwinproc },
2688 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2689 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2690 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2691 { HCBT_SETFOCUS, hook },
2692 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2693 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
2694 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2695 { WM_SETFOCUS, sent },
2698 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
2699 static const struct message WmMinimizeMDIchildVisibleSeq[] = {
2700 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
2701 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|0x8000 },
2702 { WM_NCCALCSIZE, sent|wparam, 1 },
2703 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOCLIENTSIZE|0x8000 },
2704 { WM_MOVE, sent|defwinproc },
2705 { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
2706 { WM_CHILDACTIVATE, sent|wparam|lparam|defwinproc, 0, 0 },
2707 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2708 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2709 /* FIXME: Wine creates an icon/title window while Windows doesn't */
2710 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, /* MDI client */
2713 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
2714 static const struct message WmRestoreMDIchildInisibleSeq[] = {
2715 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE },
2716 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
2717 { WM_NCCALCSIZE, sent|wparam, 1 },
2718 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2719 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
2720 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
2721 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
2723 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
2724 { WM_NCCALCSIZE, sent|wparam, 1 },
2725 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
2726 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2727 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2731 static HWND mdi_client;
2732 static WNDPROC old_mdi_client_proc;
2734 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2738 /* do not log painting messages */
2739 if (message != WM_PAINT &&
2740 message != WM_NCPAINT &&
2741 message != WM_SYNCPAINT &&
2742 message != WM_ERASEBKGND &&
2743 message != WM_NCPAINT &&
2744 message != WM_NCHITTEST &&
2745 message != WM_GETTEXT &&
2746 message != WM_MDIGETACTIVE &&
2747 message != WM_GETICON &&
2748 message != WM_DEVICECHANGE)
2750 trace("mdi client: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
2754 case WM_WINDOWPOSCHANGING:
2755 case WM_WINDOWPOSCHANGED:
2757 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2759 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2760 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2761 winpos->hwnd, winpos->hwndInsertAfter,
2762 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2763 dump_winpos_flags(winpos->flags);
2765 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2766 * in the high word for internal purposes
2768 wParam = winpos->flags & 0xffff;
2769 /* We are not interested in the flags that don't match under XP and Win9x */
2770 wParam &= ~(SWP_NOZORDER);
2775 msg.message = message;
2776 msg.flags = sent|wparam|lparam;
2777 msg.wParam = wParam;
2778 msg.lParam = lParam;
2782 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
2785 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2787 static long defwndproc_counter = 0;
2791 /* do not log painting messages */
2792 if (message != WM_PAINT &&
2793 message != WM_NCPAINT &&
2794 message != WM_SYNCPAINT &&
2795 message != WM_ERASEBKGND &&
2796 message != WM_NCPAINT &&
2797 message != WM_NCHITTEST &&
2798 message != WM_GETTEXT &&
2799 message != WM_GETICON &&
2800 message != WM_DEVICECHANGE)
2802 trace("mdi child: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
2806 case WM_WINDOWPOSCHANGING:
2807 case WM_WINDOWPOSCHANGED:
2809 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2811 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2812 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2813 winpos->hwnd, winpos->hwndInsertAfter,
2814 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2815 dump_winpos_flags(winpos->flags);
2817 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2818 * in the high word for internal purposes
2820 wParam = winpos->flags & 0xffff;
2821 /* We are not interested in the flags that don't match under XP and Win9x */
2822 wParam &= ~(SWP_NOZORDER);
2826 case WM_MDIACTIVATE:
2828 HWND active, client = GetParent(hwnd);
2830 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
2832 if (hwnd == (HWND)lParam) /* if we are being activated */
2833 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
2835 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
2840 msg.message = message;
2841 msg.flags = sent|wparam|lparam;
2842 if (defwndproc_counter) msg.flags |= defwinproc;
2843 msg.wParam = wParam;
2844 msg.lParam = lParam;
2848 defwndproc_counter++;
2849 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
2850 defwndproc_counter--;
2855 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2857 static long defwndproc_counter = 0;
2861 /* do not log painting messages */
2862 if (message != WM_PAINT &&
2863 message != WM_NCPAINT &&
2864 message != WM_SYNCPAINT &&
2865 message != WM_ERASEBKGND &&
2866 message != WM_NCPAINT &&
2867 message != WM_NCHITTEST &&
2868 message != WM_GETTEXT &&
2869 message != WM_GETICON &&
2870 message != WM_DEVICECHANGE)
2872 trace("mdi frame: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
2876 case WM_WINDOWPOSCHANGING:
2877 case WM_WINDOWPOSCHANGED:
2879 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2881 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2882 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2883 winpos->hwnd, winpos->hwndInsertAfter,
2884 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2885 dump_winpos_flags(winpos->flags);
2887 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2888 * in the high word for internal purposes
2890 wParam = winpos->flags & 0xffff;
2891 /* We are not interested in the flags that don't match under XP and Win9x */
2892 wParam &= ~(SWP_NOZORDER);
2897 msg.message = message;
2898 msg.flags = sent|wparam|lparam;
2899 if (defwndproc_counter) msg.flags |= defwinproc;
2900 msg.wParam = wParam;
2901 msg.lParam = lParam;
2905 defwndproc_counter++;
2906 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
2907 defwndproc_counter--;
2912 static BOOL mdi_RegisterWindowClasses(void)
2917 cls.lpfnWndProc = mdi_frame_wnd_proc;
2920 cls.hInstance = GetModuleHandleA(0);
2922 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
2923 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2924 cls.lpszMenuName = NULL;
2925 cls.lpszClassName = "MDI_frame_class";
2926 if (!RegisterClassA(&cls)) return FALSE;
2928 cls.lpfnWndProc = mdi_child_wnd_proc;
2929 cls.lpszClassName = "MDI_child_class";
2930 if (!RegisterClassA(&cls)) return FALSE;
2932 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
2933 old_mdi_client_proc = cls.lpfnWndProc;
2934 cls.hInstance = GetModuleHandleA(0);
2935 cls.lpfnWndProc = mdi_client_hook_proc;
2936 cls.lpszClassName = "MDI_client_class";
2937 if (!RegisterClassA(&cls)) assert(0);
2942 static void test_mdi_messages(void)
2944 MDICREATESTRUCTA mdi_cs;
2945 CLIENTCREATESTRUCT client_cs;
2946 HWND mdi_frame, mdi_child, mdi_child2, active_child;
2948 HMENU hMenu = CreateMenu();
2950 assert(mdi_RegisterWindowClasses());
2954 trace("creating MDI frame window\n");
2955 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
2956 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2957 WS_MAXIMIZEBOX | WS_VISIBLE,
2958 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2959 GetDesktopWindow(), hMenu,
2960 GetModuleHandleA(0), NULL);
2962 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", FALSE);
2964 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2965 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
2967 trace("creating MDI client window\n");
2968 client_cs.hWindowMenu = 0;
2969 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
2970 mdi_client = CreateWindowExA(0, "MDI_client_class",
2972 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
2974 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
2976 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
2978 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2979 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
2981 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2982 ok(!active_child, "wrong active MDI child %p\n", active_child);
2983 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2988 trace("creating invisible MDI child window\n");
2989 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2991 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2992 mdi_client, 0, GetModuleHandleA(0), NULL);
2996 ShowWindow(mdi_child, SW_SHOWNORMAL);
2997 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
2999 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3000 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
3002 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3003 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3005 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3006 ok(!active_child, "wrong active MDI child %p\n", active_child);
3007 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3009 ShowWindow(mdi_child, SW_HIDE);
3010 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
3013 ShowWindow(mdi_child, SW_SHOW);
3014 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
3016 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3017 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
3019 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3020 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3022 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3023 ok(!active_child, "wrong active MDI child %p\n", active_child);
3024 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3026 DestroyWindow(mdi_child);
3029 trace("creating visible MDI child window\n");
3030 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3031 WS_CHILD | WS_VISIBLE,
3032 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3033 mdi_client, 0, GetModuleHandleA(0), NULL);
3035 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE);
3037 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3038 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
3040 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3041 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
3043 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3044 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
3045 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3048 DestroyWindow(mdi_child);
3049 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
3051 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3052 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3054 /* Win2k: MDI client still returns a just destroyed child as active
3055 * Win9x: MDI client returns 0
3057 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3058 ok(active_child == mdi_child || /* win2k */
3059 !active_child, /* win9x */
3060 "wrong active MDI child %p\n", active_child);
3061 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3065 trace("creating invisible MDI child window\n");
3066 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3068 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3069 mdi_client, 0, GetModuleHandleA(0), NULL);
3071 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
3073 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
3074 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
3076 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3077 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3079 /* Win2k: MDI client still returns a just destroyed child as active
3080 * Win9x: MDI client returns mdi_child2
3082 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3083 ok(active_child == mdi_child || /* win2k */
3084 active_child == mdi_child2, /* win9x */
3085 "wrong active MDI child %p\n", active_child);
3086 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3089 ShowWindow(mdi_child2, SW_MAXIMIZE);
3090 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE);
3092 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3093 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
3095 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3096 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3097 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3100 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3101 ok(GetFocus() == mdi_child2 || /* win2k */
3102 GetFocus() == 0, /* win9x */
3103 "wrong focus window %p\n", GetFocus());
3108 ShowWindow(mdi_child2, SW_HIDE);
3109 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
3111 ShowWindow(mdi_child2, SW_RESTORE);
3112 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE);
3115 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3116 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
3118 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3119 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3120 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3126 ShowWindow(mdi_child2, SW_HIDE);
3127 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
3129 ShowWindow(mdi_child2, SW_SHOW);
3130 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
3132 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3133 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3135 ShowWindow(mdi_child2, SW_MAXIMIZE);
3136 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE);
3138 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3139 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3141 ShowWindow(mdi_child2, SW_RESTORE);
3142 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE);
3144 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3145 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3147 ShowWindow(mdi_child2, SW_MINIMIZE);
3148 ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", TRUE);
3150 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3151 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3153 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3154 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3155 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3158 ShowWindow(mdi_child2, SW_RESTORE);
3159 ok_sequence(WmRestoreMDIchildVisibleSeq_2, "ShowWindow(SW_RESTORE):minimized MDI child", TRUE);
3161 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3162 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
3164 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3165 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3166 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3172 ShowWindow(mdi_child2, SW_HIDE);
3173 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
3175 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3176 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3178 DestroyWindow(mdi_child2);
3179 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
3181 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3182 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3184 /* test for maximized MDI children */
3185 trace("creating maximized visible MDI child window 1\n");
3186 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3187 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
3188 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3189 mdi_client, 0, GetModuleHandleA(0), NULL);
3191 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
3192 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
3194 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3195 ok(GetFocus() == mdi_child || /* win2k */
3196 GetFocus() == 0, /* win9x */
3197 "wrong focus window %p\n", GetFocus());
3199 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3200 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
3201 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3204 trace("creating maximized visible MDI child window 2\n");
3205 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3206 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
3207 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3208 mdi_client, 0, GetModuleHandleA(0), NULL);
3210 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
3211 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
3212 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
3214 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3215 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
3217 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3218 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3219 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3222 trace("destroying maximized visible MDI child window 2\n");
3223 DestroyWindow(mdi_child2);
3224 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
3226 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
3228 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3229 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3231 /* Win2k: MDI client still returns a just destroyed child as active
3232 * Win9x: MDI client returns 0
3234 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3235 ok(active_child == mdi_child2 || /* win2k */
3236 !active_child, /* win9x */
3237 "wrong active MDI child %p\n", active_child);
3240 ShowWindow(mdi_child, SW_MAXIMIZE);
3241 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
3244 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3245 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
3247 trace("re-creating maximized visible MDI child window 2\n");
3248 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3249 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
3250 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3251 mdi_client, 0, GetModuleHandleA(0), NULL);
3253 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
3254 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
3255 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
3257 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3258 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
3260 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3261 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3262 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3265 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
3266 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
3267 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
3269 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
3270 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3271 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
3273 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3274 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
3275 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3278 DestroyWindow(mdi_child);
3279 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
3281 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3282 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3284 /* Win2k: MDI client still returns a just destroyed child as active
3285 * Win9x: MDI client returns 0
3287 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3288 ok(active_child == mdi_child || /* win2k */
3289 !active_child, /* win9x */
3290 "wrong active MDI child %p\n", active_child);
3293 trace("creating maximized invisible MDI child window\n");
3294 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3295 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME,
3296 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3297 mdi_client, 0, GetModuleHandleA(0), NULL);
3299 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", TRUE);
3300 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n");
3301 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n");
3302 ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n");
3304 /* Win2k: MDI client still returns a just destroyed child as active
3305 * Win9x: MDI client returns 0
3307 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3308 ok(active_child == mdi_child || /* win2k */
3309 !active_child, /* win9x */
3310 "wrong active MDI child %p\n", active_child);
3313 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
3314 ShowWindow(mdi_child2, SW_MAXIMIZE);
3315 ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE);
3316 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n");
3317 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3318 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
3320 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3321 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3322 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3325 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0);
3328 /* end of test for maximized MDI children */
3331 trace("creating maximized visible MDI child window 1(Switch test)\n");
3332 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3333 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
3334 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3335 mdi_client, 0, GetModuleHandleA(0), NULL);
3337 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE);
3338 ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n");
3340 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow());
3341 ok(GetFocus() == mdi_child || /* win2k */
3342 GetFocus() == 0, /* win9x */
3343 "wrong focus window %p(Switch test)\n", GetFocus());
3345 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3346 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child);
3347 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed);
3350 trace("creating maximized visible MDI child window 2(Switch test)\n");
3351 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3352 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
3353 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
3354 mdi_client, 0, GetModuleHandleA(0), NULL);
3356 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE);
3358 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n");
3359 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n");
3361 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow());
3362 ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus());
3364 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3365 ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child);
3366 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed);
3369 trace("Switch child window.\n");
3370 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child, 0);
3371 ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE);
3372 trace("end of test for switch maximized MDI children\n");
3374 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
3377 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0);
3382 /* end of test for switch maximized MDI children */
3384 mdi_cs.szClass = "MDI_child_Class";
3385 mdi_cs.szTitle = "MDI child";
3386 mdi_cs.hOwner = GetModuleHandleA(0);
3389 mdi_cs.cx = CW_USEDEFAULT;
3390 mdi_cs.cy = CW_USEDEFAULT;
3391 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
3393 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
3394 ok(mdi_child != 0, "MDI child creation failed\n");
3395 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
3397 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
3399 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3400 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
3402 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
3403 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3404 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
3406 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3407 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
3408 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3411 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
3412 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
3414 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
3415 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3416 ok(!active_child, "wrong active MDI child %p\n", active_child);
3421 DestroyWindow(mdi_client);
3422 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
3424 /* test maximization of MDI child with invisible parent */
3425 client_cs.hWindowMenu = 0;
3426 mdi_client = CreateWindow("MDI_client_class",
3428 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
3430 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
3431 ok_sequence(WmCreateMDIclientSeq, "Create MDI client window", FALSE);
3433 ShowWindow(mdi_client, SW_HIDE);
3434 ok_sequence(WmHideMDIclientSeq, "Hide MDI client window", FALSE);
3436 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3437 WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
3439 mdi_client, 0, GetModuleHandleA(0), NULL);
3440 ok_sequence(WmCreateMDIchildInvisibleParentSeq, "Create MDI child window with invisible parent", FALSE);
3442 SendMessage(mdi_client, WM_MDIMAXIMIZE, (WPARAM) mdi_child, 0);
3443 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq, "Maximize MDI child window with invisible parent", TRUE);
3444 zoomed = IsZoomed(mdi_child);
3445 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3447 ShowWindow(mdi_client, SW_SHOW);
3448 ok_sequence(WmShowMDIclientSeq, "Show MDI client window", FALSE);
3450 DestroyWindow(mdi_child);
3451 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible maximized MDI child window", TRUE);
3453 /* end of test for maximization of MDI child with invisible parent */
3455 DestroyWindow(mdi_client);
3456 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
3458 DestroyWindow(mdi_frame);
3459 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
3461 /************************* End of MDI test **********************************/
3463 static void test_WM_SETREDRAW(HWND hwnd)
3465 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
3469 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
3470 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
3472 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
3473 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
3476 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
3477 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
3479 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
3480 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
3482 /* restore original WS_VISIBLE state */
3483 SetWindowLongA(hwnd, GWL_STYLE, style);
3488 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3492 trace("dialog: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
3494 /* explicitly ignore WM_GETICON message */
3495 if (message == WM_GETICON) return 0;
3502 case WM_DEVICECHANGE:
3507 case WM_WINDOWPOSCHANGING:
3508 case WM_WINDOWPOSCHANGED:
3510 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
3512 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
3513 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
3514 winpos->hwnd, winpos->hwndInsertAfter,
3515 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
3516 dump_winpos_flags(winpos->flags);
3518 /* Log only documented flags, win2k uses 0x1000 and 0x2000
3519 * in the high word for internal purposes
3521 wParam = winpos->flags & 0xffff;
3522 /* We are not interested in the flags that don't match under XP and Win9x */
3523 wParam &= ~(SWP_NOZORDER);
3528 msg.message = message;
3529 msg.flags = sent|wparam|lparam;
3530 msg.wParam = wParam;
3531 msg.lParam = lParam;
3534 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
3535 if (message == WM_TIMER) EndDialog( hwnd, 0 );
3539 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
3541 DWORD style, exstyle;
3545 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
3546 style = GetWindowLongA(hwnd, GWL_STYLE);
3547 /* do not be confused by WS_DLGFRAME set */
3548 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
3550 if (clear) ok(style & clear, "style %08x should be set\n", clear);
3551 if (set) ok(!(style & set), "style %08x should not be set\n", set);
3553 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
3554 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError());
3555 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
3556 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
3558 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
3560 style = GetWindowLongA(hwnd, GWL_STYLE);
3561 if (set) ok(style & set, "style %08x should be set\n", set);
3562 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear);
3564 /* a subsequent call should do nothing */
3565 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
3566 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError());
3567 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
3571 trace("Ignore GetScrollRange error below if you are on Win9x\n");
3572 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax);
3573 ok( ret, "GetScrollRange(%d) error %d\n", ctl, GetLastError());
3574 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
3575 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
3576 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
3579 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
3581 DWORD style, exstyle;
3585 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
3586 style = GetWindowLongA(hwnd, GWL_STYLE);
3587 /* do not be confused by WS_DLGFRAME set */
3588 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
3590 if (clear) ok(style & clear, "style %08x should be set\n", clear);
3591 if (set) ok(!(style & set), "style %08x should not be set\n", set);
3593 si.cbSize = sizeof(si);
3594 si.fMask = SIF_RANGE;
3597 SetScrollInfo(hwnd, ctl, &si, TRUE);
3598 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
3599 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
3601 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
3603 style = GetWindowLongA(hwnd, GWL_STYLE);
3604 if (set) ok(style & set, "style %08x should be set\n", set);
3605 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear);
3607 /* a subsequent call should do nothing */
3608 SetScrollInfo(hwnd, ctl, &si, TRUE);
3609 if (style & WS_HSCROLL)
3610 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
3611 else if (style & WS_VSCROLL)
3612 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
3614 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
3616 si.fMask = SIF_PAGE;
3618 SetScrollInfo(hwnd, ctl, &si, FALSE);
3619 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
3623 SetScrollInfo(hwnd, ctl, &si, FALSE);
3624 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
3626 si.fMask = SIF_RANGE;
3627 si.nMin = 0xdeadbeef;
3628 si.nMax = 0xdeadbeef;
3629 ret = GetScrollInfo(hwnd, ctl, &si);
3630 ok( ret, "GetScrollInfo error %d\n", GetLastError());
3631 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
3632 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
3633 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
3636 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
3637 static void test_scroll_messages(HWND hwnd)
3645 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
3646 ok( ret, "GetScrollRange error %d\n", GetLastError());
3647 if (sequence->message != WmGetScrollRangeSeq[0].message)
3648 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
3649 /* values of min and max are undefined */
3652 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE);
3653 ok( ret, "SetScrollRange error %d\n", GetLastError());
3654 if (sequence->message != WmSetScrollRangeSeq[0].message)
3655 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
3660 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
3661 ok( ret, "GetScrollRange error %d\n", GetLastError());
3662 if (sequence->message != WmGetScrollRangeSeq[0].message)
3663 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
3664 /* values of min and max are undefined */
3667 si.cbSize = sizeof(si);
3668 si.fMask = SIF_RANGE;
3671 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
3672 if (sequence->message != WmSetScrollRangeSeq[0].message)
3673 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
3676 si.fMask = SIF_PAGE;
3678 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
3679 if (sequence->message != WmSetScrollRangeSeq[0].message)
3680 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
3685 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
3686 if (sequence->message != WmSetScrollRangeSeq[0].message)
3687 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
3690 si.fMask = SIF_RANGE;
3691 si.nMin = 0xdeadbeef;
3692 si.nMax = 0xdeadbeef;
3693 ret = GetScrollInfo(hwnd, SB_CTL, &si);
3694 ok( ret, "GetScrollInfo error %d\n", GetLastError());
3695 if (sequence->message != WmGetScrollInfoSeq[0].message)
3696 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
3697 /* values of min and max are undefined */
3700 /* set WS_HSCROLL */
3701 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
3702 /* clear WS_HSCROLL */
3703 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
3705 /* set WS_HSCROLL */
3706 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
3707 /* clear WS_HSCROLL */
3708 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
3710 /* set WS_VSCROLL */
3711 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
3712 /* clear WS_VSCROLL */
3713 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
3715 /* set WS_VSCROLL */
3716 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
3717 /* clear WS_VSCROLL */
3718 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
3721 static void test_showwindow(void)
3726 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3727 100, 100, 200, 200, 0, 0, 0, NULL);
3728 ok (hwnd != 0, "Failed to create overlapped window\n");
3729 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
3730 0, 0, 10, 10, hwnd, 0, 0, NULL);
3731 ok (hchild != 0, "Failed to create child\n");
3734 /* ShowWindow( SW_SHOWNA) for invisible top level window */
3735 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
3736 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
3737 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", TRUE);
3740 /* ShowWindow( SW_SHOWNA) for now visible top level window */
3741 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
3742 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
3743 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE);
3745 /* back to invisible */
3746 ShowWindow(hchild, SW_HIDE);
3747 ShowWindow(hwnd, SW_HIDE);
3749 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
3750 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
3751 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
3752 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE);
3754 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
3755 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
3757 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
3758 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
3759 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE);
3761 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
3762 ShowWindow( hwnd, SW_SHOW);
3764 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
3765 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
3766 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE);
3769 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
3770 ShowWindow( hchild, SW_HIDE);
3772 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
3773 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
3774 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE);
3778 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture());
3779 DestroyWindow(hchild);
3780 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
3782 DestroyWindow(hwnd);
3787 * 1. Create invisible maximized popup window.
3788 * 2. Move and resize it.
3789 * 3. Show it maximized.
3791 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
3792 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
3793 100, 100, 200, 200, 0, 0, 0, NULL);
3794 ok (hwnd != 0, "Failed to create popup window\n");
3795 ok(IsZoomed(hwnd), "window should be maximized\n");
3796 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
3799 GetWindowRect(hwnd, &rc);
3800 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
3801 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
3802 "Invalid maximized size before ShowWindow (%d,%d)-(%d,%d)\n",
3803 rc.left, rc.top, rc.right, rc.bottom);
3804 /* Reset window's size & position */
3805 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
3806 ok(IsZoomed(hwnd), "window should be maximized\n");
3809 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
3810 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
3811 ok(IsZoomed(hwnd), "window should be maximized\n");
3812 ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE);
3815 GetWindowRect(hwnd, &rc);
3816 ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
3817 rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
3818 "Invalid maximized size after ShowWindow (%d,%d)-(%d,%d)\n",
3819 rc.left, rc.top, rc.right, rc.bottom);
3820 DestroyWindow(hwnd);
3824 * 1. Create invisible maximized popup window.
3825 * 2. Show it maximized.
3827 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
3828 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
3829 100, 100, 200, 200, 0, 0, 0, NULL);
3830 ok (hwnd != 0, "Failed to create popup window\n");
3831 ok(IsZoomed(hwnd), "window should be maximized\n");
3832 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
3835 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
3836 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
3837 ok(IsZoomed(hwnd), "window should be maximized\n");
3838 ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE);
3840 DestroyWindow(hwnd);
3844 * 1. Create visible maximized popup window.
3846 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
3847 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
3848 100, 100, 200, 200, 0, 0, 0, NULL);
3849 ok (hwnd != 0, "Failed to create popup window\n");
3850 ok(IsZoomed(hwnd), "window should be maximized\n");
3851 ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
3853 DestroyWindow(hwnd);
3857 * 1. Create visible popup window.
3860 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
3861 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE,
3862 100, 100, 200, 200, 0, 0, 0, NULL);
3863 ok (hwnd != 0, "Failed to create popup window\n");
3864 ok(!IsZoomed(hwnd), "window should NOT be maximized\n");
3865 ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", FALSE);
3868 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
3869 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
3870 ok(IsZoomed(hwnd), "window should be maximized\n");
3871 ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
3873 DestroyWindow(hwnd);
3877 static void test_sys_menu(void)
3883 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
3884 100, 100, 200, 200, 0, 0, 0, NULL);
3885 ok (hwnd != 0, "Failed to create overlapped window\n");
3889 /* test existing window without CS_NOCLOSE style */
3890 hmenu = GetSystemMenu(hwnd, FALSE);
3891 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
3893 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3894 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3895 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
3897 EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
3898 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
3900 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3901 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3902 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state);
3904 EnableMenuItem(hmenu, SC_CLOSE, 0);
3905 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
3907 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3908 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3909 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
3911 /* test whether removing WS_SYSMENU destroys a system menu */
3912 SetWindowLongW(hwnd, GWL_STYLE, WS_POPUP);
3913 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED);
3915 hmenu = GetSystemMenu(hwnd, FALSE);
3916 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
3918 DestroyWindow(hwnd);
3920 /* test new window with CS_NOCLOSE style */
3921 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW,
3922 100, 100, 200, 200, 0, 0, 0, NULL);
3923 ok (hwnd != 0, "Failed to create overlapped window\n");
3925 hmenu = GetSystemMenu(hwnd, FALSE);
3926 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
3928 state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND);
3929 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state);
3931 DestroyWindow(hwnd);
3933 /* test new window without WS_SYSMENU style */
3934 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW & ~WS_SYSMENU,
3935 100, 100, 200, 200, 0, 0, 0, NULL);
3936 ok(hwnd != 0, "Failed to create overlapped window\n");
3938 hmenu = GetSystemMenu(hwnd, FALSE);
3939 ok(!hmenu, "GetSystemMenu error %d\n", GetLastError());
3941 DestroyWindow(hwnd);
3944 /* For shown WS_OVERLAPPEDWINDOW */
3945 static const struct message WmSetIcon_1[] = {
3946 { WM_SETICON, sent },
3947 { 0x00AE, sent|defwinproc|optional }, /* XP */
3948 { WM_GETTEXT, sent|defwinproc|optional },
3949 { WM_GETTEXT, sent|defwinproc|optional }, /* XP sends a duplicate */
3953 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
3954 static const struct message WmSetIcon_2[] = {
3955 { WM_SETICON, sent },
3959 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
3960 static const struct message WmInitEndSession[] = {
3962 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF },
3966 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
3967 static const struct message WmInitEndSession_2[] = {
3969 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 },
3973 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
3974 static const struct message WmInitEndSession_3[] = {
3976 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF },
3980 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
3981 static const struct message WmInitEndSession_4[] = {
3983 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 },
3987 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
3988 static const struct message WmInitEndSession_5[] = {
3990 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 1, ENDSESSION_LOGOFF },
3994 static void test_MsgWaitForMultipleObjects(HWND hwnd)
3999 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
4000 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
4002 PostMessageA(hwnd, WM_USER, 0, 0);
4004 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
4005 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
4007 ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
4008 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
4010 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
4011 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
4013 PostMessageA(hwnd, WM_USER, 0, 0);
4015 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
4016 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
4018 ok(PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n");
4019 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
4021 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
4022 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
4023 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
4025 PostMessageA(hwnd, WM_USER, 0, 0);
4027 /* new incoming message causes it to become signaled again */
4028 ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE);
4029 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
4031 ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
4032 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
4033 ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
4034 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
4037 /* test if we receive the right sequence of messages */
4038 static void test_messages(void)
4040 HWND hwnd, hparent, hchild;
4041 HWND hchild2, hbutton;
4048 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
4049 100, 100, 200, 200, 0, 0, 0, NULL);
4050 ok (hwnd != 0, "Failed to create overlapped window\n");
4051 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
4053 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
4054 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
4055 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
4057 /* test WM_SETREDRAW on a not visible top level window */
4058 test_WM_SETREDRAW(hwnd);
4060 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
4061 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
4062 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
4064 ok(GetActiveWindow() == hwnd, "window should be active\n");
4065 ok(GetFocus() == hwnd, "window should have input focus\n");
4066 ShowWindow(hwnd, SW_HIDE);
4067 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
4069 ShowWindow(hwnd, SW_SHOW);
4070 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
4072 ShowWindow(hwnd, SW_HIDE);
4073 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
4075 ShowWindow(hwnd, SW_SHOWMAXIMIZED);
4076 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE);
4078 ShowWindow(hwnd, SW_RESTORE);
4079 /* FIXME: add ok_sequence() here */
4082 ShowWindow(hwnd, SW_MINIMIZE);
4083 ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE);
4086 ShowWindow(hwnd, SW_RESTORE);
4087 /* FIXME: add ok_sequence() here */
4090 ShowWindow(hwnd, SW_SHOW);
4091 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
4093 ok(GetActiveWindow() == hwnd, "window should be active\n");
4094 ok(GetFocus() == hwnd, "window should have input focus\n");
4095 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
4096 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
4097 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
4098 ok(GetActiveWindow() == hwnd, "window should still be active\n");
4100 /* test WM_SETREDRAW on a visible top level window */
4101 ShowWindow(hwnd, SW_SHOW);
4102 test_WM_SETREDRAW(hwnd);
4104 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
4105 test_scroll_messages(hwnd);
4107 /* test resizing and moving */
4108 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOACTIVATE );
4109 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE );
4112 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE );
4113 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE );
4116 SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER );
4117 ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE );
4121 /* popups don't get WM_GETMINMAXINFO */
4122 SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP );
4123 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED);
4125 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOACTIVATE );
4126 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
4128 DestroyWindow(hwnd);
4129 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
4131 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4132 100, 100, 200, 200, 0, 0, 0, NULL);
4133 ok (hparent != 0, "Failed to create parent window\n");
4136 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
4137 0, 0, 10, 10, hparent, 0, 0, NULL);
4138 ok (hchild != 0, "Failed to create child window\n");
4139 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE);
4140 DestroyWindow(hchild);
4143 /* visible child window with a caption */
4144 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
4145 WS_CHILD | WS_VISIBLE | WS_CAPTION,
4146 0, 0, 10, 10, hparent, 0, 0, NULL);
4147 ok (hchild != 0, "Failed to create child window\n");
4148 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
4150 trace("testing scroll APIs on a visible child window %p\n", hchild);
4151 test_scroll_messages(hchild);
4153 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
4154 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
4156 DestroyWindow(hchild);
4159 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4160 0, 0, 10, 10, hparent, 0, 0, NULL);
4161 ok (hchild != 0, "Failed to create child window\n");
4162 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
4164 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
4165 100, 100, 50, 50, hparent, 0, 0, NULL);
4166 ok (hchild2 != 0, "Failed to create child2 window\n");
4169 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
4170 0, 100, 50, 50, hchild, 0, 0, NULL);
4171 ok (hbutton != 0, "Failed to create button window\n");
4173 /* test WM_SETREDRAW on a not visible child window */
4174 test_WM_SETREDRAW(hchild);
4176 ShowWindow(hchild, SW_SHOW);
4177 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
4179 /* check parent messages too */
4180 log_all_parent_messages++;
4181 ShowWindow(hchild, SW_HIDE);
4182 ok_sequence(WmHideChildSeq2, "ShowWindow(SW_HIDE):child", FALSE);
4183 log_all_parent_messages--;
4185 ShowWindow(hchild, SW_SHOW);
4186 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
4188 ShowWindow(hchild, SW_HIDE);
4189 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
4191 ShowWindow(hchild, SW_SHOW);
4192 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
4194 /* test WM_SETREDRAW on a visible child window */
4195 test_WM_SETREDRAW(hchild);
4197 log_all_parent_messages++;
4198 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
4199 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
4200 log_all_parent_messages--;
4202 ShowWindow(hchild, SW_HIDE);
4204 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
4205 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
4207 ShowWindow(hchild, SW_HIDE);
4209 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
4210 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
4212 /* DestroyWindow sequence below expects that a child has focus */
4216 DestroyWindow(hchild);
4217 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
4218 DestroyWindow(hchild2);
4219 DestroyWindow(hbutton);
4222 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
4223 0, 0, 100, 100, hparent, 0, 0, NULL);
4224 ok (hchild != 0, "Failed to create child popup window\n");
4225 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
4226 DestroyWindow(hchild);
4228 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
4230 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
4231 0, 0, 100, 100, hparent, 0, 0, NULL);
4232 ok (hchild != 0, "Failed to create popup window\n");
4233 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
4234 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4235 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
4237 ShowWindow(hchild, SW_SHOW);
4238 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
4240 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
4241 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
4243 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
4244 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", TRUE);
4245 DestroyWindow(hchild);
4247 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
4248 * changes nothing in message sequences.
4251 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
4252 0, 0, 100, 100, hparent, 0, 0, NULL);
4253 ok (hchild != 0, "Failed to create popup window\n");
4254 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
4255 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4256 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
4258 ShowWindow(hchild, SW_SHOW);
4259 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
4261 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
4262 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
4263 DestroyWindow(hchild);
4266 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
4267 0, 0, 100, 100, hparent, 0, 0, NULL);
4268 ok(hwnd != 0, "Failed to create custom dialog window\n");
4269 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
4272 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
4273 test_scroll_messages(hwnd);
4279 SendMessage(hwnd, WM_NULL, 0, 0);
4282 after_end_dialog = 1;
4283 EndDialog( hwnd, 0 );
4284 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
4286 DestroyWindow(hwnd);
4287 after_end_dialog = 0;
4290 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP,
4291 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
4292 ok(hwnd != 0, "Failed to create custom dialog window\n");
4294 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
4295 ShowWindow(hwnd, SW_SHOW);
4296 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
4297 DestroyWindow(hwnd);
4300 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
4301 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
4303 DestroyWindow(hparent);
4306 /* Message sequence for SetMenu */
4307 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
4308 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
4310 hmenu = CreateMenu();
4311 ok (hmenu != 0, "Failed to create menu\n");
4312 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
4313 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
4314 100, 100, 200, 200, 0, hmenu, 0, NULL);
4315 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
4316 ok (SetMenu(hwnd, 0), "SetMenu\n");
4317 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
4318 ok (SetMenu(hwnd, 0), "SetMenu\n");
4319 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
4320 ShowWindow(hwnd, SW_SHOW);
4321 UpdateWindow( hwnd );
4324 ok (SetMenu(hwnd, 0), "SetMenu\n");
4325 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE);
4326 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
4327 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE);
4329 UpdateWindow( hwnd );
4332 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
4334 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
4336 DestroyWindow(hwnd);
4339 /* Message sequence for EnableWindow */
4340 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4341 100, 100, 200, 200, 0, 0, 0, NULL);
4342 ok (hparent != 0, "Failed to create parent window\n");
4343 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
4344 0, 0, 10, 10, hparent, 0, 0, NULL);
4345 ok (hchild != 0, "Failed to create child window\n");
4351 EnableWindow(hparent, FALSE);
4352 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE);
4354 EnableWindow(hparent, TRUE);
4355 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(TRUE)", FALSE);
4360 test_MsgWaitForMultipleObjects(hparent);
4362 /* the following test causes an exception in user.exe under win9x */
4363 if (!PostMessageW( hparent, WM_USER, 0, 0 ))
4365 DestroyWindow(hparent);
4369 PostMessageW( hparent, WM_USER+1, 0, 0 );
4370 /* PeekMessage(NULL) fails, but still removes the message */
4371 SetLastError(0xdeadbeef);
4372 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
4373 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */
4374 GetLastError() == 0xdeadbeef, /* NT4 */
4375 "last error is %d\n", GetLastError() );
4376 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
4377 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
4379 DestroyWindow(hchild);
4380 DestroyWindow(hparent);
4383 /* Message sequences for WM_SETICON */
4384 trace("testing WM_SETICON\n");
4385 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
4386 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4388 ShowWindow(hwnd, SW_SHOW);
4392 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(0, IDI_APPLICATION));
4393 ok_sequence(WmSetIcon_1, "WM_SETICON for shown window with caption", FALSE);
4395 ShowWindow(hwnd, SW_HIDE);
4398 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(0, IDI_APPLICATION));
4399 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window with caption", FALSE);
4400 DestroyWindow(hwnd);
4403 hwnd = CreateWindowExA(0, "TestPopupClass", NULL, WS_POPUP,
4404 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4406 ShowWindow(hwnd, SW_SHOW);
4410 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(0, IDI_APPLICATION));
4411 ok_sequence(WmSetIcon_2, "WM_SETICON for shown window without caption", FALSE);
4413 ShowWindow(hwnd, SW_HIDE);
4416 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(0, IDI_APPLICATION));
4417 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window without caption", FALSE);
4420 res = SendMessage(hwnd, 0x3B, 0x8000000b, 0);
4421 ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE);
4423 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res);
4424 res = SendMessage(hwnd, 0x3B, 0x0000000b, 0);
4425 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE);
4427 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res);
4428 res = SendMessage(hwnd, 0x3B, 0x0000000f, 0);
4429 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE);
4431 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res);
4434 res = SendMessage(hwnd, 0x3B, 0x80000008, 0);
4435 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE);
4437 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res);
4438 res = SendMessage(hwnd, 0x3B, 0x00000008, 0);
4439 ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE);
4441 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res);
4443 res = SendMessage(hwnd, 0x3B, 0x80000004, 0);
4444 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE);
4446 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res);
4448 res = SendMessage(hwnd, 0x3B, 0x80000001, 0);
4449 ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE);
4451 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res);
4453 DestroyWindow(hwnd);
4457 static void invisible_parent_tests(void)
4459 HWND hparent, hchild;
4461 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
4462 100, 100, 200, 200, 0, 0, 0, NULL);
4463 ok (hparent != 0, "Failed to create parent window\n");
4466 /* test showing child with hidden parent */
4468 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4469 0, 0, 10, 10, hparent, 0, 0, NULL);
4470 ok (hchild != 0, "Failed to create child window\n");
4471 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
4473 ShowWindow( hchild, SW_MINIMIZE );
4474 ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
4475 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4476 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4481 ShowWindow( hchild, SW_MINIMIZE );
4482 ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
4484 DestroyWindow(hchild);
4485 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4486 0, 0, 10, 10, hparent, 0, 0, NULL);
4489 ShowWindow( hchild, SW_MAXIMIZE );
4490 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
4491 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4492 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4497 ShowWindow( hchild, SW_MAXIMIZE );
4498 ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
4500 DestroyWindow(hchild);
4501 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4502 0, 0, 10, 10, hparent, 0, 0, NULL);
4505 ShowWindow( hchild, SW_RESTORE );
4506 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE);
4507 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4508 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4510 DestroyWindow(hchild);
4511 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4512 0, 0, 10, 10, hparent, 0, 0, NULL);
4515 ShowWindow( hchild, SW_SHOWMINIMIZED );
4516 ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
4517 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4518 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4523 ShowWindow( hchild, SW_SHOWMINIMIZED );
4524 ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
4526 DestroyWindow(hchild);
4527 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4528 0, 0, 10, 10, hparent, 0, 0, NULL);
4531 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
4532 ShowWindow( hchild, SW_SHOWMAXIMIZED );
4533 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE);
4534 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4535 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4537 DestroyWindow(hchild);
4538 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4539 0, 0, 10, 10, hparent, 0, 0, NULL);
4542 ShowWindow( hchild, SW_SHOWMINNOACTIVE );
4543 ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
4544 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4545 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4550 ShowWindow( hchild, SW_SHOWMINNOACTIVE );
4551 ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
4553 DestroyWindow(hchild);
4554 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4555 0, 0, 10, 10, hparent, 0, 0, NULL);
4558 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
4559 ShowWindow( hchild, SW_FORCEMINIMIZE );
4560 ok_sequence(WmEmptySeq, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE);
4562 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
4564 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4566 DestroyWindow(hchild);
4567 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4568 0, 0, 10, 10, hparent, 0, 0, NULL);
4571 ShowWindow( hchild, SW_SHOWNA );
4572 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE);
4573 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4574 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4579 ShowWindow( hchild, SW_SHOWNA );
4580 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE);
4582 DestroyWindow(hchild);
4583 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4584 0, 0, 10, 10, hparent, 0, 0, NULL);
4587 ShowWindow( hchild, SW_SHOW );
4588 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOW) child with invisible parent", FALSE);
4589 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4590 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4595 ShowWindow( hchild, SW_SHOW );
4596 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW) child with invisible parent", FALSE);
4598 ShowWindow( hchild, SW_HIDE );
4599 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE);
4600 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
4601 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4603 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
4604 ok_sequence(WmShowChildInvisibleParentSeq_6, "SetWindowPos:show child with invisible parent", FALSE);
4605 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4606 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4608 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
4609 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE);
4610 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
4611 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
4613 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
4615 DestroyWindow(hchild);
4616 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE);
4618 DestroyWindow(hparent);
4622 /****************** button message test *************************/
4623 static const struct message WmSetFocusButtonSeq[] =
4625 { HCBT_SETFOCUS, hook },
4626 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
4627 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
4628 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4629 { WM_SETFOCUS, sent|wparam, 0 },
4630 { WM_CTLCOLORBTN, sent|defwinproc },
4633 static const struct message WmKillFocusButtonSeq[] =
4635 { HCBT_SETFOCUS, hook },
4636 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4637 { WM_KILLFOCUS, sent|wparam, 0 },
4638 { WM_CTLCOLORBTN, sent|defwinproc },
4639 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
4640 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 },
4643 static const struct message WmSetFocusStaticSeq[] =
4645 { HCBT_SETFOCUS, hook },
4646 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
4647 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
4648 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4649 { WM_SETFOCUS, sent|wparam, 0 },
4650 { WM_CTLCOLORSTATIC, sent|defwinproc },
4653 static const struct message WmKillFocusStaticSeq[] =
4655 { HCBT_SETFOCUS, hook },
4656 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4657 { WM_KILLFOCUS, sent|wparam, 0 },
4658 { WM_CTLCOLORSTATIC, sent|defwinproc },
4659 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
4660 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 },
4663 static const struct message WmLButtonDownSeq[] =
4665 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
4666 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
4667 { HCBT_SETFOCUS, hook },
4668 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
4669 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
4670 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4671 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
4672 { WM_CTLCOLORBTN, sent|defwinproc },
4673 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
4674 { WM_CTLCOLORBTN, sent|defwinproc },
4675 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4678 static const struct message WmLButtonUpSeq[] =
4680 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
4681 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
4682 { WM_CTLCOLORBTN, sent|defwinproc },
4683 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4684 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
4685 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
4688 static const struct message WmSetFontButtonSeq[] =
4690 { WM_SETFONT, sent },
4692 { WM_ERASEBKGND, sent|defwinproc|optional },
4693 { WM_CTLCOLORBTN, sent|defwinproc },
4697 static WNDPROC old_button_proc;
4699 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4701 static long defwndproc_counter = 0;
4705 trace("button: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
4707 /* explicitly ignore WM_GETICON message */
4708 if (message == WM_GETICON) return 0;
4710 msg.message = message;
4711 msg.flags = sent|wparam|lparam;
4712 if (defwndproc_counter) msg.flags |= defwinproc;
4713 msg.wParam = wParam;
4714 msg.lParam = lParam;
4717 if (message == BM_SETSTATE)
4718 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
4720 defwndproc_counter++;
4721 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
4722 defwndproc_counter--;
4727 static void subclass_button(void)
4731 if (!GetClassInfoA(0, "button", &cls)) assert(0);
4733 old_button_proc = cls.lpfnWndProc;
4735 cls.hInstance = GetModuleHandle(0);
4736 cls.lpfnWndProc = button_hook_proc;
4737 cls.lpszClassName = "my_button_class";
4738 UnregisterClass(cls.lpszClassName, cls.hInstance);
4739 if (!RegisterClassA(&cls)) assert(0);
4742 static void test_button_messages(void)
4748 const struct message *setfocus;
4749 const struct message *killfocus;
4751 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
4752 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
4753 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
4754 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
4755 { BS_CHECKBOX, DLGC_BUTTON,
4756 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
4757 { BS_AUTOCHECKBOX, DLGC_BUTTON,
4758 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
4759 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
4760 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
4761 { BS_3STATE, DLGC_BUTTON,
4762 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
4763 { BS_AUTO3STATE, DLGC_BUTTON,
4764 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
4765 { BS_GROUPBOX, DLGC_STATIC,
4766 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
4767 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
4768 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
4769 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
4770 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
4771 { BS_OWNERDRAW, DLGC_BUTTON,
4772 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
4781 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
4783 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
4784 0, 0, 50, 14, 0, 0, 0, NULL);
4785 ok(hwnd != 0, "Failed to create button window\n");
4787 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
4788 ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code);
4790 ShowWindow(hwnd, SW_SHOW);
4795 trace("button style %08x\n", button[i].style);
4797 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
4800 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
4802 DestroyWindow(hwnd);
4805 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
4806 0, 0, 50, 14, 0, 0, 0, NULL);
4807 ok(hwnd != 0, "Failed to create button window\n");
4813 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
4814 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
4816 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
4817 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONUP on a button", FALSE);
4820 zfont = (HFONT)GetStockObject(SYSTEM_FONT);
4821 SendMessageA(hwnd, WM_SETFONT, (WPARAM)zfont, TRUE);
4823 ok_sequence(WmSetFontButtonSeq, "WM_SETFONT on a button", FALSE);
4825 DestroyWindow(hwnd);
4828 /****************** static message test *************************/
4829 static const struct message WmSetFontStaticSeq[] =
4831 { WM_SETFONT, sent },
4832 { WM_PAINT, sent|defwinproc },
4833 { WM_ERASEBKGND, sent|defwinproc|optional },
4834 { WM_CTLCOLORSTATIC, sent|defwinproc },
4838 static WNDPROC old_static_proc;
4840 static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4842 static long defwndproc_counter = 0;
4846 trace("static: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
4848 /* explicitly ignore WM_GETICON message */
4849 if (message == WM_GETICON) return 0;
4851 msg.message = message;
4852 msg.flags = sent|wparam|lparam;
4853 if (defwndproc_counter) msg.flags |= defwinproc;
4854 msg.wParam = wParam;
4855 msg.lParam = lParam;
4859 defwndproc_counter++;
4860 ret = CallWindowProcA(old_static_proc, hwnd, message, wParam, lParam);
4861 defwndproc_counter--;
4866 static void subclass_static(void)
4870 if (!GetClassInfoA(0, "static", &cls)) assert(0);
4872 old_static_proc = cls.lpfnWndProc;
4874 cls.hInstance = GetModuleHandle(0);
4875 cls.lpfnWndProc = static_hook_proc;
4876 cls.lpszClassName = "my_static_class";
4877 UnregisterClass(cls.lpszClassName, cls.hInstance);
4878 if (!RegisterClassA(&cls)) assert(0);
4881 static void test_static_messages(void)
4883 /* FIXME: make as comprehensive as the button message test */
4888 const struct message *setfont;
4890 { SS_LEFT, DLGC_STATIC,
4891 WmSetFontStaticSeq }
4899 for (i = 0; i < sizeof(static_ctrl)/sizeof(static_ctrl[0]); i++)
4901 hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP,
4902 0, 0, 50, 14, 0, 0, 0, NULL);
4903 ok(hwnd != 0, "Failed to create static window\n");
4905 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
4906 ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code);
4908 ShowWindow(hwnd, SW_SHOW);
4913 trace("static style %08x\n", static_ctrl[i].style);
4914 SendMessage(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE);
4915 ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE);
4917 DestroyWindow(hwnd);
4921 /************* painting message test ********************/
4923 void dump_region(HRGN hrgn)
4926 RGNDATA *data = NULL;
4931 printf( "null region\n" );
4934 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
4935 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
4936 GetRegionData( hrgn, size, data );
4937 printf("%d rects:", data->rdh.nCount );
4938 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
4939 printf( " (%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom );
4941 HeapFree( GetProcessHeap(), 0, data );
4944 static void check_update_rgn( HWND hwnd, HRGN hrgn )
4948 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
4949 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
4951 ret = GetUpdateRgn( hwnd, update, FALSE );
4952 ok( ret != ERROR, "GetUpdateRgn failed\n" );
4953 if (ret == NULLREGION)
4955 ok( !hrgn, "Update region shouldn't be empty\n" );
4959 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
4961 ok( 0, "Regions are different\n" );
4962 if (winetest_debug > 0)
4964 printf( "Update region: " );
4965 dump_region( update );
4966 printf( "Wanted region: " );
4967 dump_region( hrgn );
4971 GetRgnBox( update, &r1 );
4972 GetUpdateRect( hwnd, &r2, FALSE );
4973 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
4974 "Rectangles are different: %d,%d-%d,%d / %d,%d-%d,%d\n",
4975 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
4977 DeleteObject( tmp );
4978 DeleteObject( update );
4981 static const struct message WmInvalidateRgn[] = {
4982 { WM_NCPAINT, sent },
4983 { WM_GETTEXT, sent|defwinproc|optional },
4987 static const struct message WmGetUpdateRect[] = {
4988 { WM_NCPAINT, sent },
4989 { WM_GETTEXT, sent|defwinproc|optional },
4994 static const struct message WmInvalidateFull[] = {
4995 { WM_NCPAINT, sent|wparam, 1 },
4996 { WM_GETTEXT, sent|defwinproc|optional },
5000 static const struct message WmInvalidateErase[] = {
5001 { WM_NCPAINT, sent|wparam, 1 },
5002 { WM_GETTEXT, sent|defwinproc|optional },
5003 { WM_ERASEBKGND, sent },
5007 static const struct message WmInvalidatePaint[] = {
5009 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
5010 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
5014 static const struct message WmInvalidateErasePaint[] = {
5016 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
5017 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
5018 { WM_ERASEBKGND, sent|beginpaint },
5022 static const struct message WmInvalidateErasePaint2[] = {
5024 { WM_NCPAINT, sent|beginpaint },
5025 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
5026 { WM_ERASEBKGND, sent|beginpaint },
5030 static const struct message WmErase[] = {
5031 { WM_ERASEBKGND, sent },
5035 static const struct message WmPaint[] = {
5040 static const struct message WmParentOnlyPaint[] = {
5041 { WM_PAINT, sent|parent },
5045 static const struct message WmInvalidateParent[] = {
5046 { WM_NCPAINT, sent|parent },
5047 { WM_GETTEXT, sent|defwinproc|parent|optional },
5048 { WM_ERASEBKGND, sent|parent },
5052 static const struct message WmInvalidateParentChild[] = {
5053 { WM_NCPAINT, sent|parent },
5054 { WM_GETTEXT, sent|defwinproc|parent|optional },
5055 { WM_ERASEBKGND, sent|parent },
5056 { WM_NCPAINT, sent },
5057 { WM_GETTEXT, sent|defwinproc|optional },
5058 { WM_ERASEBKGND, sent },
5062 static const struct message WmInvalidateParentChild2[] = {
5063 { WM_ERASEBKGND, sent|parent },
5064 { WM_NCPAINT, sent },
5065 { WM_GETTEXT, sent|defwinproc|optional },
5066 { WM_ERASEBKGND, sent },
5070 static const struct message WmParentPaint[] = {
5071 { WM_PAINT, sent|parent },
5076 static const struct message WmParentPaintNc[] = {
5077 { WM_PAINT, sent|parent },
5079 { WM_NCPAINT, sent|beginpaint },
5080 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
5081 { WM_ERASEBKGND, sent|beginpaint },
5085 static const struct message WmChildPaintNc[] = {
5087 { WM_NCPAINT, sent|beginpaint },
5088 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
5089 { WM_ERASEBKGND, sent|beginpaint },
5093 static const struct message WmParentErasePaint[] = {
5094 { WM_PAINT, sent|parent },
5095 { WM_NCPAINT, sent|parent|beginpaint },
5096 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
5097 { WM_ERASEBKGND, sent|parent|beginpaint },
5099 { WM_NCPAINT, sent|beginpaint },
5100 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
5101 { WM_ERASEBKGND, sent|beginpaint },
5105 static const struct message WmParentOnlyNcPaint[] = {
5106 { WM_PAINT, sent|parent },
5107 { WM_NCPAINT, sent|parent|beginpaint },
5108 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
5112 static const struct message WmSetParentStyle[] = {
5113 { WM_STYLECHANGING, sent|parent },
5114 { WM_STYLECHANGED, sent|parent },
5118 static void test_paint_messages(void)
5124 HWND hparent, hchild;
5125 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
5126 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
5127 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
5128 100, 100, 200, 200, 0, 0, 0, NULL);
5129 ok (hwnd != 0, "Failed to create overlapped window\n");
5131 ShowWindow( hwnd, SW_SHOW );
5132 UpdateWindow( hwnd );
5136 check_update_rgn( hwnd, 0 );
5137 SetRectRgn( hrgn, 10, 10, 20, 20 );
5138 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
5139 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
5140 check_update_rgn( hwnd, hrgn );
5141 SetRectRgn( hrgn2, 20, 20, 30, 30 );
5142 ret = RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
5143 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
5144 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
5145 check_update_rgn( hwnd, hrgn );
5146 /* validate everything */
5147 ret = RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
5148 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
5149 check_update_rgn( hwnd, 0 );
5151 /* test empty region */
5152 SetRectRgn( hrgn, 10, 10, 10, 15 );
5153 ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
5154 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
5155 check_update_rgn( hwnd, 0 );
5156 /* test empty rect */
5157 SetRect( &rect, 10, 10, 10, 15 );
5158 ret = RedrawWindow( hwnd, &rect, NULL, RDW_INVALIDATE );
5159 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
5160 check_update_rgn( hwnd, 0 );
5162 /* flush pending messages */
5166 GetClientRect( hwnd, &rect );
5167 SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top );
5168 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
5169 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
5171 trace("testing InvalidateRect(0, NULL, FALSE)\n");
5172 SetRectEmpty( &rect );
5173 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) should fail\n");
5174 check_update_rgn( hwnd, hrgn );
5175 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
5177 ok_sequence( WmPaint, "Paint", FALSE );
5178 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
5179 check_update_rgn( hwnd, 0 );
5181 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
5182 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
5184 trace("testing ValidateRect(0, NULL)\n");
5185 SetRectEmpty( &rect );
5186 ok(ValidateRect(0, &rect), "ValidateRect(0, &rc) should not fail\n");
5187 check_update_rgn( hwnd, hrgn );
5188 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
5190 ok_sequence( WmPaint, "Paint", FALSE );
5191 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
5192 check_update_rgn( hwnd, 0 );
5194 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
5195 SetLastError(0xdeadbeef);
5196 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n");
5197 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || GetLastError() == 0xdeadbeef,
5198 "wrong error code %d\n", GetLastError());
5199 check_update_rgn( hwnd, 0 );
5201 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
5203 trace("testing ValidateRgn(0, NULL)\n");
5204 SetLastError(0xdeadbeef);
5205 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n");
5206 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %d\n", GetLastError());
5207 check_update_rgn( hwnd, 0 );
5209 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
5211 /* now with frame */
5212 SetRectRgn( hrgn, -5, -5, 20, 20 );
5214 /* flush pending messages */
5217 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
5218 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
5220 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
5221 check_update_rgn( hwnd, hrgn );
5224 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
5225 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
5228 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
5229 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
5231 GetClientRect( hwnd, &rect );
5232 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
5233 check_update_rgn( hwnd, hrgn );
5236 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
5237 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
5240 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
5241 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
5242 check_update_rgn( hwnd, 0 );
5245 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
5246 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
5247 check_update_rgn( hwnd, 0 );
5250 SetRectRgn( hrgn, 0, 0, 100, 100 );
5251 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
5252 SetRectRgn( hrgn, 0, 0, 50, 100 );
5253 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
5254 SetRectRgn( hrgn, 50, 0, 100, 100 );
5255 check_update_rgn( hwnd, hrgn );
5256 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
5257 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
5258 check_update_rgn( hwnd, 0 );
5261 SetRectRgn( hrgn, 0, 0, 100, 100 );
5262 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
5263 SetRectRgn( hrgn, 0, 0, 100, 50 );
5264 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
5265 ok_sequence( WmErase, "Erase", FALSE );
5266 SetRectRgn( hrgn, 0, 50, 100, 100 );
5267 check_update_rgn( hwnd, hrgn );
5270 SetRectRgn( hrgn, 0, 0, 100, 100 );
5271 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
5272 SetRectRgn( hrgn, 0, 0, 50, 50 );
5273 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
5274 ok_sequence( WmPaint, "Paint", FALSE );
5277 SetRectRgn( hrgn, -4, -4, -2, -2 );
5278 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
5279 SetRectRgn( hrgn, -200, -200, -198, -198 );
5280 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
5281 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
5284 SetRectRgn( hrgn, -4, -4, -2, -2 );
5285 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
5286 SetRectRgn( hrgn, -4, -4, -3, -3 );
5287 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
5288 SetRectRgn( hrgn, 0, 0, 1, 1 );
5289 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
5290 ok_sequence( WmPaint, "Paint", FALSE );
5293 SetRectRgn( hrgn, -4, -4, -1, -1 );
5294 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
5295 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
5296 /* make sure no WM_PAINT was generated */
5298 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
5301 SetRectRgn( hrgn, -4, -4, -1, -1 );
5302 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
5303 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
5305 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
5307 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
5308 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
5309 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
5310 ret = GetUpdateRect( hwnd, &rect, FALSE );
5311 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
5312 /* this will send WM_NCPAINT and validate the non client area */
5313 ret = GetUpdateRect( hwnd, &rect, TRUE );
5314 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
5316 DispatchMessage( &msg );
5318 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
5320 DestroyWindow( hwnd );
5322 /* now test with a child window */
5324 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
5325 100, 100, 200, 200, 0, 0, 0, NULL);
5326 ok (hparent != 0, "Failed to create parent window\n");
5328 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
5329 10, 10, 100, 100, hparent, 0, 0, NULL);
5330 ok (hchild != 0, "Failed to create child window\n");
5332 ShowWindow( hparent, SW_SHOW );
5333 UpdateWindow( hparent );
5334 UpdateWindow( hchild );
5337 log_all_parent_messages++;
5339 SetRect( &rect, 0, 0, 50, 50 );
5340 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5341 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
5342 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
5344 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5346 MapWindowPoints( hchild, hparent, &pt, 1 );
5347 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
5348 check_update_rgn( hchild, hrgn );
5349 SetRectRgn( hrgn, 0, 0, 50, 50 );
5350 check_update_rgn( hparent, hrgn );
5351 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
5352 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
5353 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
5354 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
5357 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
5359 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
5360 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
5361 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
5362 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
5363 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
5365 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
5366 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
5367 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
5369 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
5371 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
5372 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
5373 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
5375 /* flush all paint messages */
5379 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
5380 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
5381 SetRectRgn( hrgn, 0, 0, 50, 50 );
5382 check_update_rgn( hparent, hrgn );
5383 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
5384 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
5385 SetRectRgn( hrgn, 0, 0, 50, 50 );
5386 check_update_rgn( hparent, hrgn );
5388 /* flush all paint messages */
5390 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
5393 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
5394 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5395 SetRectRgn( hrgn, 0, 0, 50, 50 );
5396 check_update_rgn( hparent, hrgn );
5397 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
5398 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
5399 SetRectRgn( hrgn2, 10, 10, 50, 50 );
5400 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
5401 check_update_rgn( hparent, hrgn );
5402 /* flush all paint messages */
5406 /* same as above but parent gets completely validated */
5407 SetRect( &rect, 20, 20, 30, 30 );
5408 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5409 SetRectRgn( hrgn, 20, 20, 30, 30 );
5410 check_update_rgn( hparent, hrgn );
5411 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
5412 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
5413 check_update_rgn( hparent, 0 ); /* no update region */
5415 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
5417 /* make sure RDW_VALIDATE on child doesn't have the same effect */
5419 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5420 SetRectRgn( hrgn, 20, 20, 30, 30 );
5421 check_update_rgn( hparent, hrgn );
5422 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
5423 SetRectRgn( hrgn, 20, 20, 30, 30 );
5424 check_update_rgn( hparent, hrgn );
5426 /* same as above but normal WM_PAINT doesn't validate parent */
5428 SetRect( &rect, 20, 20, 30, 30 );
5429 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5430 SetRectRgn( hrgn, 20, 20, 30, 30 );
5431 check_update_rgn( hparent, hrgn );
5432 /* no WM_PAINT in child while parent still pending */
5433 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5434 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
5435 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5436 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
5439 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5440 /* no WM_PAINT in child while parent still pending */
5441 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5442 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
5443 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
5444 /* now that parent is valid child should get WM_PAINT */
5445 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5446 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
5447 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5448 ok_sequence( WmEmptySeq, "No other message", FALSE );
5450 /* same thing with WS_CLIPCHILDREN in parent */
5452 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
5453 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
5454 /* changing style invalidates non client area, but we need to invalidate something else to see it */
5455 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
5456 ok_sequence( WmEmptySeq, "No message", FALSE );
5457 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
5458 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
5461 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
5462 SetRectRgn( hrgn, 20, 20, 30, 30 );
5463 check_update_rgn( hparent, hrgn );
5464 /* no WM_PAINT in child while parent still pending */
5465 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5466 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
5467 /* WM_PAINT in parent first */
5468 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
5469 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
5471 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
5473 SetRect( &rect, 0, 0, 30, 30 );
5474 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
5475 SetRectRgn( hrgn, 0, 0, 30, 30 );
5476 check_update_rgn( hparent, hrgn );
5478 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
5480 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
5482 SetRect( &rect, -10, 0, 30, 30 );
5483 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
5484 SetRect( &rect, 0, 0, 20, 20 );
5485 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
5486 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
5487 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
5489 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
5491 SetRect( &rect, -10, 0, 30, 30 );
5492 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
5493 SetRect( &rect, 0, 0, 100, 100 );
5494 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
5495 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
5496 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
5497 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
5498 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
5500 /* test RDW_INTERNALPAINT behavior */
5503 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
5505 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
5507 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
5509 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
5511 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
5513 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
5515 assert( GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN );
5516 UpdateWindow( hparent );
5519 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
5520 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5521 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
5522 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
5524 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
5526 UpdateWindow( hparent );
5529 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
5530 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5531 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
5532 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
5534 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
5536 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
5537 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
5538 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
5540 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
5542 assert( !(GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN) );
5543 UpdateWindow( hparent );
5546 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
5547 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5548 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
5549 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
5551 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
5553 UpdateWindow( hparent );
5556 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
5557 RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
5558 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
5559 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
5561 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
5563 log_all_parent_messages--;
5564 DestroyWindow( hparent );
5565 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
5567 DeleteObject( hrgn );
5568 DeleteObject( hrgn2 );
5577 static DWORD WINAPI thread_proc(void *param)
5580 struct wnd_event *wnd_event = (struct wnd_event *)param;
5582 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
5583 100, 100, 200, 200, 0, 0, 0, NULL);
5584 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
5586 SetEvent(wnd_event->event);
5588 while (GetMessage(&msg, 0, 0, 0))
5590 TranslateMessage(&msg);
5591 DispatchMessage(&msg);
5594 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
5599 static void test_interthread_messages(void)
5606 int len, expected_len;
5607 struct wnd_event wnd_event;
5610 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
5611 if (!wnd_event.event)
5613 trace("skipping interthread message test under win9x\n");
5617 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
5618 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
5620 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5622 CloseHandle(wnd_event.event);
5624 SetLastError(0xdeadbeef);
5625 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
5626 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef,
5627 "wrong error code %d\n", GetLastError());
5629 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
5630 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
5632 expected_len = lstrlenA("window caption text");
5633 memset(buf, 0, sizeof(buf));
5634 SetLastError(0xdeadbeef);
5635 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
5636 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len, expected_len);
5637 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
5639 msg.hwnd = wnd_event.hwnd;
5640 msg.message = WM_GETTEXT;
5641 msg.wParam = sizeof(buf);
5642 msg.lParam = (LPARAM)buf;
5643 memset(buf, 0, sizeof(buf));
5644 SetLastError(0xdeadbeef);
5645 len = DispatchMessageA(&msg);
5646 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
5647 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %d\n", len, GetLastError());
5649 /* the following test causes an exception in user.exe under win9x */
5650 msg.hwnd = wnd_event.hwnd;
5651 msg.message = WM_TIMER;
5653 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
5654 SetLastError(0xdeadbeef);
5655 len = DispatchMessageA(&msg);
5656 ok(!len && GetLastError() == 0xdeadbeef,
5657 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len, GetLastError());
5659 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
5660 ok( ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
5662 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5663 CloseHandle(hThread);
5665 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
5669 static const struct message WmVkN[] = {
5670 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
5671 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
5672 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
5673 { WM_CHAR, wparam|lparam, 'n', 1 },
5674 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
5675 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
5676 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
5677 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
5680 static const struct message WmShiftVkN[] = {
5681 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */
5682 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
5683 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
5684 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
5685 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
5686 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
5687 { WM_CHAR, wparam|lparam, 'N', 1 },
5688 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
5689 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
5690 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
5691 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
5692 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
5693 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
5694 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
5697 static const struct message WmCtrlVkN[] = {
5698 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */
5699 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
5700 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
5701 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
5702 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
5703 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
5704 { WM_CHAR, wparam|lparam, 0x000e, 1 },
5705 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
5706 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
5707 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
5708 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
5709 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
5710 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
5711 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
5714 static const struct message WmCtrlVkN_2[] = {
5715 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */
5716 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
5717 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
5718 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
5719 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
5720 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
5721 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
5722 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
5723 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
5724 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
5725 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
5726 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
5729 static const struct message WmAltVkN[] = {
5730 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
5731 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
5732 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
5733 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
5734 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
5735 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
5736 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
5737 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
5738 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
5739 { HCBT_SYSCOMMAND, hook },
5740 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
5741 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
5742 { 0x00AE, sent|defwinproc|optional }, /* XP */
5743 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */
5744 { WM_INITMENU, sent|defwinproc },
5745 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
5746 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
5747 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
5748 { WM_CAPTURECHANGED, sent|defwinproc },
5749 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
5750 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
5751 { WM_EXITMENULOOP, sent|defwinproc },
5752 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
5753 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
5754 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
5755 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
5756 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
5757 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
5758 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
5759 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
5762 static const struct message WmAltVkN_2[] = {
5763 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
5764 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
5765 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
5766 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
5767 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
5768 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
5769 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
5770 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
5771 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
5772 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
5773 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
5774 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
5777 static const struct message WmCtrlAltVkN[] = {
5778 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */
5779 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
5780 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
5781 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
5782 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
5783 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
5784 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
5785 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
5786 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
5787 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
5788 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
5789 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
5790 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
5791 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
5792 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
5793 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
5794 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
5795 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
5798 static const struct message WmCtrlShiftVkN[] = {
5799 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */
5800 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
5801 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
5802 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */
5803 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
5804 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
5805 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
5806 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
5807 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 },
5808 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
5809 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
5810 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
5811 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
5812 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
5813 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
5814 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
5815 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
5816 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
5819 static const struct message WmCtrlAltShiftVkN[] = {
5820 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */
5821 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
5822 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
5823 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
5824 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
5825 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
5826 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0x20000001 }, /* XP */
5827 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 },
5828 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 },
5829 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
5830 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
5831 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 },
5832 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
5833 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
5834 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
5835 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xe0000001 }, /* XP */
5836 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 },
5837 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 },
5838 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
5839 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
5840 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
5841 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
5842 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
5843 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
5846 static const struct message WmAltPressRelease[] = {
5847 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
5848 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
5849 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
5850 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
5851 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
5852 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
5853 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 },
5854 { HCBT_SYSCOMMAND, hook },
5855 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
5856 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
5857 { WM_INITMENU, sent|defwinproc },
5858 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
5859 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE) },
5860 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
5862 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x30000001 }, /* XP */
5864 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
5865 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
5866 { WM_CAPTURECHANGED, sent|defwinproc },
5867 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) },
5868 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
5869 { WM_EXITMENULOOP, sent|defwinproc },
5870 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
5871 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
5872 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
5875 static const struct message WmAltMouseButton[] = {
5876 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
5877 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
5878 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
5879 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
5880 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
5881 { WM_LBUTTONDOWN, wparam, MK_LBUTTON, 0 },
5882 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON, 0 },
5883 { WM_LBUTTONUP, wparam, 0, 0 },
5884 { WM_LBUTTONUP, sent|wparam, 0, 0 },
5885 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
5886 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
5887 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
5890 static const struct message WmF1Seq[] = {
5891 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 1 }, /* XP */
5892 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 },
5893 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 },
5894 { WM_KEYF1, wparam|lparam, 0, 0 },
5895 { WM_KEYF1, sent|wparam|lparam, 0, 0 },
5896 { WM_HELP, sent|defwinproc },
5897 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 0xc0000001 }, /* XP */
5898 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 },
5899 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 },
5902 static const struct message WmVkAppsSeq[] = {
5903 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 1 }, /* XP */
5904 { WM_KEYDOWN, wparam|lparam, VK_APPS, 1 },
5905 { WM_KEYDOWN, sent|wparam|lparam, VK_APPS, 0x00000001 },
5906 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 0xc0000001 }, /* XP */
5907 { WM_KEYUP, wparam|lparam, VK_APPS, 0xc0000001 },
5908 { WM_KEYUP, sent|wparam|lparam, VK_APPS, 0xc0000001 },
5909 { WM_CONTEXTMENU, lparam, /*hwnd*/0, (LPARAM)-1 },
5910 { WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, (LPARAM)-1 },
5914 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
5918 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
5920 struct message log_msg;
5922 trace("accel: %p, %04x, %08lx, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
5924 /* ignore some unwanted messages */
5925 if (msg.message == WM_MOUSEMOVE ||
5926 msg.message == WM_GETICON ||
5927 msg.message == WM_DEVICECHANGE)
5930 log_msg.message = msg.message;
5931 log_msg.flags = wparam|lparam;
5932 log_msg.wParam = msg.wParam;
5933 log_msg.lParam = msg.lParam;
5934 add_message(&log_msg);
5936 if (!hAccel || !TranslateAccelerator(hwnd, hAccel, &msg))
5938 TranslateMessage(&msg);
5939 DispatchMessage(&msg);
5944 static void test_accelerators(void)
5949 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5950 100, 100, 200, 200, 0, 0, 0, NULL);
5959 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
5961 state = GetKeyState(VK_SHIFT);
5962 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
5963 state = GetKeyState(VK_CAPITAL);
5964 ok(state == 0, "wrong CapsLock state %04x\n", state);
5966 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
5967 assert(hAccel != 0);
5969 pump_msg_loop(hwnd, 0);
5972 trace("testing VK_N press/release\n");
5974 keybd_event('N', 0, 0, 0);
5975 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
5976 pump_msg_loop(hwnd, hAccel);
5977 ok_sequence(WmVkN, "VK_N press/release", FALSE);
5979 trace("testing Shift+VK_N press/release\n");
5981 keybd_event(VK_SHIFT, 0, 0, 0);
5982 keybd_event('N', 0, 0, 0);
5983 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
5984 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
5985 pump_msg_loop(hwnd, hAccel);
5986 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
5988 trace("testing Ctrl+VK_N press/release\n");
5990 keybd_event(VK_CONTROL, 0, 0, 0);
5991 keybd_event('N', 0, 0, 0);
5992 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
5993 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
5994 pump_msg_loop(hwnd, hAccel);
5995 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
5997 trace("testing Alt+VK_N press/release\n");
5999 keybd_event(VK_MENU, 0, 0, 0);
6000 keybd_event('N', 0, 0, 0);
6001 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6002 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6003 pump_msg_loop(hwnd, hAccel);
6004 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
6006 trace("testing Ctrl+Alt+VK_N press/release 1\n");
6008 keybd_event(VK_CONTROL, 0, 0, 0);
6009 keybd_event(VK_MENU, 0, 0, 0);
6010 keybd_event('N', 0, 0, 0);
6011 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6012 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6013 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
6014 pump_msg_loop(hwnd, hAccel);
6015 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
6017 ret = DestroyAcceleratorTable(hAccel);
6018 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError());
6020 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
6021 assert(hAccel != 0);
6023 trace("testing VK_N press/release\n");
6025 keybd_event('N', 0, 0, 0);
6026 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6027 pump_msg_loop(hwnd, hAccel);
6028 ok_sequence(WmVkN, "VK_N press/release", FALSE);
6030 trace("testing Shift+VK_N press/release\n");
6032 keybd_event(VK_SHIFT, 0, 0, 0);
6033 keybd_event('N', 0, 0, 0);
6034 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6035 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
6036 pump_msg_loop(hwnd, hAccel);
6037 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
6039 trace("testing Ctrl+VK_N press/release 2\n");
6041 keybd_event(VK_CONTROL, 0, 0, 0);
6042 keybd_event('N', 0, 0, 0);
6043 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6044 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
6045 pump_msg_loop(hwnd, hAccel);
6046 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
6048 trace("testing Alt+VK_N press/release 2\n");
6050 keybd_event(VK_MENU, 0, 0, 0);
6051 keybd_event('N', 0, 0, 0);
6052 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6053 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6054 pump_msg_loop(hwnd, hAccel);
6055 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
6057 trace("testing Ctrl+Alt+VK_N press/release 2\n");
6059 keybd_event(VK_CONTROL, 0, 0, 0);
6060 keybd_event(VK_MENU, 0, 0, 0);
6061 keybd_event('N', 0, 0, 0);
6062 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6063 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6064 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
6065 pump_msg_loop(hwnd, hAccel);
6066 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
6068 trace("testing Ctrl+Shift+VK_N press/release\n");
6070 keybd_event(VK_CONTROL, 0, 0, 0);
6071 keybd_event(VK_SHIFT, 0, 0, 0);
6072 keybd_event('N', 0, 0, 0);
6073 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6074 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
6075 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
6076 pump_msg_loop(hwnd, hAccel);
6077 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE);
6079 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
6081 keybd_event(VK_CONTROL, 0, 0, 0);
6082 keybd_event(VK_MENU, 0, 0, 0);
6083 keybd_event(VK_SHIFT, 0, 0, 0);
6084 keybd_event('N', 0, 0, 0);
6085 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
6086 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
6087 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6088 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
6089 pump_msg_loop(hwnd, hAccel);
6090 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE);
6092 ret = DestroyAcceleratorTable(hAccel);
6093 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError());
6095 trace("testing Alt press/release\n");
6097 keybd_event(VK_MENU, 0, 0, 0);
6098 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6099 keybd_event(VK_MENU, 0, 0, 0);
6100 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6101 pump_msg_loop(hwnd, 0);
6102 /* this test doesn't pass in Wine for managed windows */
6103 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
6105 trace("testing Alt+MouseButton press/release\n");
6106 /* first, move mouse pointer inside of the window client area */
6107 GetClientRect(hwnd, &rc);
6108 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
6109 rc.left += (rc.right - rc.left)/2;
6110 rc.top += (rc.bottom - rc.top)/2;
6111 SetCursorPos(rc.left, rc.top);
6115 keybd_event(VK_MENU, 0, 0, 0);
6116 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
6117 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
6118 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
6119 pump_msg_loop(hwnd, 0);
6120 ok_sequence(WmAltMouseButton, "Alt+MouseButton press/release", FALSE);
6122 trace("testing VK_F1 press/release\n");
6123 keybd_event(VK_F1, 0, 0, 0);
6124 keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0);
6125 pump_msg_loop(hwnd, 0);
6126 ok_sequence(WmF1Seq, "F1 press/release", FALSE);
6128 trace("testing VK_APPS press/release\n");
6129 keybd_event(VK_APPS, 0, 0, 0);
6130 keybd_event(VK_APPS, 0, KEYEVENTF_KEYUP, 0);
6131 pump_msg_loop(hwnd, 0);
6132 ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE);
6134 DestroyWindow(hwnd);
6137 /************* window procedures ********************/
6139 static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message,
6140 WPARAM wParam, LPARAM lParam)
6142 static long defwndproc_counter = 0;
6143 static long beginpaint_counter = 0;
6147 trace("%p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
6149 /* explicitly ignore WM_GETICON message */
6150 if (message == WM_GETICON) return 0;
6156 LONG style = GetWindowLongA(hwnd, GWL_STYLE);
6157 ok((BOOL)wParam == !(style & WS_DISABLED),
6158 "wrong WS_DISABLED state: %ld != %d\n", wParam, !(style & WS_DISABLED));
6162 case WM_CAPTURECHANGED:
6163 if (test_DestroyWindow_flag)
6165 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
6166 if (style & WS_CHILD)
6167 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
6168 else if (style & WS_POPUP)
6169 lParam = WND_POPUP_ID;
6171 lParam = WND_PARENT_ID;
6179 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
6180 capture = GetCapture();
6183 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture);
6184 trace("current capture %p, releasing...\n", capture);
6191 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n");
6192 if (test_DestroyWindow_flag)
6194 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
6195 if (style & WS_CHILD)
6196 lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
6197 else if (style & WS_POPUP)
6198 lParam = WND_POPUP_ID;
6200 lParam = WND_PARENT_ID;
6204 /* test_accelerators() depends on this */
6211 case WM_DEVICECHANGE:
6214 case WM_WINDOWPOSCHANGING:
6215 case WM_WINDOWPOSCHANGED:
6217 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
6219 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
6220 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
6221 winpos->hwnd, winpos->hwndInsertAfter,
6222 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
6223 dump_winpos_flags(winpos->flags);
6225 /* Log only documented flags, win2k uses 0x1000 and 0x2000
6226 * in the high word for internal purposes
6228 wParam = winpos->flags & 0xffff;
6229 /* We are not interested in the flags that don't match under XP and Win9x */
6230 wParam &= ~(SWP_NOZORDER);
6235 msg.message = message;
6236 msg.flags = sent|wparam|lparam;
6237 if (defwndproc_counter) msg.flags |= defwinproc;
6238 if (beginpaint_counter) msg.flags |= beginpaint;
6239 msg.wParam = wParam;
6240 msg.lParam = lParam;
6243 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
6245 HWND parent = GetParent(hwnd);
6247 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
6249 GetClientRect(parent, &rc);
6250 trace("parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
6252 trace("ptReserved = (%d,%d)\n"
6253 "ptMaxSize = (%d,%d)\n"
6254 "ptMaxPosition = (%d,%d)\n"
6255 "ptMinTrackSize = (%d,%d)\n"
6256 "ptMaxTrackSize = (%d,%d)\n",
6257 minmax->ptReserved.x, minmax->ptReserved.y,
6258 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
6259 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
6260 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
6261 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
6263 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %d != %d\n",
6264 minmax->ptMaxSize.x, rc.right);
6265 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %d != %d\n",
6266 minmax->ptMaxSize.y, rc.bottom);
6269 if (message == WM_PAINT)
6272 beginpaint_counter++;
6273 BeginPaint( hwnd, &ps );
6274 beginpaint_counter--;
6275 EndPaint( hwnd, &ps );
6279 defwndproc_counter++;
6280 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam)
6281 : DefWindowProcA(hwnd, message, wParam, lParam);
6282 defwndproc_counter--;
6287 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6289 return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);
6292 static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6294 return MsgCheckProc (TRUE, hwnd, message, wParam, lParam);
6297 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6299 static long defwndproc_counter = 0;
6303 trace("popup: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
6305 /* explicitly ignore WM_GETICON message */
6306 if (message == WM_GETICON) return 0;
6308 msg.message = message;
6309 msg.flags = sent|wparam|lparam;
6310 if (defwndproc_counter) msg.flags |= defwinproc;
6311 msg.wParam = wParam;
6312 msg.lParam = lParam;
6315 if (message == WM_CREATE)
6317 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
6318 SetWindowLongA(hwnd, GWL_STYLE, style);
6321 defwndproc_counter++;
6322 ret = DefWindowProcA(hwnd, message, wParam, lParam);
6323 defwndproc_counter--;
6328 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6330 static long defwndproc_counter = 0;
6331 static long beginpaint_counter = 0;
6334 LPARAM logged_lParam;
6336 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
6338 /* explicitly ignore WM_GETICON message */
6339 if (message == WM_GETICON) return 0;
6341 logged_lParam=lParam;
6342 if (log_all_parent_messages ||
6343 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
6344 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
6345 message == WM_ENABLE || message == WM_ENTERIDLE ||
6346 message == WM_DRAWITEM ||
6347 message == WM_IME_SETCONTEXT)
6361 INT ret = GetClipBox((HDC)wParam, &rc);
6363 trace("WM_ERASEBKGND: GetClipBox()=%d, (%d,%d-%d,%d)\n",
6364 ret, rc.left, rc.top, rc.right, rc.bottom);
6368 case WM_WINDOWPOSCHANGING:
6369 case WM_WINDOWPOSCHANGED:
6371 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
6373 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
6374 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
6375 winpos->hwnd, winpos->hwndInsertAfter,
6376 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
6377 dump_winpos_flags(winpos->flags);
6379 /* Log only documented flags, win2k uses 0x1000 and 0x2000
6380 * in the high word for internal purposes
6382 wParam = winpos->flags & 0xffff;
6383 /* We are not interested in the flags that don't match under XP and Win9x */
6384 wParam &= ~(SWP_NOZORDER);
6390 /* encode DRAWITEMSTRUCT into an LPARAM */
6391 DRAW_ITEM_STRUCT di;
6392 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
6394 trace("WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x\n",
6395 dis->CtlType, dis->CtlID, dis->itemID, dis->itemAction, dis->itemState);
6397 di.u.item.type = dis->CtlType;
6398 di.u.item.ctl_id = dis->CtlID;
6399 di.u.item.item_id = dis->itemID;
6400 di.u.item.action = dis->itemAction;
6401 di.u.item.state = dis->itemState;
6403 logged_lParam = di.u.lp;
6408 msg.message = message;
6409 msg.flags = sent|parent|wparam|lparam;
6410 if (defwndproc_counter) msg.flags |= defwinproc;
6411 if (beginpaint_counter) msg.flags |= beginpaint;
6412 msg.wParam = wParam;
6413 msg.lParam = logged_lParam;
6417 if (message == WM_PAINT)
6420 beginpaint_counter++;
6421 BeginPaint( hwnd, &ps );
6422 beginpaint_counter--;
6423 EndPaint( hwnd, &ps );
6427 defwndproc_counter++;
6428 ret = DefWindowProcA(hwnd, message, wParam, lParam);
6429 defwndproc_counter--;
6434 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6436 static long defwndproc_counter = 0;
6440 trace("dialog: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
6442 /* explicitly ignore WM_GETICON message */
6443 if (message == WM_GETICON) return 0;
6447 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
6448 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
6449 if (after_end_dialog)
6450 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
6452 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
6457 case WM_WINDOWPOSCHANGING:
6458 case WM_WINDOWPOSCHANGED:
6460 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
6462 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
6463 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
6464 winpos->hwnd, winpos->hwndInsertAfter,
6465 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
6466 dump_winpos_flags(winpos->flags);
6468 /* Log only documented flags, win2k uses 0x1000 and 0x2000
6469 * in the high word for internal purposes
6471 wParam = winpos->flags & 0xffff;
6472 /* We are not interested in the flags that don't match under XP and Win9x */
6473 wParam &= ~(SWP_NOZORDER);
6478 msg.message = message;
6479 msg.flags = sent|wparam|lparam;
6480 if (defwndproc_counter) msg.flags |= defwinproc;
6481 msg.wParam = wParam;
6482 msg.lParam = lParam;
6485 defwndproc_counter++;
6486 ret = DefDlgProcA(hwnd, message, wParam, lParam);
6487 defwndproc_counter--;
6492 static void dump_winpos_flags(UINT flags)
6494 if (!winetest_debug) return;
6496 if (flags & SWP_SHOWWINDOW) printf("|SWP_SHOWWINDOW");
6497 if (flags & SWP_HIDEWINDOW) printf("|SWP_HIDEWINDOW");
6498 if (flags & SWP_NOACTIVATE) printf("|SWP_NOACTIVATE");
6499 if (flags & SWP_FRAMECHANGED) printf("|SWP_FRAMECHANGED");
6500 if (flags & SWP_NOCOPYBITS) printf("|SWP_NOCOPYBITS");
6501 if (flags & SWP_NOOWNERZORDER) printf("|SWP_NOOWNERZORDER");
6502 if (flags & SWP_NOSENDCHANGING) printf("|SWP_NOSENDCHANGING");
6503 if (flags & SWP_DEFERERASE) printf("|SWP_DEFERERASE");
6504 if (flags & SWP_ASYNCWINDOWPOS) printf("|SWP_ASYNCWINDOWPOS");
6505 if (flags & SWP_NOZORDER) printf("|SWP_NOZORDER");
6506 if (flags & SWP_NOREDRAW) printf("|SWP_NOREDRAW");
6507 if (flags & SWP_NOSIZE) printf("|SWP_NOSIZE");
6508 if (flags & SWP_NOMOVE) printf("|SWP_NOMOVE");
6509 if (flags & SWP_NOCLIENTSIZE) printf("|SWP_NOCLIENTSIZE");
6510 if (flags & SWP_NOCLIENTMOVE) printf("|SWP_NOCLIENTMOVE");
6512 #define DUMPED_FLAGS \
6518 SWP_FRAMECHANGED | \
6522 SWP_NOOWNERZORDER | \
6523 SWP_NOSENDCHANGING | \
6525 SWP_ASYNCWINDOWPOS | \
6526 SWP_NOCLIENTSIZE | \
6529 if(flags & ~DUMPED_FLAGS) printf("|0x%04x", flags & ~DUMPED_FLAGS);
6534 static LRESULT WINAPI ShowWindowProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6536 static long defwndproc_counter = 0;
6540 /* log only specific messages we are interested in */
6543 #if 0 /* probably log these as well */
6549 trace("WM_SHOWWINDOW %ld\n", wParam);
6552 trace("WM_SIZE %ld\n", wParam);
6557 case WM_GETMINMAXINFO:
6558 trace("WM_GETMINMAXINFO\n");
6561 case WM_WINDOWPOSCHANGING:
6562 case WM_WINDOWPOSCHANGED:
6564 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
6566 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
6567 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
6568 winpos->hwnd, winpos->hwndInsertAfter,
6569 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
6571 dump_winpos_flags(winpos->flags);
6573 /* Log only documented flags, win2k uses 0x1000 and 0x2000
6574 * in the high word for internal purposes
6576 wParam = winpos->flags & 0xffff;
6577 /* We are not interested in the flags that don't match under XP and Win9x */
6578 wParam &= ~(SWP_NOZORDER);
6582 default: /* ignore */
6583 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
6584 return DefWindowProcA(hwnd, message, wParam, lParam);
6587 msg.message = message;
6588 msg.flags = sent|wparam|lparam;
6589 if (defwndproc_counter) msg.flags |= defwinproc;
6590 msg.wParam = wParam;
6591 msg.lParam = lParam;
6594 defwndproc_counter++;
6595 ret = DefWindowProcA(hwnd, message, wParam, lParam);
6596 defwndproc_counter--;
6601 static BOOL RegisterWindowClasses(void)
6607 cls.lpfnWndProc = MsgCheckProcA;
6610 cls.hInstance = GetModuleHandleA(0);
6612 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
6613 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6614 cls.lpszMenuName = NULL;
6615 cls.lpszClassName = "TestWindowClass";
6616 if(!RegisterClassA(&cls)) return FALSE;
6618 cls.lpfnWndProc = ShowWindowProcA;
6619 cls.lpszClassName = "ShowWindowClass";
6620 if(!RegisterClassA(&cls)) return FALSE;
6622 cls.lpfnWndProc = PopupMsgCheckProcA;
6623 cls.lpszClassName = "TestPopupClass";
6624 if(!RegisterClassA(&cls)) return FALSE;
6626 cls.lpfnWndProc = ParentMsgCheckProcA;
6627 cls.lpszClassName = "TestParentClass";
6628 if(!RegisterClassA(&cls)) return FALSE;
6630 cls.lpfnWndProc = DefWindowProcA;
6631 cls.lpszClassName = "SimpleWindowClass";
6632 if(!RegisterClassA(&cls)) return FALSE;
6634 cls.style = CS_NOCLOSE;
6635 cls.lpszClassName = "NoCloseWindowClass";
6636 if(!RegisterClassA(&cls)) return FALSE;
6638 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
6640 cls.hInstance = GetModuleHandleA(0);
6641 cls.hbrBackground = 0;
6642 cls.lpfnWndProc = TestDlgProcA;
6643 cls.lpszClassName = "TestDialogClass";
6644 if(!RegisterClassA(&cls)) return FALSE;
6647 clsW.lpfnWndProc = MsgCheckProcW;
6648 clsW.cbClsExtra = 0;
6649 clsW.cbWndExtra = 0;
6650 clsW.hInstance = GetModuleHandleW(0);
6652 clsW.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
6653 clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
6654 clsW.lpszMenuName = NULL;
6655 clsW.lpszClassName = testWindowClassW;
6656 RegisterClassW(&clsW); /* ignore error, this fails on Win9x */
6661 static HHOOK hCBT_hook;
6662 static DWORD cbt_hook_thread_id;
6664 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
6666 static const char * const CBT_code_name[10] = {
6673 "HCBT_CLICKSKIPPED",
6677 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
6681 trace("CBT: %d (%s), %08lx, %08lx\n", nCode, code_name, wParam, lParam);
6683 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
6685 if (nCode == HCBT_CLICKSKIPPED)
6687 /* ignore this event, XP sends it a lot when switching focus between windows */
6688 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
6691 if (nCode == HCBT_SYSCOMMAND || nCode == HCBT_KEYSKIPPED)
6695 msg.message = nCode;
6696 msg.flags = hook|wparam|lparam;
6697 msg.wParam = wParam;
6698 msg.lParam = lParam;
6701 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
6704 if (nCode == HCBT_DESTROYWND)
6706 if (test_DestroyWindow_flag)
6708 DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE);
6709 if (style & WS_CHILD)
6710 lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID);
6711 else if (style & WS_POPUP)
6712 lParam = WND_POPUP_ID;
6714 lParam = WND_PARENT_ID;
6718 /* Log also SetFocus(0) calls */
6719 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
6721 if (GetClassNameA(hwnd, buf, sizeof(buf)))
6723 if (!lstrcmpiA(buf, "TestWindowClass") ||
6724 !lstrcmpiA(buf, "ShowWindowClass") ||
6725 !lstrcmpiA(buf, "TestParentClass") ||
6726 !lstrcmpiA(buf, "TestPopupClass") ||
6727 !lstrcmpiA(buf, "SimpleWindowClass") ||
6728 !lstrcmpiA(buf, "TestDialogClass") ||
6729 !lstrcmpiA(buf, "MDI_frame_class") ||
6730 !lstrcmpiA(buf, "MDI_client_class") ||
6731 !lstrcmpiA(buf, "MDI_child_class") ||
6732 !lstrcmpiA(buf, "my_button_class") ||
6733 !lstrcmpiA(buf, "my_edit_class") ||
6734 !lstrcmpiA(buf, "static") ||
6735 !lstrcmpiA(buf, "ListBox") ||
6736 !lstrcmpiA(buf, "MyDialogClass") ||
6737 !lstrcmpiA(buf, "#32770"))
6741 msg.message = nCode;
6742 msg.flags = hook|wparam|lparam;
6743 msg.wParam = wParam;
6744 msg.lParam = lParam;
6748 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
6751 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
6761 trace("WEH:%p,event %08x,hwnd %p,obj %08x,id %08x,thread %08x,time %08x\n",
6762 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
6764 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
6766 /* ignore mouse cursor events */
6767 if (object_id == OBJID_CURSOR) return;
6769 if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf)))
6772 !lstrcmpiA(buf, "TestWindowClass") ||
6773 !lstrcmpiA(buf, "TestParentClass") ||
6774 !lstrcmpiA(buf, "TestPopupClass") ||
6775 !lstrcmpiA(buf, "SimpleWindowClass") ||
6776 !lstrcmpiA(buf, "TestDialogClass") ||
6777 !lstrcmpiA(buf, "MDI_frame_class") ||
6778 !lstrcmpiA(buf, "MDI_client_class") ||
6779 !lstrcmpiA(buf, "MDI_child_class") ||
6780 !lstrcmpiA(buf, "my_button_class") ||
6781 !lstrcmpiA(buf, "my_edit_class") ||
6782 !lstrcmpiA(buf, "static") ||
6783 !lstrcmpiA(buf, "ListBox") ||
6784 !lstrcmpiA(buf, "MyDialogClass") ||
6785 !lstrcmpiA(buf, "#32770"))
6789 msg.message = event;
6790 msg.flags = winevent_hook|wparam|lparam;
6791 msg.wParam = object_id;
6792 msg.lParam = child_id;
6798 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
6799 static const WCHAR wszAnsi[] = {'U',0};
6801 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
6805 case CB_FINDSTRINGEXACT:
6806 trace("String: %p\n", (LPCWSTR)lParam);
6807 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
6809 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
6813 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
6816 static const struct message WmGetTextLengthAfromW[] = {
6817 { WM_GETTEXTLENGTH, sent },
6818 { WM_GETTEXT, sent },
6822 static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0};
6824 /* dummy window proc for WM_GETTEXTLENGTH test */
6825 static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
6829 case WM_GETTEXTLENGTH:
6830 return lstrlenW(dummy_window_text) + 37; /* some random length */
6832 lstrcpynW( (LPWSTR)lp, dummy_window_text, wp );
6833 return lstrlenW( (LPWSTR)lp );
6835 return DefWindowProcW( hwnd, msg, wp, lp );
6839 static void test_message_conversion(void)
6841 static const WCHAR wszMsgConversionClass[] =
6842 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
6846 WNDPROC wndproc, newproc;
6850 cls.lpfnWndProc = MsgConversionProcW;
6853 cls.hInstance = GetModuleHandleW(NULL);
6855 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
6856 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
6857 cls.lpszMenuName = NULL;
6858 cls.lpszClassName = wszMsgConversionClass;
6859 /* this call will fail on Win9x, but that doesn't matter as this test is
6860 * meaningless on those platforms */
6861 if(!RegisterClassW(&cls)) return;
6863 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
6864 100, 100, 200, 200, 0, 0, 0, NULL);
6865 ok(hwnd != NULL, "Window creation failed\n");
6869 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
6870 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6871 ok(lRes == 0, "String should have been converted\n");
6872 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6873 ok(lRes == 1, "String shouldn't have been converted\n");
6877 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
6878 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6879 ok(lRes == 1, "String shouldn't have been converted\n");
6880 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6881 ok(lRes == 1, "String shouldn't have been converted\n");
6883 /* Synchronous messages */
6885 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6886 ok(lRes == 0, "String should have been converted\n");
6887 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6888 ok(lRes == 1, "String shouldn't have been converted\n");
6890 /* Asynchronous messages */
6893 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6894 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6895 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6897 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6898 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6899 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6901 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6902 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6903 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6905 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6906 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6907 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6909 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6910 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6911 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6913 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
6914 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6915 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6917 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
6918 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6919 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6921 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
6922 ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
6923 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError());
6925 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
6927 hwnd = CreateWindowW (testWindowClassW, wszUnicode,
6928 WS_OVERLAPPEDWINDOW,
6929 100, 100, 200, 200, 0, 0, 0, NULL);
6932 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0);
6933 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
6934 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
6935 "got bad length %ld\n", lRes );
6938 lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ),
6939 hwnd, WM_GETTEXTLENGTH, 0, 0);
6940 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
6941 ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
6942 "got bad length %ld\n", lRes );
6944 wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc );
6945 newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC );
6946 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
6947 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
6948 NULL, 0, NULL, NULL ),
6949 "got bad length %ld\n", lRes );
6951 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */
6952 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
6953 ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
6954 NULL, 0, NULL, NULL ),
6955 "got bad length %ld\n", lRes );
6957 ret = DestroyWindow(hwnd);
6958 ok( ret, "DestroyWindow() error %d\n", GetLastError());
6968 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime)
6972 #define TIMER_ID 0x19
6974 static DWORD WINAPI timer_thread_proc(LPVOID x)
6976 struct timer_info *info = x;
6979 r = KillTimer(info->hWnd, 0x19);
6980 ok(r,"KillTimer failed in thread\n");
6981 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
6982 ok(r,"SetTimer failed in thread\n");
6983 ok(r==TIMER_ID,"SetTimer id different\n");
6984 r = SetEvent(info->handles[0]);
6985 ok(r,"SetEvent failed in thread\n");
6989 static void test_timers(void)
6991 struct timer_info info;
6994 info.hWnd = CreateWindow ("TestWindowClass", NULL,
6995 WS_OVERLAPPEDWINDOW ,
6996 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
6999 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
7000 ok(info.id, "SetTimer failed\n");
7001 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
7002 info.handles[0] = CreateEvent(NULL,0,0,NULL);
7003 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
7005 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
7007 WaitForSingleObject(info.handles[1], INFINITE);
7009 CloseHandle(info.handles[0]);
7010 CloseHandle(info.handles[1]);
7012 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
7014 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
7017 static int count = 0;
7018 static VOID CALLBACK callback_count(
7028 static void test_timers_no_wnd(void)
7034 id = SetTimer(NULL, 0, 100, callback_count);
7035 ok(id != 0, "did not get id from SetTimer.\n");
7036 id2 = SetTimer(NULL, id, 200, callback_count);
7037 ok(id2 == id, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2, id);
7039 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
7040 ok(count == 0, "did not get zero count as expected (%i).\n", count);
7042 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
7043 ok(count == 1, "did not get one count as expected (%i).\n", count);
7044 KillTimer(NULL, id);
7046 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
7047 ok(count == 1, "killing replaced timer did not work (%i).\n", count);
7050 /* Various win events with arbitrary parameters */
7051 static const struct message WmWinEventsSeq[] = {
7052 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
7053 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
7054 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
7055 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
7056 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
7057 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
7058 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
7059 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
7060 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
7061 /* our win event hook ignores OBJID_CURSOR events */
7062 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
7063 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
7064 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
7065 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
7066 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
7067 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
7068 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
7069 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
7070 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
7071 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
7072 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
7073 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
7074 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
7075 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
7078 static const struct message WmWinEventCaretSeq[] = {
7079 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
7080 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
7081 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */
7082 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
7085 static const struct message WmWinEventCaretSeq_2[] = {
7086 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
7087 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
7088 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
7091 static const struct message WmWinEventAlertSeq[] = {
7092 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 },
7095 static const struct message WmWinEventAlertSeq_2[] = {
7096 /* create window in the thread proc */
7097 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 },
7098 /* our test event */
7099 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 },
7102 static const struct message WmGlobalHookSeq_1[] = {
7103 /* create window in the thread proc */
7104 { HCBT_CREATEWND, hook|lparam, 0, 2 },
7105 /* our test events */
7106 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 },
7107 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 },
7110 static const struct message WmGlobalHookSeq_2[] = {
7111 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */
7112 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */
7113 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */
7114 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */
7118 static const struct message WmMouseLLHookSeq[] = {
7119 { WM_MOUSEMOVE, hook },
7120 { WM_LBUTTONUP, hook },
7121 { WM_MOUSEMOVE, hook },
7125 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent,
7135 trace("WEH_2:%p,event %08x,hwnd %p,obj %08x,id %08x,thread %08x,time %08x\n",
7136 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
7138 if (GetClassNameA(hwnd, buf, sizeof(buf)))
7140 if (!lstrcmpiA(buf, "TestWindowClass") ||
7141 !lstrcmpiA(buf, "static"))
7145 msg.message = event;
7146 msg.flags = winevent_hook|wparam|lparam;
7147 msg.wParam = object_id;
7148 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2);
7154 static HHOOK hCBT_global_hook;
7155 static DWORD cbt_global_hook_thread_id;
7157 static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
7162 trace("CBT_2: %d, %08lx, %08lx\n", nCode, wParam, lParam);
7164 if (nCode == HCBT_SYSCOMMAND)
7168 msg.message = nCode;
7169 msg.flags = hook|wparam|lparam;
7170 msg.wParam = wParam;
7171 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
7174 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
7176 /* WH_MOUSE_LL hook */
7177 if (nCode == HC_ACTION)
7179 MSLLHOOKSTRUCT *mhll = (MSLLHOOKSTRUCT *)lParam;
7181 /* we can't test for real mouse events */
7182 if (mhll->flags & LLMHF_INJECTED)
7186 memset (&msg, 0, sizeof (msg));
7187 msg.message = wParam;
7191 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
7194 /* Log also SetFocus(0) calls */
7195 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
7197 if (GetClassNameA(hwnd, buf, sizeof(buf)))
7199 if (!lstrcmpiA(buf, "TestWindowClass") ||
7200 !lstrcmpiA(buf, "static"))
7204 msg.message = nCode;
7205 msg.flags = hook|wparam|lparam;
7206 msg.wParam = wParam;
7207 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
7211 return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
7214 static DWORD WINAPI win_event_global_thread_proc(void *param)
7218 HANDLE hevent = *(HANDLE *)param;
7220 assert(pNotifyWinEvent);
7222 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
7224 trace("created thread window %p\n", hwnd);
7226 *(HWND *)param = hwnd;
7229 /* this event should be received only by our new hook proc,
7230 * an old one does not expect an event from another thread.
7232 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0);
7235 while (GetMessage(&msg, 0, 0, 0))
7237 TranslateMessage(&msg);
7238 DispatchMessage(&msg);
7243 static DWORD WINAPI cbt_global_hook_thread_proc(void *param)
7247 HANDLE hevent = *(HANDLE *)param;
7250 /* these events should be received only by our new hook proc,
7251 * an old one does not expect an event from another thread.
7254 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
7256 trace("created thread window %p\n", hwnd);
7258 *(HWND *)param = hwnd;
7260 /* Windows doesn't like when a thread plays games with the focus,
7261 that leads to all kinds of misbehaviours and failures to activate
7262 a window. So, better keep next lines commented out.
7266 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
7267 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
7271 while (GetMessage(&msg, 0, 0, 0))
7273 TranslateMessage(&msg);
7274 DispatchMessage(&msg);
7279 static DWORD WINAPI mouse_ll_global_thread_proc(void *param)
7283 HANDLE hevent = *(HANDLE *)param;
7285 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
7287 trace("created thread window %p\n", hwnd);
7289 *(HWND *)param = hwnd;
7293 /* Windows doesn't like when a thread plays games with the focus,
7294 * that leads to all kinds of misbehaviours and failures to activate
7295 * a window. So, better don't generate a mouse click message below.
7297 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
7298 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
7299 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
7302 while (GetMessage(&msg, 0, 0, 0))
7304 TranslateMessage(&msg);
7305 DispatchMessage(&msg);
7310 static void test_winevents(void)
7316 HANDLE hthread, hevent;
7318 HWINEVENTHOOK hhook;
7319 const struct message *events = WmWinEventsSeq;
7321 hwnd = CreateWindowExA(0, "TestWindowClass", NULL,
7322 WS_OVERLAPPEDWINDOW,
7323 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
7327 /****** start of global hook test *************/
7328 hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0);
7329 if (!hCBT_global_hook)
7331 ok(DestroyWindow(hwnd), "failed to destroy window\n");
7332 skip( "cannot set global hook\n" );
7336 hevent = CreateEventA(NULL, 0, 0, NULL);
7338 hwnd2 = (HWND)hevent;
7340 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid);
7341 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
7343 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
7345 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
7348 /* this one should be received only by old hook proc */
7349 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
7350 /* this one should be received only by old hook proc */
7351 DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
7353 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
7355 ret = UnhookWindowsHookEx(hCBT_global_hook);
7356 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError());
7358 PostThreadMessageA(tid, WM_QUIT, 0, 0);
7359 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
7360 CloseHandle(hthread);
7361 CloseHandle(hevent);
7362 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
7363 /****** end of global hook test *************/
7365 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent)
7367 ok(DestroyWindow(hwnd), "failed to destroy window\n");
7375 /* this test doesn't pass under Win9x */
7376 /* win2k ignores events with hwnd == 0 */
7377 SetLastError(0xdeadbeef);
7378 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
7379 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
7380 GetLastError() == 0xdeadbeef, /* Win9x */
7381 "unexpected error %d\n", GetLastError());
7382 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
7385 for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
7386 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
7388 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
7390 /****** start of event filtering test *************/
7391 hhook = (HWINEVENTHOOK)pSetWinEventHook(
7392 EVENT_OBJECT_SHOW, /* 0x8002 */
7393 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */
7394 GetModuleHandleA(0), win_event_global_hook_proc,
7395 GetCurrentProcessId(), 0,
7396 WINEVENT_INCONTEXT);
7397 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError());
7399 hevent = CreateEventA(NULL, 0, 0, NULL);
7401 hwnd2 = (HWND)hevent;
7403 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
7404 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
7406 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
7408 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
7411 /* this one should be received only by old hook proc */
7412 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
7413 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
7414 /* this one should be received only by old hook proc */
7415 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
7417 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
7419 ret = pUnhookWinEvent(hhook);
7420 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
7422 PostThreadMessageA(tid, WM_QUIT, 0, 0);
7423 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
7424 CloseHandle(hthread);
7425 CloseHandle(hevent);
7426 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
7427 /****** end of event filtering test *************/
7429 /****** start of out of context event test *************/
7430 hhook = (HWINEVENTHOOK)pSetWinEventHook(
7431 EVENT_MIN, EVENT_MAX,
7432 0, win_event_global_hook_proc,
7433 GetCurrentProcessId(), 0,
7434 WINEVENT_OUTOFCONTEXT);
7435 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError());
7437 hevent = CreateEventA(NULL, 0, 0, NULL);
7439 hwnd2 = (HWND)hevent;
7443 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
7444 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
7446 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
7448 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
7449 /* process pending winevent messages */
7450 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
7451 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
7454 /* this one should be received only by old hook proc */
7455 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
7456 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
7457 /* this one should be received only by old hook proc */
7458 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
7460 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE);
7461 /* process pending winevent messages */
7462 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
7463 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
7465 ret = pUnhookWinEvent(hhook);
7466 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
7468 PostThreadMessageA(tid, WM_QUIT, 0, 0);
7469 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
7470 CloseHandle(hthread);
7471 CloseHandle(hevent);
7472 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
7473 /****** end of out of context event test *************/
7475 /****** start of MOUSE_LL hook test *************/
7476 hCBT_global_hook = SetWindowsHookExA(WH_MOUSE_LL, cbt_global_hook_proc, GetModuleHandleA(0), 0);
7477 /* WH_MOUSE_LL is not supported on Win9x platforms */
7478 if (!hCBT_global_hook)
7480 trace("Skipping WH_MOUSE_LL test on this platform\n");
7481 goto skip_mouse_ll_hook_test;
7484 hevent = CreateEventA(NULL, 0, 0, NULL);
7486 hwnd2 = (HWND)hevent;
7488 hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid);
7489 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
7491 while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT)
7492 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
7494 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE);
7497 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
7498 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
7499 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
7501 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE);
7503 ret = UnhookWindowsHookEx(hCBT_global_hook);
7504 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError());
7506 PostThreadMessageA(tid, WM_QUIT, 0, 0);
7507 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
7508 CloseHandle(hthread);
7509 CloseHandle(hevent);
7510 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
7511 /****** end of MOUSE_LL hook test *************/
7512 skip_mouse_ll_hook_test:
7514 ok(DestroyWindow(hwnd), "failed to destroy window\n");
7517 static void test_set_hook(void)
7521 HWINEVENTHOOK hwinevent_hook;
7523 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId());
7524 ok(hhook != 0, "local hook does not require hModule set to 0\n");
7525 UnhookWindowsHookEx(hhook);
7529 /* this test doesn't pass under Win9x: BUG! */
7530 SetLastError(0xdeadbeef);
7531 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0);
7532 ok(!hhook, "global hook requires hModule != 0\n");
7533 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %d\n", GetLastError());
7536 SetLastError(0xdeadbeef);
7537 hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId());
7538 ok(!hhook, "SetWinEventHook with invalid proc should fail\n");
7539 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */
7540 GetLastError() == 0xdeadbeef, /* Win9x */
7541 "unexpected error %d\n", GetLastError());
7543 SetLastError(0xdeadbeef);
7544 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
7545 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */
7546 GetLastError() == 0xdeadbeef, /* Win9x */
7547 "unexpected error %d\n", GetLastError());
7549 if (!pSetWinEventHook || !pUnhookWinEvent) return;
7551 /* even process local incontext hooks require hmodule */
7552 SetLastError(0xdeadbeef);
7553 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
7554 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
7555 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
7556 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
7557 GetLastError() == 0xdeadbeef, /* Win9x */
7558 "unexpected error %d\n", GetLastError());
7560 /* even thread local incontext hooks require hmodule */
7561 SetLastError(0xdeadbeef);
7562 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
7563 0, win_event_proc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT);
7564 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
7565 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
7566 GetLastError() == 0xdeadbeef, /* Win9x */
7567 "unexpected error %d\n", GetLastError());
7571 /* these 3 tests don't pass under Win9x */
7572 SetLastError(0xdeadbeef);
7573 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(1, 0,
7574 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
7575 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
7576 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError());
7578 SetLastError(0xdeadbeef);
7579 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(-1, 1,
7580 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
7581 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
7582 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError());
7584 SetLastError(0xdeadbeef);
7585 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
7586 0, win_event_proc, 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT);
7587 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n");
7588 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %d\n", GetLastError());
7591 SetLastError(0xdeadbeef);
7592 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(0, 0,
7593 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
7594 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError());
7595 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
7596 ret = pUnhookWinEvent(hwinevent_hook);
7597 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
7600 /* This call succeeds under win2k SP4, but fails under Wine.
7601 Does win2k test/use passed process id? */
7602 SetLastError(0xdeadbeef);
7603 hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
7604 0, win_event_proc, 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT);
7605 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError());
7606 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
7607 ret = pUnhookWinEvent(hwinevent_hook);
7608 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
7611 SetLastError(0xdeadbeef);
7612 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n");
7613 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
7614 GetLastError() == 0xdeadbeef, /* Win9x */
7615 "unexpected error %d\n", GetLastError());
7618 static const struct message ScrollWindowPaint1[] = {
7620 { WM_ERASEBKGND, sent|beginpaint },
7624 static const struct message ScrollWindowPaint2[] = {
7629 static void test_scrollwindowex(void)
7632 RECT rect={0,0,130,130};
7634 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll",
7635 WS_VISIBLE|WS_OVERLAPPEDWINDOW,
7636 100, 100, 200, 200, 0, 0, 0, NULL);
7637 ok (hwnd != 0, "Failed to create overlapped window\n");
7638 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
7639 WS_VISIBLE|WS_CAPTION|WS_CHILD,
7640 10, 10, 150, 150, hwnd, 0, 0, NULL);
7641 ok (hchild != 0, "Failed to create child\n");
7646 /* scroll without the child window */
7647 trace("start scroll\n");
7648 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
7649 SW_ERASE|SW_INVALIDATE);
7650 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
7651 trace("end scroll\n");
7654 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
7658 /* Now without the SW_ERASE flag */
7659 trace("start scroll\n");
7660 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE);
7661 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
7662 trace("end scroll\n");
7665 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", 0);
7669 /* now scroll the child window as well */
7670 trace("start scroll\n");
7671 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
7672 SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE);
7673 todo_wine { /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
7674 /* windows sometimes a WM_MOVE */
7675 ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
7677 trace("end scroll\n");
7680 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
7684 /* now scroll with ScrollWindow() */
7685 trace("start scroll with ScrollWindow\n");
7686 ScrollWindow( hwnd, 5, 5, NULL, NULL);
7687 trace("end scroll\n");
7690 ok_sequence(ScrollWindowPaint1, "ScrollWindow", 0);
7692 ok(DestroyWindow(hchild), "failed to destroy window\n");
7693 ok(DestroyWindow(hwnd), "failed to destroy window\n");
7697 static const struct message destroy_window_with_children[] = {
7698 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
7699 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */
7700 { 0x0090, sent|optional },
7701 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */
7702 { 0x0090, sent|optional },
7703 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
7704 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
7705 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
7706 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
7707 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */
7708 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
7709 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
7710 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
7711 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
7712 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
7713 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
7714 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
7715 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
7719 static void test_DestroyWindow(void)
7722 HWND parent, child1, child2, child3, child4, test;
7723 UINT child_id = WND_CHILD_ID + 1;
7725 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
7726 100, 100, 200, 200, 0, 0, 0, NULL);
7727 assert(parent != 0);
7728 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
7729 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL);
7730 assert(child1 != 0);
7731 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
7732 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL);
7733 assert(child2 != 0);
7734 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
7735 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL);
7736 assert(child3 != 0);
7737 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP,
7738 0, 0, 50, 50, parent, 0, 0, NULL);
7739 assert(child4 != 0);
7741 /* test owner/parent of child2 */
7742 test = GetParent(child2);
7743 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
7744 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
7746 test = pGetAncestor(child2, GA_PARENT);
7747 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
7749 test = GetWindow(child2, GW_OWNER);
7750 ok(!test, "wrong owner %p\n", test);
7752 test = SetParent(child2, parent);
7753 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test);
7755 /* test owner/parent of the parent */
7756 test = GetParent(parent);
7757 ok(!test, "wrong parent %p\n", test);
7758 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent);
7760 test = pGetAncestor(parent, GA_PARENT);
7761 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
7763 test = GetWindow(parent, GW_OWNER);
7764 ok(!test, "wrong owner %p\n", test);
7766 /* test owner/parent of child1 */
7767 test = GetParent(child1);
7768 ok(test == parent, "wrong parent %p\n", test);
7769 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
7771 test = pGetAncestor(child1, GA_PARENT);
7772 ok(test == parent, "wrong parent %p\n", test);
7774 test = GetWindow(child1, GW_OWNER);
7775 ok(!test, "wrong owner %p\n", test);
7777 /* test owner/parent of child2 */
7778 test = GetParent(child2);
7779 ok(test == parent, "wrong parent %p\n", test);
7780 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
7782 test = pGetAncestor(child2, GA_PARENT);
7783 ok(test == parent, "wrong parent %p\n", test);
7785 test = GetWindow(child2, GW_OWNER);
7786 ok(!test, "wrong owner %p\n", test);
7788 /* test owner/parent of child3 */
7789 test = GetParent(child3);
7790 ok(test == child1, "wrong parent %p\n", test);
7791 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
7793 test = pGetAncestor(child3, GA_PARENT);
7794 ok(test == child1, "wrong parent %p\n", test);
7796 test = GetWindow(child3, GW_OWNER);
7797 ok(!test, "wrong owner %p\n", test);
7799 /* test owner/parent of child4 */
7800 test = GetParent(child4);
7801 ok(test == parent, "wrong parent %p\n", test);
7802 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
7804 test = pGetAncestor(child4, GA_PARENT);
7805 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
7807 test = GetWindow(child4, GW_OWNER);
7808 ok(test == parent, "wrong owner %p\n", test);
7812 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
7813 parent, child1, child2, child3, child4);
7816 test = GetCapture();
7817 ok(test == child4, "wrong capture window %p\n", test);
7819 test_DestroyWindow_flag = TRUE;
7820 ret = DestroyWindow(parent);
7821 ok( ret, "DestroyWindow() error %d\n", GetLastError());
7822 test_DestroyWindow_flag = FALSE;
7823 ok_sequence(destroy_window_with_children, "destroy window with children", 0);
7825 ok(!IsWindow(parent), "parent still exists\n");
7826 ok(!IsWindow(child1), "child1 still exists\n");
7827 ok(!IsWindow(child2), "child2 still exists\n");
7828 ok(!IsWindow(child3), "child3 still exists\n");
7829 ok(!IsWindow(child4), "child4 still exists\n");
7831 test = GetCapture();
7832 ok(!test, "wrong capture window %p\n", test);
7836 static const struct message WmDispatchPaint[] = {
7837 { WM_NCPAINT, sent },
7838 { WM_GETTEXT, sent|defwinproc|optional },
7839 { WM_GETTEXT, sent|defwinproc|optional },
7840 { WM_ERASEBKGND, sent },
7844 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
7846 if (message == WM_PAINT) return 0;
7847 return MsgCheckProcA( hwnd, message, wParam, lParam );
7850 static void test_DispatchMessage(void)
7855 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
7856 100, 100, 200, 200, 0, 0, 0, NULL);
7857 ShowWindow( hwnd, SW_SHOW );
7858 UpdateWindow( hwnd );
7861 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc );
7863 SetRect( &rect, -5, -5, 5, 5 );
7864 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
7866 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
7868 if (msg.message != WM_PAINT) DispatchMessage( &msg );
7872 DispatchMessage( &msg );
7873 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
7874 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
7875 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE );
7876 if (++count > 10) break;
7879 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" );
7881 trace("now without DispatchMessage\n");
7883 RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
7885 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
7887 if (msg.message != WM_PAINT) DispatchMessage( &msg );
7890 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
7892 /* this will send WM_NCCPAINT just like DispatchMessage does */
7893 GetUpdateRgn( hwnd, hrgn, TRUE );
7894 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
7895 DeleteObject( hrgn );
7896 GetClientRect( hwnd, &rect );
7897 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */
7898 ok( !count, "Got multiple WM_PAINTs\n" );
7899 if (++count > 10) break;
7902 DestroyWindow(hwnd);
7906 static const struct message WmUser[] = {
7918 static DWORD CALLBACK send_msg_thread( LPVOID arg )
7920 struct sendmsg_info *info = arg;
7921 info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL );
7922 if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT, "unexpected error %d\n", GetLastError());
7926 static void wait_for_thread( HANDLE thread )
7928 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0)
7931 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage(&msg);
7935 static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
7937 if (message == WM_USER) Sleep(200);
7938 return MsgCheckProcA( hwnd, message, wParam, lParam );
7941 static void test_SendMessageTimeout(void)
7944 struct sendmsg_info info;
7947 info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
7948 100, 100, 200, 200, 0, 0, 0, NULL);
7952 info.timeout = 1000;
7953 info.ret = 0xdeadbeef;
7954 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
7955 wait_for_thread( thread );
7956 CloseHandle( thread );
7957 ok( info.ret == 1, "SendMessageTimeout failed\n" );
7958 ok_sequence( WmUser, "WmUser", FALSE );
7961 info.ret = 0xdeadbeef;
7962 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
7963 Sleep(100); /* SendMessageTimeout should time out here */
7964 wait_for_thread( thread );
7965 CloseHandle( thread );
7966 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
7967 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
7969 /* 0 means infinite timeout */
7971 info.ret = 0xdeadbeef;
7972 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
7974 wait_for_thread( thread );
7975 CloseHandle( thread );
7976 ok( info.ret == 1, "SendMessageTimeout failed\n" );
7977 ok_sequence( WmUser, "WmUser", FALSE );
7979 /* timeout is treated as signed despite the prototype */
7980 info.timeout = 0x7fffffff;
7981 info.ret = 0xdeadbeef;
7982 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
7984 wait_for_thread( thread );
7985 CloseHandle( thread );
7986 ok( info.ret == 1, "SendMessageTimeout failed\n" );
7987 ok_sequence( WmUser, "WmUser", FALSE );
7989 info.timeout = 0x80000000;
7990 info.ret = 0xdeadbeef;
7991 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
7993 wait_for_thread( thread );
7994 CloseHandle( thread );
7995 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
7996 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
7998 /* now check for timeout during message processing */
7999 SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc );
8001 info.ret = 0xdeadbeef;
8002 thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
8003 wait_for_thread( thread );
8004 CloseHandle( thread );
8005 /* we should time out but still get the message */
8006 ok( info.ret == 0, "SendMessageTimeout failed\n" );
8007 ok_sequence( WmUser, "WmUser", FALSE );
8009 DestroyWindow( info.hwnd );
8013 /****************** edit message test *************************/
8014 #define ID_EDIT 0x1234
8015 static const struct message sl_edit_setfocus[] =
8017 { HCBT_SETFOCUS, hook },
8018 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
8019 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
8020 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
8021 { WM_SETFOCUS, sent|wparam, 0 },
8022 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 },
8023 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 15 },
8024 { WM_CTLCOLOREDIT, sent|parent },
8025 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 },
8026 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8027 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8028 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
8031 static const struct message ml_edit_setfocus[] =
8033 { HCBT_SETFOCUS, hook },
8034 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
8035 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
8036 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
8037 { WM_SETFOCUS, sent|wparam, 0 },
8038 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 },
8039 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 },
8040 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8041 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8042 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
8045 static const struct message sl_edit_killfocus[] =
8047 { HCBT_SETFOCUS, hook },
8048 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
8049 { WM_KILLFOCUS, sent|wparam, 0 },
8050 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8051 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8052 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) },
8053 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
8054 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 },
8057 static const struct message sl_edit_lbutton_dblclk[] =
8059 { WM_LBUTTONDBLCLK, sent },
8060 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
8063 static const struct message sl_edit_lbutton_down[] =
8065 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
8066 { HCBT_SETFOCUS, hook },
8067 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
8068 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
8069 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
8070 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
8071 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 },
8072 { WM_CTLCOLOREDIT, sent|parent },
8073 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 },
8074 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8075 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8076 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8077 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
8078 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
8079 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8080 { WM_CTLCOLOREDIT, sent|parent|optional },
8081 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 },
8082 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8083 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8086 static const struct message ml_edit_lbutton_down[] =
8088 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
8089 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
8090 { HCBT_SETFOCUS, hook },
8091 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
8092 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
8093 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
8094 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
8095 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 },
8096 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 },
8097 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8098 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8099 { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
8102 static const struct message sl_edit_lbutton_up[] =
8104 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
8105 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8106 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
8107 { WM_CAPTURECHANGED, sent|defwinproc },
8108 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
8111 static const struct message ml_edit_lbutton_up[] =
8113 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
8114 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
8115 { WM_CAPTURECHANGED, sent|defwinproc },
8119 static WNDPROC old_edit_proc;
8121 static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
8123 static long defwndproc_counter = 0;
8127 trace("edit: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
8129 /* explicitly ignore WM_GETICON message */
8130 if (message == WM_GETICON) return 0;
8132 msg.message = message;
8133 msg.flags = sent|wparam|lparam;
8134 if (defwndproc_counter) msg.flags |= defwinproc;
8135 msg.wParam = wParam;
8136 msg.lParam = lParam;
8139 defwndproc_counter++;
8140 ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam);
8141 defwndproc_counter--;
8146 static void subclass_edit(void)
8150 if (!GetClassInfoA(0, "edit", &cls)) assert(0);
8152 old_edit_proc = cls.lpfnWndProc;
8154 cls.hInstance = GetModuleHandle(0);
8155 cls.lpfnWndProc = edit_hook_proc;
8156 cls.lpszClassName = "my_edit_class";
8157 UnregisterClass(cls.lpszClassName, cls.hInstance);
8158 if (!RegisterClassA(&cls)) assert(0);
8161 static void test_edit_messages(void)
8167 log_all_parent_messages++;
8169 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8170 100, 100, 200, 200, 0, 0, 0, NULL);
8171 ok (parent != 0, "Failed to create parent window\n");
8173 /* test single line edit */
8174 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD,
8175 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
8176 ok(hwnd != 0, "Failed to create edit window\n");
8178 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
8179 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08x\n", dlg_code);
8181 ShowWindow(hwnd, SW_SHOW);
8187 ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE);
8190 ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE);
8196 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
8197 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE);
8203 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
8204 ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE);
8206 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
8207 ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE);
8209 DestroyWindow(hwnd);
8211 /* test multiline edit */
8212 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE,
8213 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
8214 ok(hwnd != 0, "Failed to create edit window\n");
8216 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
8217 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS),
8218 "wrong dlg_code %08x\n", dlg_code);
8220 ShowWindow(hwnd, SW_SHOW);
8226 ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE);
8229 ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE);
8235 SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
8236 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE);
8242 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
8243 ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE);
8245 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
8246 ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE);
8248 DestroyWindow(hwnd);
8249 DestroyWindow(parent);
8251 log_all_parent_messages--;
8254 /**************************** End of Edit test ******************************/
8256 static const struct message WmKeyDownSkippedSeq[] =
8258 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
8261 static const struct message WmKeyUpSkippedSeq[] =
8263 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
8267 #define EV_START_STOP 0
8268 #define EV_SENDMSG 1
8274 HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
8277 static DWORD CALLBACK send_msg_thread_2(void *param)
8280 struct peekmsg_info *info = param;
8282 trace("thread: waiting for start\n");
8283 WaitForSingleObject(info->hevent[EV_START_STOP], INFINITE);
8284 trace("thread: looping\n");
8288 ret = WaitForMultipleObjects(2, info->hevent, FALSE, INFINITE);
8292 case WAIT_OBJECT_0 + EV_START_STOP:
8293 trace("thread: exiting\n");
8296 case WAIT_OBJECT_0 + EV_SENDMSG:
8297 trace("thread: sending message\n");
8298 SendNotifyMessageA(info->hwnd, WM_USER, 0, 0);
8299 SetEvent(info->hevent[EV_ACK]);
8303 trace("unexpected return: %04x\n", ret);
8311 static void test_PeekMessage(void)
8316 UINT qs_all_input = QS_ALLINPUT;
8317 UINT qs_input = QS_INPUT;
8319 struct peekmsg_info info;
8321 info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
8322 100, 100, 200, 200, 0, 0, 0, NULL);
8324 ShowWindow(info.hwnd, SW_SHOW);
8325 UpdateWindow(info.hwnd);
8326 SetFocus(info.hwnd);
8328 info.hevent[EV_START_STOP] = CreateEventA(NULL, 0, 0, NULL);
8329 info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL);
8330 info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL);
8332 hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid);
8335 trace("signalling to start looping\n");
8336 SetEvent(info.hevent[EV_START_STOP]);
8341 SetLastError(0xdeadbeef);
8342 qstatus = GetQueueStatus(qs_all_input);
8343 if (GetLastError() == ERROR_INVALID_FLAGS)
8345 trace("QS_RAWINPUT not supported on this platform\n");
8346 qs_all_input &= ~QS_RAWINPUT;
8347 qs_input &= ~QS_RAWINPUT;
8349 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
8351 trace("signalling to send message\n");
8352 SetEvent(info.hevent[EV_SENDMSG]);
8353 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
8355 /* pass invalid QS_xxxx flags */
8356 SetLastError(0xdeadbeef);
8357 qstatus = GetQueueStatus(0xffffffff);
8358 ok(qstatus == 0, "GetQueueStatus should fail: %08x\n", qstatus);
8359 ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError());
8361 qstatus = GetQueueStatus(qs_all_input);
8362 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE),
8363 "wrong qstatus %08x\n", qstatus);
8366 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
8368 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8370 ok_sequence(WmUser, "WmUser", FALSE);
8372 qstatus = GetQueueStatus(qs_all_input);
8373 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
8375 keybd_event('N', 0, 0, 0);
8376 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
8377 qstatus = GetQueueStatus(qs_all_input);
8378 ok(qstatus == MAKELONG(QS_KEY, QS_KEY),
8379 "wrong qstatus %08x\n", qstatus);
8381 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
8382 qstatus = GetQueueStatus(qs_all_input);
8383 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY),
8384 "wrong qstatus %08x\n", qstatus);
8386 InvalidateRect(info.hwnd, NULL, FALSE);
8387 qstatus = GetQueueStatus(qs_all_input);
8388 ok(qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
8389 "wrong qstatus %08x\n", qstatus);
8391 trace("signalling to send message\n");
8392 SetEvent(info.hevent[EV_SENDMSG]);
8393 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
8395 qstatus = GetQueueStatus(qs_all_input);
8396 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY),
8397 "wrong qstatus %08x\n", qstatus);
8400 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16));
8402 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8404 ok_sequence(WmUser, "WmUser", FALSE);
8406 qstatus = GetQueueStatus(qs_all_input);
8407 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
8408 "wrong qstatus %08x\n", qstatus);
8410 trace("signalling to send message\n");
8411 SetEvent(info.hevent[EV_SENDMSG]);
8412 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
8414 qstatus = GetQueueStatus(qs_all_input);
8415 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY),
8416 "wrong qstatus %08x\n", qstatus);
8419 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
8421 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8423 ok_sequence(WmUser, "WmUser", FALSE);
8425 qstatus = GetQueueStatus(qs_all_input);
8426 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
8427 "wrong qstatus %08x\n", qstatus);
8430 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
8431 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
8432 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
8433 ret, msg.message, msg.wParam);
8434 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8436 qstatus = GetQueueStatus(qs_all_input);
8437 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
8438 "wrong qstatus %08x\n", qstatus);
8441 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
8443 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8445 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8447 qstatus = GetQueueStatus(qs_all_input);
8448 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
8449 "wrong qstatus %08x\n", qstatus);
8452 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT);
8453 ok(ret && msg.message == WM_PAINT,
8454 "got %d and %04x instead of TRUE and WM_PAINT\n", ret, msg.message);
8455 DispatchMessageA(&msg);
8456 ok_sequence(WmPaint, "WmPaint", FALSE);
8458 qstatus = GetQueueStatus(qs_all_input);
8459 ok(qstatus == MAKELONG(0, QS_KEY),
8460 "wrong qstatus %08x\n", qstatus);
8463 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT);
8465 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8467 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8469 qstatus = GetQueueStatus(qs_all_input);
8470 ok(qstatus == MAKELONG(0, QS_KEY),
8471 "wrong qstatus %08x\n", qstatus);
8473 trace("signalling to send message\n");
8474 SetEvent(info.hevent[EV_SENDMSG]);
8475 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
8477 qstatus = GetQueueStatus(qs_all_input);
8478 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY),
8479 "wrong qstatus %08x\n", qstatus);
8481 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
8483 qstatus = GetQueueStatus(qs_all_input);
8484 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
8485 "wrong qstatus %08x\n", qstatus);
8488 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE);
8489 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
8490 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
8491 ret, msg.message, msg.wParam);
8492 ok_sequence(WmUser, "WmUser", FALSE);
8494 qstatus = GetQueueStatus(qs_all_input);
8495 ok(qstatus == MAKELONG(0, QS_KEY),
8496 "wrong qstatus %08x\n", qstatus);
8499 ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE);
8501 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8503 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8505 qstatus = GetQueueStatus(qs_all_input);
8506 ok(qstatus == MAKELONG(0, QS_KEY),
8507 "wrong qstatus %08x\n", qstatus);
8509 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
8511 qstatus = GetQueueStatus(qs_all_input);
8512 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY),
8513 "wrong qstatus %08x\n", qstatus);
8515 trace("signalling to send message\n");
8516 SetEvent(info.hevent[EV_SENDMSG]);
8517 WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
8519 qstatus = GetQueueStatus(qs_all_input);
8520 ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
8521 "wrong qstatus %08x\n", qstatus);
8524 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16));
8526 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8528 ok_sequence(WmUser, "WmUser", FALSE);
8530 qstatus = GetQueueStatus(qs_all_input);
8531 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
8532 "wrong qstatus %08x\n", qstatus);
8535 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */
8536 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16));
8537 else /* workaround for a missing QS_RAWINPUT support */
8538 ret = PeekMessageA(&msg, 0, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE);
8539 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N',
8540 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
8541 ret, msg.message, msg.wParam);
8542 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE);
8544 qstatus = GetQueueStatus(qs_all_input);
8545 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
8546 "wrong qstatus %08x\n", qstatus);
8549 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */
8550 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16));
8551 else /* workaround for a missing QS_RAWINPUT support */
8552 ret = PeekMessageA(&msg, 0, WM_KEYUP, WM_KEYUP, PM_REMOVE);
8553 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N',
8554 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n",
8555 ret, msg.message, msg.wParam);
8556 ok_sequence(WmKeyUpSkippedSeq, "WmKeyUpSkippedSeq", FALSE);
8558 qstatus = GetQueueStatus(qs_all_input);
8559 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
8560 "wrong qstatus %08x\n", qstatus);
8563 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE);
8565 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8567 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8569 qstatus = GetQueueStatus(qs_all_input);
8570 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
8571 "wrong qstatus %08x\n", qstatus);
8574 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
8575 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
8576 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
8577 ret, msg.message, msg.wParam);
8578 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8580 qstatus = GetQueueStatus(qs_all_input);
8582 "wrong qstatus %08x\n", qstatus);
8585 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
8587 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8589 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8591 qstatus = GetQueueStatus(qs_all_input);
8593 "wrong qstatus %08x\n", qstatus);
8595 /* test whether presence of the quit flag in the queue affects
8598 PostQuitMessage(0x1234abcd);
8600 qstatus = GetQueueStatus(qs_all_input);
8601 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE),
8602 "wrong qstatus %08x\n", qstatus);
8604 PostMessageA(info.hwnd, WM_USER, 0, 0);
8606 qstatus = GetQueueStatus(qs_all_input);
8607 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE),
8608 "wrong qstatus %08x\n", qstatus);
8611 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
8612 ok(ret && msg.message == WM_USER,
8613 "got %d and %04x instead of TRUE and WM_USER\n", ret, msg.message);
8614 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8616 qstatus = GetQueueStatus(qs_all_input);
8617 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
8618 "wrong qstatus %08x\n", qstatus);
8621 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
8622 ok(ret && msg.message == WM_QUIT,
8623 "got %d and %04x instead of TRUE and WM_QUIT\n", ret, msg.message);
8624 ok(msg.wParam == 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg.wParam);
8625 ok(msg.lParam == 0, "got lParam %08lx instead of 0\n", msg.lParam);
8626 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8628 qstatus = GetQueueStatus(qs_all_input);
8630 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
8631 "wrong qstatus %08x\n", qstatus);
8635 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
8637 "PeekMessageA should have returned FALSE instead of msg %04x\n",
8639 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
8641 qstatus = GetQueueStatus(qs_all_input);
8643 "wrong qstatus %08x\n", qstatus);
8645 trace("signalling to exit\n");
8646 SetEvent(info.hevent[EV_START_STOP]);
8648 WaitForSingleObject(hthread, INFINITE);
8650 CloseHandle(hthread);
8651 CloseHandle(info.hevent[0]);
8652 CloseHandle(info.hevent[1]);
8653 CloseHandle(info.hevent[2]);
8655 DestroyWindow(info.hwnd);
8658 static void wait_move_event(HWND hwnd, int x, int y)
8665 time = GetTickCount();
8666 while (GetTickCount() - time < 200 && !go) {
8667 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE);
8668 go = ret && msg.pt.x > x && msg.pt.y > y;
8673 static void test_PeekMessage2(void)
8679 DWORD time1, time2, time3;
8680 int x1, y1, x2, y2, x3, y3;
8683 time1 = time2 = time3 = 0;
8684 x1 = y1 = x2 = y2 = x3 = y3 = 0;
8686 /* Initialise window and make sure it is ready for events */
8687 hwnd = CreateWindow("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW,
8688 10, 10, 800, 800, NULL, NULL, NULL, NULL);
8690 trace("Window for test_PeekMessage2 %p\n", hwnd);
8691 ShowWindow(hwnd, SW_SHOW);
8695 SetCursorPos(100, 100);
8696 mouse_event(MOUSEEVENTF_MOVE, -STEP, -STEP, 0, 0);
8699 /* Do initial mousemove, wait until we can see it
8700 and then do our test peek with PM_NOREMOVE. */
8701 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0);
8702 wait_move_event(hwnd, 80, 80);
8704 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE);
8705 ok(ret, "no message available\n");
8707 trace("1st move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y);
8708 message = msg.message;
8712 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message);
8715 /* Allow time to advance a bit, and then simulate the user moving their
8716 * mouse around. After that we peek again with PM_NOREMOVE.
8717 * Although the previous mousemove message was never removed, the
8718 * mousemove we now peek should reflect the recent mouse movements
8719 * because the input queue will merge the move events. */
8721 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0);
8722 wait_move_event(hwnd, x1, y1);
8724 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE);
8725 ok(ret, "no message available\n");
8727 trace("2nd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y);
8728 message = msg.message;
8732 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message);
8733 ok(time2 > time1, "message time not advanced: %x %x\n", time1, time2);
8734 ok(x2 != x1 && y2 != y1, "coords not changed: (%d %d) (%d %d)\n", x1, y1, x2, y2);
8737 /* Have another go, to drive the point home */
8739 mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0);
8740 wait_move_event(hwnd, x2, y2);
8742 ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE);
8743 ok(ret, "no message available\n");
8745 trace("3rd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y);
8746 message = msg.message;
8750 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message);
8751 ok(time3 > time2, "message time not advanced: %x %x\n", time2, time3);
8752 ok(x3 != x2 && y3 != y2, "coords not changed: (%d %d) (%d %d)\n", x2, y2, x3, y3);
8755 DestroyWindow(hwnd);
8756 SetCursorPos(pos.x, pos.y);
8760 static void test_quit_message(void)
8765 /* test using PostQuitMessage */
8766 PostQuitMessage(0xbeef);
8768 ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
8769 ok(ret, "PeekMessage failed with error %d\n", GetLastError());
8770 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
8771 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam);
8773 ret = PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
8774 ok(ret, "PostMessage failed with error %d\n", GetLastError());
8776 ret = GetMessage(&msg, NULL, 0, 0);
8777 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError());
8778 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
8780 /* note: WM_QUIT message received after WM_USER message */
8781 ret = GetMessage(&msg, NULL, 0, 0);
8782 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError());
8783 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
8784 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam);
8786 ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
8787 ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" );
8789 /* now test with PostThreadMessage - different behaviour! */
8790 PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0xdead, 0);
8792 ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
8793 ok(ret, "PeekMessage failed with error %d\n", GetLastError());
8794 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
8795 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam);
8797 ret = PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
8798 ok(ret, "PostMessage failed with error %d\n", GetLastError());
8800 /* note: we receive the WM_QUIT message first this time */
8801 ret = GetMessage(&msg, NULL, 0, 0);
8802 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError());
8803 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
8804 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam);
8806 ret = GetMessage(&msg, NULL, 0, 0);
8807 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError());
8808 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
8811 static const struct message WmMouseHoverSeq[] = {
8812 { WM_MOUSEACTIVATE, sent|optional }, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
8813 { WM_MOUSEACTIVATE, sent|optional },
8814 { WM_TIMER, sent|optional }, /* XP sends it */
8815 { WM_SYSTIMER, sent },
8816 { WM_MOUSEHOVER, sent|wparam, 0 },
8820 static void pump_msg_loop_timeout(DWORD timeout, BOOL inject_mouse_move)
8823 DWORD start_ticks, end_ticks;
8825 start_ticks = GetTickCount();
8826 /* add some deviation (5%) to cover not expected delays */
8827 start_ticks += timeout / 20;
8831 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
8833 /* Timer proc messages are not dispatched to the window proc,
8834 * and therefore not logged.
8836 if (msg.message == WM_TIMER || msg.message == WM_SYSTIMER)
8838 struct message s_msg;
8840 s_msg.message = msg.message;
8841 s_msg.flags = sent|wparam|lparam;
8842 s_msg.wParam = msg.wParam;
8843 s_msg.lParam = msg.lParam;
8844 add_message(&s_msg);
8846 DispatchMessage(&msg);
8849 end_ticks = GetTickCount();
8851 /* inject WM_MOUSEMOVE to see how it changes tracking */
8852 if (inject_mouse_move && start_ticks + timeout / 2 >= end_ticks)
8854 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
8855 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
8857 inject_mouse_move = FALSE;
8859 } while (start_ticks + timeout >= end_ticks);
8862 static void test_TrackMouseEvent(void)
8864 TRACKMOUSEEVENT tme;
8867 RECT rc_parent, rc_child;
8868 UINT default_hover_time, hover_width = 0, hover_height = 0;
8870 #define track_hover(track_hwnd, track_hover_time) \
8871 tme.cbSize = sizeof(tme); \
8872 tme.dwFlags = TME_HOVER; \
8873 tme.hwndTrack = track_hwnd; \
8874 tme.dwHoverTime = track_hover_time; \
8875 SetLastError(0xdeadbeef); \
8876 ret = pTrackMouseEvent(&tme); \
8877 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError())
8879 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
8880 tme.cbSize = sizeof(tme); \
8881 tme.dwFlags = TME_QUERY; \
8882 tme.hwndTrack = (HWND)0xdeadbeef; \
8883 tme.dwHoverTime = 0xdeadbeef; \
8884 SetLastError(0xdeadbeef); \
8885 ret = pTrackMouseEvent(&tme); \
8886 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\
8887 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \
8888 ok(tme.dwFlags == (expected_track_flags), \
8889 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
8890 ok(tme.hwndTrack == (expected_track_hwnd), \
8891 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
8892 ok(tme.dwHoverTime == (expected_hover_time), \
8893 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time))
8895 #define track_hover_cancel(track_hwnd) \
8896 tme.cbSize = sizeof(tme); \
8897 tme.dwFlags = TME_HOVER | TME_CANCEL; \
8898 tme.hwndTrack = track_hwnd; \
8899 tme.dwHoverTime = 0xdeadbeef; \
8900 SetLastError(0xdeadbeef); \
8901 ret = pTrackMouseEvent(&tme); \
8902 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError())
8904 default_hover_time = 0xdeadbeef;
8905 SetLastError(0xdeadbeef);
8906 ret = SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &default_hover_time, 0);
8907 ok(ret, "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError());
8908 if (!ret) default_hover_time = 400;
8909 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time);
8911 SetLastError(0xdeadbeef);
8912 ret = SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0);
8913 ok(ret, "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError());
8914 if (!ret) hover_width = 4;
8915 SetLastError(0xdeadbeef);
8916 ret = SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0);
8917 ok(ret, "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError());
8918 if (!ret) hover_height = 4;
8919 trace("hover rect is %u x %d\n", hover_width, hover_height);
8921 hwnd = CreateWindowEx(0, "TestWindowClass", NULL,
8922 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8923 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
8927 hchild = CreateWindowEx(0, "TestWindowClass", NULL,
8928 WS_CHILD | WS_BORDER | WS_VISIBLE,
8929 50, 50, 200, 200, hwnd,
8937 tme.dwFlags = TME_QUERY;
8938 tme.hwndTrack = (HWND)0xdeadbeef;
8939 tme.dwHoverTime = 0xdeadbeef;
8940 SetLastError(0xdeadbeef);
8941 ret = pTrackMouseEvent(&tme);
8942 ok(!ret, "TrackMouseEvent should fail\n");
8943 ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError());
8945 tme.cbSize = sizeof(tme);
8946 tme.dwFlags = TME_HOVER;
8947 tme.hwndTrack = (HWND)0xdeadbeef;
8948 tme.dwHoverTime = 0xdeadbeef;
8949 SetLastError(0xdeadbeef);
8950 ret = pTrackMouseEvent(&tme);
8951 ok(!ret, "TrackMouseEvent should fail\n");
8952 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "not expected error %d\n", GetLastError());
8954 tme.cbSize = sizeof(tme);
8955 tme.dwFlags = TME_HOVER | TME_CANCEL;
8956 tme.hwndTrack = (HWND)0xdeadbeef;
8957 tme.dwHoverTime = 0xdeadbeef;
8958 SetLastError(0xdeadbeef);
8959 ret = pTrackMouseEvent(&tme);
8960 ok(!ret, "TrackMouseEvent should fail\n");
8961 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "not expected error %d\n", GetLastError());
8963 GetWindowRect(hwnd, &rc_parent);
8964 GetWindowRect(hchild, &rc_child);
8965 SetCursorPos(rc_child.left - 10, rc_child.top - 10);
8967 /* Process messages so that the system updates its internal current
8968 * window and hittest, otherwise TrackMouseEvent calls don't have any
8974 track_query(0, NULL, 0);
8975 track_hover(hchild, 0);
8976 track_query(0, NULL, 0);
8981 track_hover(hwnd, 0);
8982 track_query(TME_HOVER, hwnd, default_hover_time);
8984 pump_msg_loop_timeout(default_hover_time, FALSE);
8985 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE);
8987 track_query(0, NULL, 0);
8989 track_hover(hwnd, HOVER_DEFAULT);
8990 track_query(TME_HOVER, hwnd, default_hover_time);
8992 Sleep(default_hover_time / 2);
8993 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
8994 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
8996 track_query(TME_HOVER, hwnd, default_hover_time);
8998 pump_msg_loop_timeout(default_hover_time / 2, FALSE);
8999 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE);
9001 track_query(0, NULL, 0);
9003 track_hover(hwnd, HOVER_DEFAULT);
9004 track_query(TME_HOVER, hwnd, default_hover_time);
9006 pump_msg_loop_timeout(default_hover_time, TRUE);
9007 ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE);
9009 track_query(0, NULL, 0);
9011 track_hover(hwnd, HOVER_DEFAULT);
9012 track_query(TME_HOVER, hwnd, default_hover_time);
9013 track_hover_cancel(hwnd);
9015 DestroyWindow(hwnd);
9019 #undef track_hover_cancel
9023 static const struct message WmSetWindowRgn[] = {
9024 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },
9025 { WM_NCCALCSIZE, sent|wparam, 1 },
9026 { WM_NCPAINT, sent }, /* wparam != 1 */
9027 { WM_GETTEXT, sent|defwinproc|optional },
9028 { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */
9029 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },
9030 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
9034 static const struct message WmSetWindowRgn_no_redraw[] = {
9035 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW },
9036 { WM_NCCALCSIZE, sent|wparam, 1 },
9037 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW },
9038 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
9042 static const struct message WmSetWindowRgn_clear[] = {
9043 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9044 { WM_NCCALCSIZE, sent|wparam, 1 },
9045 { WM_NCPAINT, sent }, /* wparam != 1 */
9046 { WM_GETTEXT, sent|defwinproc|optional },
9047 { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */
9048 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },
9049 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
9050 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
9051 { WM_GETTEXT, sent|defwinproc|optional },
9052 { WM_ERASEBKGND, sent|optional },
9053 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
9054 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
9058 static void test_SetWindowRgn(void)
9061 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
9062 100, 100, 200, 200, 0, 0, 0, NULL);
9063 ok( hwnd != 0, "Failed to create overlapped window\n" );
9065 ShowWindow( hwnd, SW_SHOW );
9066 UpdateWindow( hwnd );
9070 trace("testing SetWindowRgn\n");
9071 hrgn = CreateRectRgn( 0, 0, 150, 150 );
9072 SetWindowRgn( hwnd, hrgn, TRUE );
9073 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn", FALSE );
9075 hrgn = CreateRectRgn( 30, 30, 160, 160 );
9076 SetWindowRgn( hwnd, hrgn, FALSE );
9077 ok_sequence( WmSetWindowRgn_no_redraw, "WmSetWindowRgn_no_redraw", FALSE );
9079 hrgn = CreateRectRgn( 0, 0, 180, 180 );
9080 SetWindowRgn( hwnd, hrgn, TRUE );
9081 ok_sequence( WmSetWindowRgn, "WmSetWindowRgn2", FALSE );
9083 SetWindowRgn( hwnd, 0, TRUE );
9084 ok_sequence( WmSetWindowRgn_clear, "WmSetWindowRgn_clear", FALSE );
9086 DestroyWindow( hwnd );
9089 /*************************** ShowWindow() test ******************************/
9090 static const struct message WmShowNormal[] = {
9091 { WM_SHOWWINDOW, sent|wparam, 1 },
9092 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
9093 { HCBT_ACTIVATE, hook },
9094 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */
9095 { HCBT_SETFOCUS, hook },
9096 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9099 static const struct message WmShow[] = {
9100 { WM_SHOWWINDOW, sent|wparam, 1 },
9101 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
9102 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */
9103 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */
9104 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */
9105 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9108 static const struct message WmShowNoActivate_1[] = {
9109 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE },
9110 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000 },
9111 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000 },
9112 { WM_MOVE, sent|defwinproc },
9113 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED },
9116 static const struct message WmShowNoActivate_2[] = {
9117 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE },
9118 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9119 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9120 { WM_MOVE, sent|defwinproc },
9121 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED },
9122 { HCBT_SETFOCUS, hook|optional },
9123 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */
9124 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */
9125 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */
9128 static const struct message WmShowNA_1[] = {
9129 { WM_SHOWWINDOW, sent|wparam, 1 },
9130 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
9131 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9134 static const struct message WmShowNA_2[] = {
9135 { WM_SHOWWINDOW, sent|wparam, 1 },
9136 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
9139 static const struct message WmRestore_1[] = {
9140 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE },
9141 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9142 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */
9143 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */
9144 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */
9145 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9146 { WM_MOVE, sent|defwinproc },
9147 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED },
9148 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */
9151 static const struct message WmRestore_2[] = {
9152 { WM_SHOWWINDOW, sent|wparam, 1 },
9153 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
9154 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */
9155 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */
9156 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */
9157 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9160 static const struct message WmRestore_3[] = {
9161 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE },
9162 { WM_GETMINMAXINFO, sent },
9163 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9164 { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */
9165 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */
9166 { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */
9167 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9168 { WM_MOVE, sent|defwinproc },
9169 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED },
9170 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */
9173 static const struct message WmRestore_4[] = {
9174 { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE },
9175 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
9176 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|0x8000 },
9177 { WM_MOVE, sent|defwinproc },
9178 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED },
9181 static const struct message WmRestore_5[] = {
9182 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL },
9183 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
9184 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|0x8000 },
9185 { WM_MOVE, sent|defwinproc },
9186 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED },
9189 static const struct message WmHide_1[] = {
9190 { WM_SHOWWINDOW, sent|wparam, 0 },
9191 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
9192 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9193 { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */
9196 static const struct message WmHide_2[] = {
9197 { WM_SHOWWINDOW, sent|wparam, 0 },
9198 { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
9199 { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
9202 static const struct message WmHide_3[] = {
9203 { WM_SHOWWINDOW, sent|wparam, 0 },
9204 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
9205 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9206 { HCBT_SETFOCUS, hook },
9207 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
9210 static const struct message WmShowMinimized_1[] = {
9211 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED },
9212 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9213 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */
9214 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */
9215 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9216 { WM_MOVE, sent|defwinproc },
9217 { WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
9220 static const struct message WmMinimize_1[] = {
9221 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
9222 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */
9223 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
9224 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9225 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9226 { WM_MOVE, sent|defwinproc },
9227 { WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
9230 static const struct message WmMinimize_2[] = {
9231 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
9232 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9233 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9234 { WM_MOVE, sent|defwinproc },
9235 { WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
9238 static const struct message WmMinimize_3[] = {
9239 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
9240 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9241 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9242 { WM_MOVE, sent|defwinproc },
9243 { WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
9246 static const struct message WmShowMinNoActivate[] = {
9247 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE },
9248 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
9249 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9252 static const struct message WmMinMax_1[] = {
9253 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED },
9256 static const struct message WmMinMax_2[] = {
9257 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED },
9260 static const struct message WmMinMax_3[] = {
9261 { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
9264 static const struct message WmMinMax_4[] = {
9265 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE },
9268 static const struct message WmShowMaximized_1[] = {
9269 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED },
9270 { WM_GETMINMAXINFO, sent },
9271 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9272 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */
9273 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */
9274 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */
9275 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9276 { WM_MOVE, sent|defwinproc },
9277 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED },
9278 { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */
9281 static const struct message WmShowMaximized_2[] = {
9282 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED },
9283 { WM_GETMINMAXINFO, sent },
9284 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
9285 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
9286 { WM_MOVE, sent|optional }, /* Win9x doesn't send it */
9287 { WM_SIZE, sent|wparam|optional, SIZE_MAXIMIZED }, /* Win9x doesn't send it */
9288 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9289 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 },
9290 { WM_MOVE, sent|defwinproc },
9291 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED },
9292 { HCBT_SETFOCUS, hook },
9295 static const struct message WmShowMaximized_3[] = {
9296 { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED },
9297 { WM_GETMINMAXINFO, sent },
9298 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
9299 { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */
9300 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */
9301 { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */
9302 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|0x8000 },
9303 { WM_MOVE, sent|defwinproc },
9304 { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED },
9308 static void test_ShowWindow(void)
9310 /* ShowWindow commands in random order */
9313 INT cmd; /* ShowWindow command */
9314 LPARAM ret; /* ShowWindow return value */
9315 DWORD style; /* window style after the command */
9316 const struct message *msg; /* message sequence the command produces */
9317 BOOL todo_msg; /* message sequence doesn't match what Wine does */
9320 /* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, FALSE },
9321 /* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, FALSE },
9322 /* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, FALSE },
9323 /* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE },
9324 /* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, FALSE },
9325 /* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, FALSE },
9326 /* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, FALSE },
9327 /* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE },
9328 /* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, FALSE },
9329 /* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, FALSE },
9330 /* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, FALSE },
9331 /* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, FALSE },
9332 /* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, FALSE },
9333 /* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE },
9334 /* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, FALSE },
9335 /* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE },
9336 /* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, FALSE },
9337 /* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, FALSE },
9338 /* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, TRUE },
9339 /* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE },
9340 /* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE },
9341 /* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, TRUE },
9342 /* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, FALSE },
9343 /* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE },
9344 /* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE },
9345 /* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, FALSE },
9346 /* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, FALSE },
9347 /* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE },
9348 /* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE },
9349 /* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, FALSE },
9350 /* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE },
9351 /* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, TRUE },
9352 /* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE },
9353 /* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE }, /* what does this mean?! */
9354 /* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE },
9355 /* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE },
9356 /* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, FALSE },
9357 /* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE },
9358 /* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE },
9359 /* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, TRUE },
9360 /* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE },
9361 /* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, TRUE },
9362 /* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, FALSE },
9363 /* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, TRUE },
9364 /* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE },
9365 /* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, FALSE },
9366 /* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, FALSE },
9367 /* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, FALSE },
9368 /* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, FALSE },
9369 /* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, FALSE },
9370 /* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, FALSE },
9371 /* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, FALSE },
9372 /* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE },
9373 /* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, TRUE },
9374 /* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE },
9375 /* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, FALSE },
9376 /* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }
9383 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
9384 hwnd = CreateWindowEx(0, "ShowWindowClass", NULL, WS_BASE,
9389 style = GetWindowLong(hwnd, GWL_STYLE) & ~WS_BASE;
9390 ok(style == 0, "expected style 0, got %08x\n", style);
9395 for (i = 0; i < sizeof(sw)/sizeof(sw[0]); i++)
9397 static const char * const sw_cmd_name[13] =
9399 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
9400 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
9401 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
9402 "SW_NORMALNA" /* 0xCC */
9405 INT idx; /* index into the above array of names */
9407 idx = (sw[i].cmd == SW_NORMALNA) ? 12 : sw[i].cmd;
9409 style = GetWindowLong(hwnd, GWL_STYLE);
9410 trace("%d: sending %s, current window style %08x\n", i+1, sw_cmd_name[idx], style);
9411 ret = ShowWindow(hwnd, sw[i].cmd);
9412 ok(!ret == !sw[i].ret, "%d: cmd %s: expected ret %lu, got %lu\n", i+1, sw_cmd_name[idx], sw[i].ret, ret);
9413 style = GetWindowLong(hwnd, GWL_STYLE) & ~WS_BASE;
9414 ok(style == sw[i].style, "%d: expected style %08x, got %08x\n", i+1, sw[i].style, style);
9416 sprintf(comment, "%d: ShowWindow(%s)", i+1, sw_cmd_name[idx]);
9417 ok_sequence(sw[i].msg, comment, sw[i].todo_msg);
9423 DestroyWindow(hwnd);
9426 static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
9430 trace("dialog: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
9434 case WM_WINDOWPOSCHANGING:
9435 case WM_WINDOWPOSCHANGED:
9437 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
9439 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
9440 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
9441 winpos->hwnd, winpos->hwndInsertAfter,
9442 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
9443 dump_winpos_flags(winpos->flags);
9445 /* Log only documented flags, win2k uses 0x1000 and 0x2000
9446 * in the high word for internal purposes
9448 wParam = winpos->flags & 0xffff;
9449 /* We are not interested in the flags that don't match under XP and Win9x */
9450 wParam &= ~(SWP_NOZORDER);
9454 /* explicitly ignore WM_GETICON message */
9459 msg.message = message;
9460 msg.flags = sent|wparam|lparam;
9461 msg.wParam = wParam;
9462 msg.lParam = lParam;
9465 /* calling DefDlgProc leads to a recursion under XP */
9476 static const struct message WmDefDlgSetFocus_1[] = {
9477 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 },
9478 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */
9479 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */
9480 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */
9481 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */
9482 { HCBT_SETFOCUS, hook },
9483 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
9484 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
9485 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
9486 { WM_SETFOCUS, sent|wparam, 0 },
9487 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 },
9488 { WM_CTLCOLOREDIT, sent },
9489 { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 },
9490 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
9491 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
9492 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
9493 { WM_COMMAND, sent|wparam, MAKEWPARAM(1, EN_SETFOCUS) },
9496 static const struct message WmDefDlgSetFocus_2[] = {
9497 { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 },
9498 { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */
9499 { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */
9500 { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */
9501 { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */
9502 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
9503 { WM_CTLCOLOREDIT, sent|optional }, /* XP */
9504 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
9507 /* Creation of a dialog */
9508 static const struct message WmCreateDialogParamSeq_1[] = {
9509 { HCBT_CREATEWND, hook },
9510 { WM_NCCREATE, sent },
9511 { WM_NCCALCSIZE, sent|wparam, 0 },
9512 { WM_CREATE, sent },
9513 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
9514 { WM_SIZE, sent|wparam, SIZE_RESTORED },
9516 { WM_SETFONT, sent },
9517 { WM_INITDIALOG, sent },
9518 { WM_CHANGEUISTATE, sent|optional },
9521 /* Creation of a dialog */
9522 static const struct message WmCreateDialogParamSeq_2[] = {
9523 { HCBT_CREATEWND, hook },
9524 { WM_NCCREATE, sent },
9525 { WM_NCCALCSIZE, sent|wparam, 0 },
9526 { WM_CREATE, sent },
9527 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
9528 { WM_SIZE, sent|wparam, SIZE_RESTORED },
9530 { WM_CHANGEUISTATE, sent|optional },
9534 static void test_dialog_messages(void)
9537 HWND hdlg, hedit1, hedit2, hfocus;
9540 #define set_selection(hctl, start, end) \
9541 ret = SendMessage(hctl, EM_SETSEL, start, end); \
9542 ok(ret == 1, "EM_SETSEL returned %ld\n", ret);
9544 #define check_selection(hctl, start, end) \
9545 ret = SendMessage(hctl, EM_GETSEL, 0, 0); \
9546 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
9550 hdlg = CreateWindowEx(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL,
9551 WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
9552 0, 0, 100, 100, 0, 0, 0, NULL);
9553 ok(hdlg != 0, "Failed to create custom dialog window\n");
9555 hedit1 = CreateWindowEx(0, "my_edit_class", NULL,
9556 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP,
9557 0, 0, 80, 20, hdlg, (HMENU)1, 0, NULL);
9558 ok(hedit1 != 0, "Failed to create edit control\n");
9559 hedit2 = CreateWindowEx(0, "my_edit_class", NULL,
9560 WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP,
9561 0, 40, 80, 20, hdlg, (HMENU)2, 0, NULL);
9562 ok(hedit2 != 0, "Failed to create edit control\n");
9564 SendMessage(hedit1, WM_SETTEXT, 0, (LPARAM)"hello");
9565 SendMessage(hedit2, WM_SETTEXT, 0, (LPARAM)"bye");
9567 hfocus = GetFocus();
9568 ok(hfocus == hdlg, "wrong focus %p\n", hfocus);
9571 hfocus = GetFocus();
9572 ok(hfocus == hedit2, "wrong focus %p\n", hfocus);
9574 check_selection(hedit1, 0, 0);
9575 check_selection(hedit2, 0, 0);
9577 set_selection(hedit2, 0, -1);
9578 check_selection(hedit2, 0, 3);
9581 hfocus = GetFocus();
9582 ok(hfocus == 0, "wrong focus %p\n", hfocus);
9585 ret = DefDlgProc(hdlg, WM_SETFOCUS, 0, 0);
9586 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret);
9587 ok_sequence(WmDefDlgSetFocus_1, "DefDlgProc(WM_SETFOCUS) 1", FALSE);
9589 hfocus = GetFocus();
9590 ok(hfocus == hedit1, "wrong focus %p\n", hfocus);
9592 check_selection(hedit1, 0, 5);
9593 check_selection(hedit2, 0, 3);
9596 ret = DefDlgProc(hdlg, WM_SETFOCUS, 0, 0);
9597 ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret);
9598 ok_sequence(WmDefDlgSetFocus_2, "DefDlgProc(WM_SETFOCUS) 2", FALSE);
9600 hfocus = GetFocus();
9601 ok(hfocus == hedit1, "wrong focus %p\n", hfocus);
9603 check_selection(hedit1, 0, 5);
9604 check_selection(hedit2, 0, 3);
9607 DestroyWindow(hedit1);
9608 DestroyWindow(hedit2);
9609 DestroyWindow(hdlg);
9612 #undef set_selection
9613 #undef check_selection
9615 ok(GetClassInfo(0, "#32770", &cls), "GetClassInfo failed\n");
9616 cls.lpszClassName = "MyDialogClass";
9617 cls.hInstance = GetModuleHandle(0);
9618 /* need a cast since a dlgproc is used as a wndproc */
9619 cls.lpfnWndProc = (WNDPROC)test_dlg_proc;
9620 if (!RegisterClass(&cls)) assert(0);
9622 hdlg = CreateDialogParam(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 0);
9623 ok(IsWindow(hdlg), "CreateDialogParam failed\n");
9624 ok_sequence(WmCreateDialogParamSeq_1, "CreateDialogParam_1", FALSE);
9626 DestroyWindow(hdlg);
9629 hdlg = CreateDialogParam(0, "CLASS_TEST_DIALOG_2", 0, NULL, 0);
9630 ok(IsWindow(hdlg), "CreateDialogParam failed\n");
9631 ok_sequence(WmCreateDialogParamSeq_2, "CreateDialogParam_2", FALSE);
9633 DestroyWindow(hdlg);
9636 UnregisterClass(cls.lpszClassName, cls.hInstance);
9639 static void test_nullCallback(void)
9643 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
9644 100, 100, 200, 200, 0, 0, 0, NULL);
9645 ok (hwnd != 0, "Failed to create overlapped window\n");
9647 SendMessageCallbackA(hwnd,WM_NULL,0,0,NULL,0);
9649 DestroyWindow(hwnd);
9652 static const struct message SetForegroundWindowSeq[] =
9654 { WM_NCACTIVATE, sent|wparam, 0 },
9655 { WM_GETTEXT, sent|defwinproc|optional },
9656 { WM_ACTIVATE, sent|wparam, 0 },
9657 { WM_ACTIVATEAPP, sent|wparam, 0 },
9658 { WM_KILLFOCUS, sent },
9659 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
9660 { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 },
9664 static void test_SetForegroundWindow(void)
9668 hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
9669 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
9670 100, 100, 200, 200, 0, 0, 0, NULL);
9671 ok (hwnd != 0, "Failed to create overlapped window\n");
9674 trace("SetForegroundWindow( 0 )\n");
9675 SetForegroundWindow( 0 );
9676 ok_sequence(WmEmptySeq, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE);
9677 trace("SetForegroundWindow( GetDesktopWindow() )\n");
9678 SetForegroundWindow( GetDesktopWindow() );
9679 ok_sequence(SetForegroundWindowSeq, "SetForegroundWindow( desktop ) away from "
9680 "foreground top level window", FALSE);
9683 DestroyWindow(hwnd);
9686 static void test_dbcs_wm_char(void)
9697 struct message wmCharSeq[2];
9701 skip("GetCPInfoExA is not available\n");
9705 pGetCPInfoExA( CP_ACP, 0, &cpinfo );
9706 if (cpinfo.MaxCharSize != 2)
9708 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo.CodePageName );
9712 dbch[0] = dbch[1] = 0;
9714 bad_wch = cpinfo.UnicodeDefaultChar;
9715 for (i = 0; !wch && i < MAX_LEADBYTES && cpinfo.LeadByte[i]; i += 2)
9716 for (j = cpinfo.LeadByte[i]; !wch && j <= cpinfo.LeadByte[i+1]; j++)
9717 for (k = 128; k <= 255; k++)
9723 if (MultiByteToWideChar( CP_ACP, 0, str, 2, wstr, 2 ) == 1 &&
9724 WideCharToMultiByte( CP_ACP, 0, wstr, 1, str, 2, NULL, NULL ) == 2 &&
9725 (BYTE)str[0] == j && (BYTE)str[1] == k &&
9726 HIBYTE(wstr[0]) && HIBYTE(wstr[0]) != 0xff)
9737 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
9740 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
9741 dbch[0], dbch[1], wch, bad_wch, cpinfo.CodePageName );
9743 hwnd = CreateWindowExW(0, testWindowClassW, NULL,
9744 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL);
9745 hwnd2 = CreateWindowExW(0, testWindowClassW, NULL,
9746 WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL);
9747 ok (hwnd != 0, "Failed to create overlapped window\n");
9748 ok (hwnd2 != 0, "Failed to create overlapped window\n");
9751 memset( wmCharSeq, 0, sizeof(wmCharSeq) );
9752 wmCharSeq[0].message = WM_CHAR;
9753 wmCharSeq[0].flags = sent|wparam;
9754 wmCharSeq[0].wParam = wch;
9756 /* posted message */
9757 PostMessageA( hwnd, WM_CHAR, dbch[0], 0 );
9758 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9759 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9760 ok( PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9761 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9762 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch );
9763 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9765 /* posted thread message */
9766 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR, dbch[0], 0 );
9767 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9768 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9769 ok( PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9770 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9771 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch );
9772 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9776 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 );
9777 ok_sequence( WmEmptySeq, "no messages", FALSE );
9778 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9779 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9780 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9782 /* sent message with timeout */
9784 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res );
9785 ok_sequence( WmEmptySeq, "no messages", FALSE );
9786 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res );
9787 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9788 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9790 /* sent message with timeout and callback */
9792 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res );
9793 ok_sequence( WmEmptySeq, "no messages", FALSE );
9794 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 );
9795 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9796 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9798 /* sent message with callback */
9800 SendNotifyMessageA( hwnd, WM_CHAR, dbch[0], 0 );
9801 ok_sequence( WmEmptySeq, "no messages", FALSE );
9802 SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 );
9803 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9804 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9806 /* direct window proc call */
9808 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 );
9809 ok_sequence( WmEmptySeq, "no messages", FALSE );
9810 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 );
9811 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9813 /* dispatch message */
9815 msg.message = WM_CHAR;
9816 msg.wParam = dbch[0];
9818 DispatchMessageA( &msg );
9819 ok_sequence( WmEmptySeq, "no messages", FALSE );
9820 msg.wParam = dbch[1];
9821 DispatchMessageA( &msg );
9822 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9824 /* window handle is irrelevant */
9826 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 );
9827 ok_sequence( WmEmptySeq, "no messages", FALSE );
9828 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9829 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9830 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9832 /* interleaved post and send */
9834 PostMessageA( hwnd2, WM_CHAR, dbch[0], 0 );
9835 SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 );
9836 ok_sequence( WmEmptySeq, "no messages", FALSE );
9837 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9838 PostMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9839 ok_sequence( WmEmptySeq, "no messages", FALSE );
9840 ok( PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9841 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9842 ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch );
9843 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9844 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9845 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9846 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9848 /* interleaved sent message and winproc */
9850 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 );
9851 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 );
9852 ok_sequence( WmEmptySeq, "no messages", FALSE );
9853 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9854 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9855 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 );
9856 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9858 /* interleaved winproc and dispatch */
9860 msg.message = WM_CHAR;
9861 msg.wParam = dbch[0];
9863 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 );
9864 DispatchMessageA( &msg );
9865 ok_sequence( WmEmptySeq, "no messages", FALSE );
9866 msg.wParam = dbch[1];
9867 DispatchMessageA( &msg );
9868 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9869 CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 );
9870 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9872 /* interleaved sends */
9874 SendMessageA( hwnd, WM_CHAR, dbch[0], 0 );
9875 SendMessageCallbackA( hwnd, WM_CHAR, dbch[0], 0, NULL, 0 );
9876 ok_sequence( WmEmptySeq, "no messages", FALSE );
9877 SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res );
9878 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9879 SendMessageA( hwnd, WM_CHAR, dbch[1], 0 );
9880 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9884 SendMessageA( hwnd2, WM_CHAR, (dbch[1] << 8) | dbch[0], 0 );
9885 ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
9886 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9888 /* other char messages are not magic */
9889 PostMessageA( hwnd, WM_SYSCHAR, dbch[0], 0 );
9890 ok( PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9891 ok( msg.message == WM_SYSCHAR, "unexpected message %x\n", msg.message );
9892 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch );
9893 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9894 PostMessageA( hwnd, WM_DEADCHAR, dbch[0], 0 );
9895 ok( PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9896 ok( msg.message == WM_DEADCHAR, "unexpected message %x\n", msg.message );
9897 ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch );
9898 ok( !PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9900 /* test retrieving messages */
9902 PostMessageW( hwnd, WM_CHAR, wch, 0 );
9903 ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9904 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9905 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9906 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9907 ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9908 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9909 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9910 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9911 ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9913 /* message filters */
9914 PostMessageW( hwnd, WM_CHAR, wch, 0 );
9915 ok( PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "no message\n" );
9916 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9917 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9918 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9919 /* message id is filtered, hwnd is not */
9920 ok( !PeekMessageA( &msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ), "no message\n" );
9921 ok( PeekMessageA( &msg, hwnd2, 0, 0, PM_REMOVE ), "no message\n" );
9922 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9923 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9924 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9925 ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9927 /* mixing GetMessage and PostMessage */
9928 PostMessageW( hwnd, WM_CHAR, wch, 0xbeef );
9929 ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" );
9930 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9931 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9932 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9933 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam );
9936 ok( time - GetTickCount() <= 100, "bad time %x\n", msg.time );
9937 ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" );
9938 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9939 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9940 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9941 ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam );
9942 ok( msg.time == time, "bad time %x/%x\n", msg.time, time );
9943 ok( msg.pt.x == pt.x && msg.pt.y == pt.y, "bad point %u,%u/%u,%u\n", msg.pt.x, msg.pt.y, pt.x, pt.y );
9944 ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9946 /* without PM_REMOVE */
9947 PostMessageW( hwnd, WM_CHAR, wch, 0 );
9948 ok( PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "no message\n" );
9949 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9950 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9951 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9952 ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" );
9953 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9954 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9955 ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9956 ok( PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "no message\n" );
9957 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9958 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9959 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9960 ok( PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "no message\n" );
9961 ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
9962 ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
9963 ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] );
9964 ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
9966 DestroyWindow(hwnd);
9969 #define ID_LISTBOX 0x000f
9971 static const struct message wm_lb_setcursel_0[] =
9973 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 },
9974 { WM_CTLCOLORLISTBOX, sent|parent },
9975 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 },
9976 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 },
9977 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 },
9980 static const struct message wm_lb_setcursel_1[] =
9982 { LB_SETCURSEL, sent|wparam|lparam, 1, 0 },
9983 { WM_CTLCOLORLISTBOX, sent|parent },
9984 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000020f2 },
9985 { WM_CTLCOLORLISTBOX, sent|parent },
9986 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000121f2 },
9987 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 },
9988 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 },
9991 static const struct message wm_lb_setcursel_2[] =
9993 { LB_SETCURSEL, sent|wparam|lparam, 2, 0 },
9994 { WM_CTLCOLORLISTBOX, sent|parent },
9995 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000021f2 },
9996 { WM_CTLCOLORLISTBOX, sent|parent },
9997 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000122f2 },
9998 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 },
9999 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 },
10002 static const struct message wm_lb_click_0[] =
10004 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, MAKELPARAM(1,1) },
10005 { HCBT_SETFOCUS, hook },
10006 { WM_KILLFOCUS, sent|parent },
10007 { WM_IME_SETCONTEXT, sent|wparam|optional|parent, 0 },
10008 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
10009 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
10010 { WM_SETFOCUS, sent },
10012 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001142f2 },
10013 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SETFOCUS) },
10014 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 },
10015 { WM_LBTRACKPOINT, sent|wparam|lparam|parent, 0, MAKELPARAM(1,1) },
10016 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
10018 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000142f2 },
10019 { WM_CTLCOLORLISTBOX, sent|parent },
10020 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000022f2 },
10021 { WM_CTLCOLORLISTBOX, sent|parent },
10022 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 },
10023 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001140f2 },
10025 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 },
10026 { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 },
10028 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
10029 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
10030 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, 0 },
10031 { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE) },
10035 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
10037 static LRESULT (WINAPI *listbox_orig_proc)(HWND, UINT, WPARAM, LPARAM);
10039 static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
10041 struct message msg;
10043 /* do not log painting messages */
10044 if (message != WM_PAINT &&
10045 message != WM_NCPAINT &&
10046 message != WM_SYNCPAINT &&
10047 message != WM_ERASEBKGND &&
10048 message != WM_NCHITTEST &&
10049 message != WM_GETTEXT &&
10050 message != WM_GETICON &&
10051 message != WM_DEVICECHANGE)
10053 trace("listbox: %p, %04x, %08lx, %08lx\n", hwnd, message, wp, lp);
10055 msg.message = message;
10056 msg.flags = sent|wparam|lparam;
10062 return CallWindowProcA(listbox_orig_proc, hwnd, message, wp, lp);
10065 static void check_lb_state_dbg(HWND listbox, int count, int cur_sel,
10066 int caret_index, int top_index, int line)
10070 /* calling an orig proc helps to avoid unnecessary message logging */
10071 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCOUNT, 0, 0);
10072 ok_(__FILE__, line)(ret == count, "expected count %d, got %ld\n", count, ret);
10073 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCURSEL, 0, 0);
10074 ok_(__FILE__, line)(ret == cur_sel, "expected cur sel %d, got %ld\n", cur_sel, ret);
10075 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCARETINDEX, 0, 0);
10076 ok_(__FILE__, line)(ret == caret_index, "expected caret index %d, got %ld\n", caret_index, ret);
10077 ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETTOPINDEX, 0, 0);
10078 ok_(__FILE__, line)(ret == top_index, "expected top index %d, got %ld\n", top_index, ret);
10081 static void test_listbox(void)
10083 HWND parent, listbox;
10086 parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
10087 100, 100, 200, 200, 0, 0, 0, NULL);
10088 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL,
10089 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE,
10090 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
10091 listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc);
10093 check_lb_state(listbox, 0, LB_ERR, 0, 0);
10095 ret = SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
10096 ok(ret == 0, "expected 0, got %ld\n", ret);
10097 ret = SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
10098 ok(ret == 1, "expected 1, got %ld\n", ret);
10099 ret = SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
10100 ok(ret == 2, "expected 2, got %ld\n", ret);
10102 check_lb_state(listbox, 3, LB_ERR, 0, 0);
10106 log_all_parent_messages++;
10108 trace("selecting item 0\n");
10109 ret = SendMessage(listbox, LB_SETCURSEL, 0, 0);
10110 ok(ret == 0, "expected 0, got %ld\n", ret);
10111 ok_sequence(wm_lb_setcursel_0, "LB_SETCURSEL 0", FALSE );
10112 check_lb_state(listbox, 3, 0, 0, 0);
10115 trace("selecting item 1\n");
10116 ret = SendMessage(listbox, LB_SETCURSEL, 1, 0);
10117 ok(ret == 1, "expected 1, got %ld\n", ret);
10118 ok_sequence(wm_lb_setcursel_1, "LB_SETCURSEL 1", FALSE );
10119 check_lb_state(listbox, 3, 1, 1, 0);
10121 trace("selecting item 2\n");
10122 ret = SendMessage(listbox, LB_SETCURSEL, 2, 0);
10123 ok(ret == 2, "expected 2, got %ld\n", ret);
10124 ok_sequence(wm_lb_setcursel_2, "LB_SETCURSEL 2", FALSE );
10125 check_lb_state(listbox, 3, 2, 2, 0);
10127 trace("clicking on item 0\n");
10128 ret = SendMessage(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1));
10129 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret);
10130 ret = SendMessage(listbox, WM_LBUTTONUP, 0, 0);
10131 ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret);
10132 ok_sequence(wm_lb_click_0, "WM_LBUTTONDOWN 0", FALSE );
10133 check_lb_state(listbox, 3, 0, 0, 0);
10136 log_all_parent_messages--;
10138 DestroyWindow(parent);
10144 FARPROC pIsWinEventHookInstalled = 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
10148 if (!RegisterWindowClasses()) assert(0);
10150 if (pSetWinEventHook)
10152 hEvent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
10153 GetModuleHandleA(0),
10156 GetCurrentThreadId(),
10157 WINEVENT_INCONTEXT);
10158 assert(hEvent_hook);
10160 if (pIsWinEventHookInstalled)
10163 for (event = EVENT_MIN; event <= EVENT_MAX; event++)
10164 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
10168 cbt_hook_thread_id = GetCurrentThreadId();
10169 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
10174 /* Fix message sequences before removing 4 lines below */
10176 if (pUnhookWinEvent && hEvent_hook)
10178 ret = pUnhookWinEvent(hEvent_hook);
10179 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
10180 pUnhookWinEvent = 0;
10186 test_PeekMessage();
10187 test_PeekMessage2();
10188 test_scrollwindowex();
10191 invisible_parent_tests();
10192 test_mdi_messages();
10193 test_button_messages();
10194 test_static_messages();
10195 test_paint_messages();
10196 test_interthread_messages();
10197 test_message_conversion();
10198 test_accelerators();
10200 test_timers_no_wnd();
10202 test_DestroyWindow();
10203 test_DispatchMessage();
10204 test_SendMessageTimeout();
10205 test_edit_messages();
10206 test_quit_message();
10208 if (!pTrackMouseEvent)
10209 skip("TrackMouseEvent is not available\n");
10211 test_TrackMouseEvent();
10213 test_SetWindowRgn();
10215 test_dialog_messages();
10216 test_nullCallback();
10217 test_SetForegroundWindow();
10218 test_dbcs_wm_char();
10221 UnhookWindowsHookEx(hCBT_hook);
10222 if (pUnhookWinEvent)
10224 ret = pUnhookWinEvent(hEvent_hook);
10225 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
10226 SetLastError(0xdeadbeef);
10227 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n");
10228 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
10229 GetLastError() == 0xdeadbeef, /* Win9x */
10230 "unexpected error %d\n", GetLastError());
10233 skip("UnhookWinEvent is not available\n");