2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004, 2005 Dmitry Timoshkov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define _WIN32_WINNT 0x0500 /* For WM_CHANGEUISTATE */
34 #include "wine/test.h"
36 #define MDI_FIRST_CHILD_ID 2004
38 /* undocumented SWP flags - from SDK 3.1 */
39 #define SWP_NOCLIENTSIZE 0x0800
40 #define SWP_NOCLIENTMOVE 0x1000
42 static HWINEVENTHOOK hEvent_hook;
45 FIXME: add tests for these
46 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
47 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
48 WS_THICKFRAME: thick border
49 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
50 WS_BORDER (default for overlapped windows): single black border
51 none (default for child (and popup?) windows): no border
68 UINT message; /* the WM_* code */
69 msg_flags_t flags; /* message props */
70 WPARAM wParam; /* expected value of wParam */
71 LPARAM lParam; /* expected value of lParam */
74 /* Empty message sequence */
75 static const struct message WmEmptySeq[] =
79 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
80 static const struct message WmCreateOverlappedSeq[] = {
81 { HCBT_CREATEWND, hook },
82 { WM_GETMINMAXINFO, sent },
83 { WM_NCCREATE, sent },
84 { WM_NCCALCSIZE, sent|wparam, 0 },
85 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
87 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
90 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
91 * for a not visible overlapped window.
93 static const struct message WmSWP_ShowOverlappedSeq[] = {
94 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
95 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
96 { WM_NCPAINT, sent|wparam|optional, 1 },
97 { WM_GETTEXT, sent|defwinproc|optional },
98 { WM_ERASEBKGND, sent|optional },
99 { HCBT_ACTIVATE, hook },
100 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
101 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
102 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
103 { WM_ACTIVATEAPP, sent|wparam, 1 },
104 { WM_NCACTIVATE, sent|wparam, 1 },
105 { WM_GETTEXT, sent|defwinproc|optional },
106 { WM_ACTIVATE, sent|wparam, 1 },
107 { HCBT_SETFOCUS, hook },
108 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
109 { WM_IME_NOTIFY, sent|defwinproc|optional },
110 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
111 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
112 { WM_NCPAINT, sent|wparam|optional, 1 },
113 { WM_GETTEXT, sent|defwinproc|optional },
114 { WM_ERASEBKGND, sent|optional },
115 /* Win9x adds SWP_NOZORDER below */
116 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
117 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
118 { WM_NCPAINT, sent|wparam|optional, 1 },
119 { WM_ERASEBKGND, sent|optional },
122 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
123 * for a visible overlapped window.
125 static const struct message WmSWP_HideOverlappedSeq[] = {
126 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
127 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
128 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
131 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
132 static const struct message WmShowOverlappedSeq[] = {
133 { WM_SHOWWINDOW, sent|wparam, 1 },
134 { WM_NCPAINT, sent|wparam|optional, 1 },
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, SWP_NOSIZE|SWP_NOMOVE },
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|defwinproc|optional },
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|optional },
159 { WM_NCPAINT, sent|optional },
160 { WM_ERASEBKGND, sent|optional },
161 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
162 * messages. Does that mean that CreateWindow doesn't set initial
163 * window dimensions for overlapped windows?
170 /* ShowWindow(SW_HIDE) for a visible overlapped window */
171 static const struct message WmHideOverlappedSeq[] = {
172 { WM_SHOWWINDOW, sent|wparam, 0 },
173 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
174 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
175 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
178 { WM_NCACTIVATE, sent|wparam, 0 },
179 { WM_ACTIVATE, sent|wparam, 0 },
180 { WM_ACTIVATEAPP, sent|wparam, 0 },
181 { WM_KILLFOCUS, sent|wparam, 0 },
182 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
183 { WM_IME_NOTIFY, sent|optional|defwinproc },
186 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
187 static const struct message WmHideInvisibleOverlappedSeq[] = {
190 /* DestroyWindow for a visible overlapped window */
191 static const struct message WmDestroyOverlappedSeq[] = {
192 { HCBT_DESTROYWND, hook },
193 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
194 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
195 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
196 { WM_NCACTIVATE, sent|wparam, 0 },
197 { WM_ACTIVATE, sent|wparam, 0 },
198 { WM_ACTIVATEAPP, sent|wparam, 0 },
199 { WM_KILLFOCUS, sent|wparam, 0 },
200 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
201 { WM_IME_NOTIFY, sent|optional|defwinproc },
202 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
203 { WM_DESTROY, sent },
204 { WM_NCDESTROY, sent },
207 /* CreateWindow (for a child popup window, not initially visible) */
208 static const struct message WmCreateChildPopupSeq[] = {
209 { HCBT_CREATEWND, hook },
210 { WM_NCCREATE, sent },
211 { WM_NCCALCSIZE, sent|wparam, 0 },
213 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
218 /* CreateWindow (for a popup window, not initially visible,
219 * which sets WS_VISIBLE in WM_CREATE handler)
221 static const struct message WmCreateInvisiblePopupSeq[] = {
222 { HCBT_CREATEWND, hook },
223 { WM_NCCREATE, sent },
224 { WM_NCCALCSIZE, sent|wparam, 0 },
226 { WM_STYLECHANGING, sent },
227 { WM_STYLECHANGED, sent },
228 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
233 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
234 * for a popup window with WS_VISIBLE style set
236 static const struct message WmShowVisiblePopupSeq_2[] = {
237 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
240 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
241 * for a popup window with WS_VISIBLE style set
243 static const struct message WmShowVisiblePopupSeq_3[] = {
244 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
245 { HCBT_ACTIVATE, hook },
246 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
247 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
248 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
249 { WM_NCACTIVATE, sent|wparam, 1 },
250 { WM_ACTIVATE, sent|wparam, 1 },
251 { HCBT_SETFOCUS, hook },
252 { WM_KILLFOCUS, sent|parent },
253 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
254 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
255 { WM_IME_NOTIFY, sent|defwinproc|optional },
256 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
257 { WM_SETFOCUS, sent|defwinproc },
260 /* CreateWindow (for child window, not initially visible) */
261 static const struct message WmCreateChildSeq[] = {
262 { HCBT_CREATEWND, hook },
263 { WM_NCCREATE, sent },
264 /* child is inserted into parent's child list after WM_NCCREATE returns */
265 { WM_NCCALCSIZE, sent|wparam, 0 },
267 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
270 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
273 /* CreateWindow (for maximized child window, not initially visible) */
274 static const struct message WmCreateMaximizedChildSeq[] = {
275 { HCBT_CREATEWND, hook },
276 { WM_NCCREATE, sent },
277 { WM_NCCALCSIZE, sent|wparam, 0 },
279 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
282 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
283 { WM_GETMINMAXINFO, sent },
284 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
285 { WM_NCCALCSIZE, sent|wparam, 1 },
286 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 },
287 { WM_SIZE, sent|defwinproc },
288 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
289 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
292 /* CreateWindow (for a child window, initially visible) */
293 static const struct message WmCreateVisibleChildSeq[] = {
294 { HCBT_CREATEWND, hook },
295 { WM_NCCREATE, sent },
296 /* child is inserted into parent's child list after WM_NCCREATE returns */
297 { WM_NCCALCSIZE, sent|wparam, 0 },
298 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
300 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
303 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
304 { WM_SHOWWINDOW, sent|wparam, 1 },
305 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
306 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
307 { WM_ERASEBKGND, sent|parent|optional },
308 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
311 /* ShowWindow(SW_SHOW) for a not visible child window */
312 static const struct message WmShowChildSeq[] = {
313 { WM_SHOWWINDOW, sent|wparam, 1 },
314 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
315 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
316 { WM_ERASEBKGND, sent|parent|optional },
317 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
320 /* ShowWindow(SW_HIDE) for a visible child window */
321 static const struct message WmHideChildSeq[] = {
322 { WM_SHOWWINDOW, sent|wparam, 0 },
323 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
324 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
325 { WM_ERASEBKGND, sent|parent|optional },
326 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
329 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
330 * for a not visible child window
332 static const struct message WmShowChildSeq_2[] = {
333 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
334 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
335 { WM_CHILDACTIVATE, sent },
336 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
339 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
340 * for a not visible child window
342 static const struct message WmShowChildSeq_3[] = {
343 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
344 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
345 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
348 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
349 * for a visible child window with a caption
351 static const struct message WmShowChildSeq_4[] = {
352 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
353 { WM_CHILDACTIVATE, sent },
356 /* ShowWindow(SW_SHOW) for child with invisible parent */
357 static const struct message WmShowChildInvisibleParentSeq[] = {
358 { WM_SHOWWINDOW, sent|wparam, 1 },
361 /* ShowWindow(SW_HIDE) for child with invisible parent */
362 static const struct message WmHideChildInvisibleParentSeq[] = {
363 { WM_SHOWWINDOW, sent|wparam, 0 },
366 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
367 static const struct message WmShowChildInvisibleParentSeq_2[] = {
368 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
369 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
370 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
373 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
374 static const struct message WmHideChildInvisibleParentSeq_2[] = {
375 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
376 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
377 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
380 /* DestroyWindow for a visible child window */
381 static const struct message WmDestroyChildSeq[] = {
382 { HCBT_DESTROYWND, hook },
383 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
384 { WM_SHOWWINDOW, sent|wparam, 0 },
385 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
386 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
387 { WM_ERASEBKGND, sent|parent|optional },
388 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
389 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
390 { WM_KILLFOCUS, sent },
391 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
392 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
393 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
394 { WM_SETFOCUS, sent|parent },
395 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
396 { WM_DESTROY, sent },
397 { WM_DESTROY, sent|optional }, /* some other (IME?) window */
398 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */
399 { WM_NCDESTROY, sent },
402 /* Moving the mouse in nonclient area */
403 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
404 { WM_NCHITTEST, sent },
405 { WM_SETCURSOR, sent },
406 { WM_NCMOUSEMOVE, posted },
409 /* Moving the mouse in client area */
410 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
411 { WM_NCHITTEST, sent },
412 { WM_SETCURSOR, sent },
413 { WM_MOUSEMOVE, posted },
416 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
417 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
418 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
419 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
420 { WM_GETMINMAXINFO, sent|defwinproc },
421 { WM_ENTERSIZEMOVE, sent|defwinproc },
422 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
423 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
424 { WM_MOVE, sent|defwinproc },
425 { WM_EXITSIZEMOVE, sent|defwinproc },
428 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
429 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
430 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
431 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
432 { WM_GETMINMAXINFO, sent|defwinproc },
433 { WM_ENTERSIZEMOVE, sent|defwinproc },
434 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
435 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
436 { WM_GETMINMAXINFO, sent|defwinproc },
437 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
438 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
439 { WM_GETTEXT, sent|defwinproc },
440 { WM_ERASEBKGND, sent|defwinproc },
441 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
442 { WM_MOVE, sent|defwinproc },
443 { WM_SIZE, sent|defwinproc },
444 { WM_EXITSIZEMOVE, sent|defwinproc },
447 /* Resizing child window with MoveWindow (32) */
448 static const struct message WmResizingChildWithMoveWindowSeq[] = {
449 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
450 { WM_NCCALCSIZE, sent|wparam, 1 },
451 { WM_ERASEBKGND, sent|optional },
452 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
453 { WM_MOVE, sent|defwinproc },
454 { WM_SIZE, sent|defwinproc },
455 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
458 /* Clicking on inactive button */
459 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
460 { WM_NCHITTEST, sent },
461 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
462 { WM_MOUSEACTIVATE, sent },
463 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
464 { WM_SETCURSOR, sent },
465 { WM_SETCURSOR, sent|parent|defwinproc },
466 { WM_LBUTTONDOWN, posted },
467 { WM_KILLFOCUS, posted|parent },
468 { WM_SETFOCUS, posted },
469 { WM_CTLCOLORBTN, posted|parent },
470 { BM_SETSTATE, posted },
471 { WM_CTLCOLORBTN, posted|parent },
472 { WM_LBUTTONUP, posted },
473 { BM_SETSTATE, posted },
474 { WM_CTLCOLORBTN, posted|parent },
475 { WM_COMMAND, posted|parent },
478 /* Reparenting a button (16/32) */
479 /* The last child (button) reparented gets topmost for its new parent. */
480 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
481 { WM_SHOWWINDOW, sent|wparam, 0 },
482 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
483 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
484 { WM_ERASEBKGND, sent|parent },
485 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
486 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
487 { WM_CHILDACTIVATE, sent },
488 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
489 { WM_MOVE, sent|defwinproc },
490 { WM_SHOWWINDOW, sent|wparam, 1 },
493 /* Creation of a custom dialog (32) */
494 static const struct message WmCreateCustomDialogSeq[] = {
495 { HCBT_CREATEWND, hook },
496 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
497 { WM_GETMINMAXINFO, sent },
498 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
499 { WM_NCCREATE, sent },
500 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
501 { WM_NCCALCSIZE, sent|wparam, 0 },
502 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
503 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
505 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
506 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
507 { WM_SHOWWINDOW, sent|wparam, 1 },
508 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
509 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
510 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
511 { HCBT_ACTIVATE, hook },
512 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
514 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
516 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
517 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
519 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
521 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
522 { WM_NCACTIVATE, sent|wparam, 1 },
523 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
524 { WM_GETTEXT, sent|optional|defwinproc },
525 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
526 { WM_GETICON, sent|optional|defwinproc },
527 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
528 { WM_GETICON, sent|optional|defwinproc },
529 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
530 { WM_GETICON, sent|optional|defwinproc },
531 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
532 { WM_GETTEXT, sent|optional|defwinproc },
533 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
534 { WM_ACTIVATE, sent|wparam, 1 },
535 { WM_KILLFOCUS, sent|parent },
536 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
537 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
538 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
539 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
540 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
541 { WM_IME_NOTIFY, sent|optional|defwinproc },
542 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
543 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
544 { WM_SETFOCUS, sent },
545 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
546 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
547 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
548 { WM_NCPAINT, sent|wparam, 1 },
549 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
550 { WM_GETTEXT, sent|optional|defwinproc },
551 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
552 { WM_GETICON, sent|optional|defwinproc },
553 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
554 { WM_GETICON, sent|optional|defwinproc },
555 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
556 { WM_GETICON, sent|optional|defwinproc },
557 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
558 { WM_GETTEXT, sent|optional|defwinproc },
559 { WM_ERASEBKGND, sent },
560 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
561 { WM_CTLCOLORDLG, sent|defwinproc },
562 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
563 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
564 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
565 { WM_GETTEXT, sent|optional },
566 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
567 { WM_GETICON, sent|optional },
568 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
569 { WM_GETICON, sent|optional },
570 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
571 { WM_GETICON, sent|optional },
572 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
573 { WM_GETTEXT, sent|optional },
574 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
575 { WM_NCCALCSIZE, sent|optional },
576 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
577 { WM_NCPAINT, sent|optional },
578 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
579 { WM_GETTEXT, sent|optional|defwinproc },
580 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
581 { WM_GETICON, sent|optional|defwinproc },
582 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
583 { WM_GETICON, sent|optional|defwinproc },
584 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
585 { WM_GETICON, sent|optional|defwinproc },
586 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
587 { WM_GETTEXT, sent|optional|defwinproc },
588 { WM_ERASEBKGND, sent|optional },
589 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
590 { WM_CTLCOLORDLG, sent|optional|defwinproc },
592 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
596 /* Calling EndDialog for a custom dialog (32) */
597 static const struct message WmEndCustomDialogSeq[] = {
598 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
599 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
600 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
601 { WM_GETTEXT, sent|optional },
602 { WM_GETICON, sent|optional },
603 { WM_GETICON, sent|optional },
604 { WM_GETICON, sent|optional },
605 { HCBT_ACTIVATE, hook },
606 { WM_NCACTIVATE, sent|wparam, 0 },
607 { WM_GETTEXT, sent|optional|defwinproc },
608 { WM_GETICON, sent|optional|defwinproc },
609 { WM_GETICON, sent|optional|defwinproc },
610 { WM_GETICON, sent|optional|defwinproc },
611 { WM_GETTEXT, sent|optional|defwinproc },
612 { WM_ACTIVATE, sent|wparam, 0 },
613 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
614 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
615 { HCBT_SETFOCUS, hook },
616 { WM_KILLFOCUS, sent },
617 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
618 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
619 { WM_IME_NOTIFY, sent|optional },
620 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
621 { WM_SETFOCUS, sent|parent|defwinproc },
624 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
625 static const struct message WmShowCustomDialogSeq[] = {
626 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
627 { WM_SHOWWINDOW, sent|wparam, 1 },
628 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
629 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
630 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
631 { HCBT_ACTIVATE, hook },
632 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
634 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
635 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
637 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
638 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
639 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
640 { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
641 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
642 { WM_NCACTIVATE, sent|wparam, 1 },
643 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
644 { WM_ACTIVATE, sent|wparam, 1 },
646 { WM_KILLFOCUS, sent|parent },
647 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
648 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
649 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
650 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
651 { WM_IME_NOTIFY, sent|optional|defwinproc },
652 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
653 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
654 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
655 { WM_SETFOCUS, sent },
656 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
657 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
658 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
659 { WM_NCPAINT, sent|wparam, 1 },
660 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
661 { WM_ERASEBKGND, sent },
662 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
663 { WM_CTLCOLORDLG, sent|defwinproc },
665 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
666 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
669 /* Creation and destruction of a modal dialog (32) */
670 static const struct message WmModalDialogSeq[] = {
671 { WM_CANCELMODE, sent|parent },
672 { HCBT_SETFOCUS, hook },
673 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
674 { WM_KILLFOCUS, sent|parent },
675 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
676 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
677 { WM_ENABLE, sent|parent|wparam, 0 },
678 { HCBT_CREATEWND, hook },
679 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
680 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
681 { WM_SETFONT, sent },
682 { WM_INITDIALOG, sent },
683 { WM_CHANGEUISTATE, sent|optional },
684 { WM_SHOWWINDOW, sent },
685 { HCBT_ACTIVATE, hook },
686 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
687 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
688 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
689 { WM_NCACTIVATE, sent|wparam, 1 },
690 { WM_GETICON, sent|optional },
691 { WM_GETICON, sent|optional },
692 { WM_GETICON, sent|optional },
693 { WM_GETTEXT, sent|optional },
694 { WM_ACTIVATE, sent|wparam, 1 },
695 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
696 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
697 { WM_NCPAINT, sent },
698 { WM_GETICON, sent|optional },
699 { WM_GETICON, sent|optional },
700 { WM_GETICON, sent|optional },
701 { WM_GETTEXT, sent|optional },
702 { WM_ERASEBKGND, sent },
703 { WM_CTLCOLORDLG, sent },
704 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
705 { WM_GETICON, sent|optional },
706 { WM_GETICON, sent|optional },
707 { WM_GETICON, sent|optional },
708 { WM_GETTEXT, sent|optional },
709 { WM_NCCALCSIZE, sent|optional },
710 { WM_NCPAINT, sent|optional },
711 { WM_GETICON, sent|optional },
712 { WM_GETICON, sent|optional },
713 { WM_GETICON, sent|optional },
714 { WM_GETTEXT, sent|optional },
715 { WM_ERASEBKGND, sent|optional },
716 { WM_CTLCOLORDLG, sent|optional },
717 { WM_PAINT, sent|optional },
718 { WM_CTLCOLORBTN, sent },
719 { WM_ENTERIDLE, sent|parent|optional },
721 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
722 { WM_ENABLE, sent|parent|wparam, 1 },
723 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
724 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
725 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
726 { WM_GETICON, sent|optional },
727 { WM_GETICON, sent|optional },
728 { WM_GETICON, sent|optional },
729 { WM_GETTEXT, sent|optional },
730 { HCBT_ACTIVATE, hook },
731 { WM_NCACTIVATE, sent|wparam, 0 },
732 { WM_GETICON, sent|optional },
733 { WM_GETICON, sent|optional },
734 { WM_GETICON, sent|optional },
735 { WM_GETTEXT, sent|optional },
736 { WM_ACTIVATE, sent|wparam, 0 },
737 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
738 { WM_WINDOWPOSCHANGING, sent|optional },
739 { HCBT_SETFOCUS, hook },
740 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
741 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
742 { WM_SETFOCUS, sent|parent|defwinproc },
743 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
744 { HCBT_DESTROYWND, hook },
745 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
746 { WM_DESTROY, sent },
747 { WM_NCDESTROY, sent },
750 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
751 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
752 /* (inside dialog proc, handling WM_INITDIALOG) */
753 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
754 { WM_NCCALCSIZE, sent },
755 { WM_NCACTIVATE, sent|parent|wparam, 0 },
756 { WM_GETTEXT, sent|defwinproc },
757 { WM_ACTIVATE, sent|parent|wparam, 0 },
758 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
759 { WM_WINDOWPOSCHANGING, sent|parent },
760 { WM_NCACTIVATE, sent|wparam, 1 },
761 { WM_ACTIVATE, sent|wparam, 1 },
762 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
763 { WM_SIZE, sent|defwinproc },
764 /* (setting focus) */
765 { WM_SHOWWINDOW, sent|wparam, 1 },
766 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
767 { WM_NCPAINT, sent },
768 { WM_GETTEXT, sent|defwinproc },
769 { WM_ERASEBKGND, sent },
770 { WM_CTLCOLORDLG, sent|defwinproc },
771 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
773 /* (bunch of WM_CTLCOLOR* for each control) */
774 { WM_PAINT, sent|parent },
775 { WM_ENTERIDLE, sent|parent|wparam, 0 },
776 { WM_SETCURSOR, sent|parent },
779 /* SetMenu for NonVisible windows with size change*/
780 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
781 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
782 { WM_NCCALCSIZE, sent|wparam, 1 },
783 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
784 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW },
785 { WM_MOVE, sent|defwinproc },
786 { WM_SIZE, sent|defwinproc },
787 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
788 { WM_GETICON, sent|optional },
789 { WM_GETICON, sent|optional },
790 { WM_GETICON, sent|optional },
791 { WM_GETTEXT, sent|optional },
792 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
795 /* SetMenu for NonVisible windows with no size change */
796 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
797 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
798 { WM_NCCALCSIZE, sent|wparam, 1 },
799 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
800 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
803 /* SetMenu for Visible windows with size change */
804 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
805 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
806 { WM_NCCALCSIZE, sent|wparam, 1 },
807 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
808 { WM_NCPAINT, sent|wparam, 1 },
809 { WM_GETTEXT, sent|defwinproc|optional },
810 { WM_ERASEBKGND, sent|optional },
811 { WM_ACTIVATE, sent|optional },
812 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
813 { WM_MOVE, sent|defwinproc },
814 { WM_SIZE, sent|defwinproc },
815 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
816 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
817 { WM_NCPAINT, sent|wparam|optional, 1 },
818 { WM_ERASEBKGND, sent|optional },
821 /* SetMenu for Visible windows with no size change */
822 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
823 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
824 { WM_NCCALCSIZE, sent|wparam, 1 },
825 { WM_NCPAINT, sent|wparam, 1 },
826 { WM_GETTEXT, sent|defwinproc|optional },
827 { WM_ERASEBKGND, sent|optional },
828 { WM_ACTIVATE, sent|optional },
829 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
830 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
833 /* DrawMenuBar for a visible window */
834 static const struct message WmDrawMenuBarSeq[] =
836 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
837 { WM_NCCALCSIZE, sent|wparam, 1 },
838 { WM_NCPAINT, sent|wparam, 1 },
839 { WM_GETTEXT, sent|defwinproc|optional },
840 { WM_ERASEBKGND, sent|optional },
841 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
842 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
846 static const struct message WmSetRedrawFalseSeq[] =
848 { WM_SETREDRAW, sent|wparam, 0 },
852 static const struct message WmSetRedrawTrueSeq[] =
854 { WM_SETREDRAW, sent|wparam, 1 },
858 static const struct message WmEnableWindowSeq[] =
860 { WM_CANCELMODE, sent },
861 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
866 static const struct message WmGetScrollRangeSeq[] =
868 { SBM_GETRANGE, sent },
871 static const struct message WmGetScrollInfoSeq[] =
873 { SBM_GETSCROLLINFO, sent },
876 static const struct message WmSetScrollRangeSeq[] =
878 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
879 sends SBM_SETSCROLLINFO.
881 { SBM_SETSCROLLINFO, sent },
884 /* SetScrollRange for a window without a non-client area */
885 static const struct message WmSetScrollRangeHSeq_empty[] =
887 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 },
890 static const struct message WmSetScrollRangeVSeq_empty[] =
892 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 },
895 static const struct message WmSetScrollRangeHVSeq[] =
897 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
898 { WM_NCCALCSIZE, sent|wparam, 1 },
899 { WM_GETTEXT, sent|defwinproc|optional },
900 { WM_ERASEBKGND, sent|optional },
901 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
902 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
905 /* SetScrollRange for a window with a non-client area */
906 static const struct message WmSetScrollRangeHV_NC_Seq[] =
908 { WM_WINDOWPOSCHANGING, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
909 { WM_NCCALCSIZE, sent|wparam, 1 },
910 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
911 { WM_NCPAINT, sent|optional },
912 { WM_GETTEXT, sent|defwinproc|optional },
913 { WM_GETICON, sent|optional|defwinproc },
914 { WM_GETICON, sent|optional|defwinproc },
915 { WM_GETICON, sent|optional|defwinproc },
916 { WM_GETTEXT, sent|defwinproc|optional },
917 { WM_ERASEBKGND, sent|optional },
918 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
919 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
920 { WM_SIZE, sent|defwinproc },
921 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
922 { WM_GETTEXT, sent|optional },
923 { WM_GETICON, sent|optional },
924 { WM_GETICON, sent|optional },
925 { WM_GETICON, sent|optional },
926 { WM_GETTEXT, sent|optional },
927 { WM_GETICON, sent|optional },
928 { WM_GETICON, sent|optional },
929 { WM_GETICON, sent|optional },
930 { WM_GETTEXT, sent|optional },
931 { WM_GETICON, sent|optional },
932 { WM_GETICON, sent|optional },
933 { WM_GETICON, sent|optional },
934 { WM_GETTEXT, sent|optional },
937 /* test if we receive the right sequence of messages */
938 /* after calling ShowWindow( SW_SHOWNA) */
939 static const struct message WmSHOWNAChildInvisParInvis[] = {
940 { WM_SHOWWINDOW, sent|wparam, 1 },
943 static const struct message WmSHOWNAChildVisParInvis[] = {
944 { WM_SHOWWINDOW, sent|wparam, 1 },
947 static const struct message WmSHOWNAChildVisParVis[] = {
948 { WM_SHOWWINDOW, sent|wparam, 1 },
949 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
952 static const struct message WmSHOWNAChildInvisParVis[] = {
953 { WM_SHOWWINDOW, sent|wparam, 1 },
954 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER},
955 { WM_ERASEBKGND, sent|optional },
956 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
959 static const struct message WmSHOWNATopVisible[] = {
960 { WM_SHOWWINDOW, sent|wparam, 1 },
961 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
964 static const struct message WmSHOWNATopInvisible[] = {
965 { WM_SHOWWINDOW, sent|wparam, 1 },
966 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
967 { WM_NCPAINT, sent|wparam, 1 },
968 { WM_GETTEXT, sent|defwinproc|optional },
969 { WM_ERASEBKGND, sent|optional },
970 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
976 static int after_end_dialog;
977 static int sequence_cnt, sequence_size;
978 static struct message* sequence;
979 static int log_all_parent_messages;
981 static void add_message(const struct message *msg)
986 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
988 if (sequence_cnt == sequence_size)
991 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
995 sequence[sequence_cnt].message = msg->message;
996 sequence[sequence_cnt].flags = msg->flags;
997 sequence[sequence_cnt].wParam = msg->wParam;
998 sequence[sequence_cnt].lParam = msg->lParam;
1003 static void flush_sequence()
1005 HeapFree(GetProcessHeap(), 0, sequence);
1007 sequence_cnt = sequence_size = 0;
1010 #define ok_sequence( exp, contx, todo) \
1011 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
1014 static void ok_sequence_(const struct message *expected, const char *context, int todo,
1015 const char *file, int line)
1017 static const struct message end_of_sequence = { 0, 0, 0, 0 };
1018 const struct message *actual;
1021 add_message(&end_of_sequence);
1025 while (expected->message && actual->message)
1027 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
1029 if (expected->message == actual->message)
1031 if (expected->flags & wparam)
1033 if (expected->wParam != actual->wParam && todo)
1037 ok_( file, line) (FALSE,
1038 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1039 context, expected->message, expected->wParam, actual->wParam);
1043 ok_( file, line) (expected->wParam == actual->wParam,
1044 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1045 context, expected->message, expected->wParam, actual->wParam);
1047 if (expected->flags & lparam)
1048 ok_( file, line) (expected->lParam == actual->lParam,
1049 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
1050 context, expected->message, expected->lParam, actual->lParam);
1051 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
1052 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
1053 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
1054 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
1055 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
1056 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
1057 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
1058 "%s: the msg 0x%04x should have been %s\n",
1059 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
1060 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
1061 "%s: the msg 0x%04x was expected in %s\n",
1062 context, expected->message, (expected->flags & parent) ? "parent" : "child");
1063 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook),
1064 "%s: the msg 0x%04x should have been sent by a hook\n",
1065 context, expected->message);
1066 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
1067 "%s: the msg 0x%04x should have been sent by a winevent hook\n",
1068 context, expected->message);
1072 /* silently drop winevent messages if there is no support for them */
1073 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))
1079 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1080 context, expected->message, actual->message);
1087 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1088 context, expected->message, actual->message);
1094 /* skip all optional trailing messages */
1095 while (expected->message && ((expected->flags & optional) ||
1096 ((expected->flags & winevent_hook) && !hEvent_hook)))
1102 if (expected->message || actual->message) {
1104 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1105 context, expected->message, actual->message);
1111 if (expected->message || actual->message)
1112 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1113 context, expected->message, actual->message);
1115 if( todo && !failcount) /* succeeded yet marked todo */
1117 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
1123 /******************************** MDI test **********************************/
1125 /* CreateWindow for MDI frame window, initially visible */
1126 static const struct message WmCreateMDIframeSeq[] = {
1127 { HCBT_CREATEWND, hook },
1128 { WM_GETMINMAXINFO, sent },
1129 { WM_NCCREATE, sent },
1130 { WM_NCCALCSIZE, sent|wparam, 0 },
1131 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1132 { WM_CREATE, sent },
1133 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1134 { WM_SHOWWINDOW, sent|wparam, 1 },
1135 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1136 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1137 { HCBT_ACTIVATE, hook },
1138 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1139 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
1140 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
1141 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* Win9x */
1142 { WM_ACTIVATEAPP, sent|wparam, 1 },
1143 { WM_NCACTIVATE, sent|wparam, 1 },
1144 { WM_ACTIVATE, sent|wparam, 1 },
1145 { HCBT_SETFOCUS, hook },
1146 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1147 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1148 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
1149 /* Win9x adds SWP_NOZORDER below */
1150 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
1155 /* DestroyWindow for MDI frame window, initially visible */
1156 static const struct message WmDestroyMDIframeSeq[] = {
1157 { HCBT_DESTROYWND, hook },
1158 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1159 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1160 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1161 { WM_NCACTIVATE, sent|wparam, 0 },
1162 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
1163 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
1164 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
1165 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1166 { WM_DESTROY, sent },
1167 { WM_NCDESTROY, sent },
1170 /* CreateWindow for MDI client window, initially visible */
1171 static const struct message WmCreateMDIclientSeq[] = {
1172 { HCBT_CREATEWND, hook },
1173 { WM_NCCREATE, sent },
1174 { WM_NCCALCSIZE, sent|wparam, 0 },
1175 { WM_CREATE, sent },
1176 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1179 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
1180 { WM_SHOWWINDOW, sent|wparam, 1 },
1181 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE },
1182 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1183 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1186 /* DestroyWindow for MDI client window, initially visible */
1187 static const struct message WmDestroyMDIclientSeq[] = {
1188 { HCBT_DESTROYWND, hook },
1189 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
1190 { WM_SHOWWINDOW, sent|wparam, 0 },
1191 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1192 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1193 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1194 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1195 { WM_DESTROY, sent },
1196 { WM_NCDESTROY, sent },
1199 /* CreateWindow for MDI child window, initially visible */
1200 static const struct message WmCreateMDIchildVisibleSeq[] = {
1201 { HCBT_CREATEWND, hook },
1202 { WM_NCCREATE, sent },
1203 { WM_NCCALCSIZE, sent|wparam, 0 },
1204 { WM_CREATE, sent },
1205 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1208 /* Win2k sends wparam set to
1209 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1210 * while Win9x doesn't bother to set child window id according to
1211 * CLIENTCREATESTRUCT.idFirstChild
1213 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1214 { WM_SHOWWINDOW, sent|wparam, 1 },
1215 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1216 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1217 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1218 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1219 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1220 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1221 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1223 /* Win9x: message sequence terminates here. */
1225 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1226 { HCBT_SETFOCUS, hook }, /* in MDI client */
1227 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1228 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1229 { WM_SETFOCUS, sent }, /* in MDI client */
1230 { HCBT_SETFOCUS, hook },
1231 { WM_KILLFOCUS, sent }, /* in MDI client */
1232 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1233 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1234 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1235 { WM_SETFOCUS, sent|defwinproc },
1236 { WM_MDIACTIVATE, sent|defwinproc },
1239 /* DestroyWindow for MDI child window, initially visible */
1240 static const struct message WmDestroyMDIchildVisibleSeq[] = {
1241 { HCBT_DESTROYWND, hook },
1242 /* Win2k sends wparam set to
1243 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1244 * while Win9x doesn't bother to set child window id according to
1245 * CLIENTCREATESTRUCT.idFirstChild
1247 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1248 { WM_SHOWWINDOW, sent|wparam, 0 },
1249 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1250 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1251 { WM_ERASEBKGND, sent|parent|optional },
1252 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1254 /* { WM_DESTROY, sent }
1255 * Win9x: message sequence terminates here.
1258 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1259 { WM_KILLFOCUS, sent },
1260 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1261 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1262 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1263 { WM_SETFOCUS, sent }, /* in MDI client */
1265 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1266 { WM_KILLFOCUS, sent }, /* in MDI client */
1267 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1268 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1269 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1270 { WM_SETFOCUS, sent }, /* in MDI client */
1272 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1274 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1275 { WM_KILLFOCUS, sent },
1276 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1277 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1278 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1279 { WM_SETFOCUS, sent }, /* in MDI client */
1281 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1282 { WM_KILLFOCUS, sent }, /* in MDI client */
1283 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1284 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1285 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1286 { WM_SETFOCUS, sent }, /* in MDI client */
1288 { WM_DESTROY, sent },
1290 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1291 { WM_KILLFOCUS, sent },
1292 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1293 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1294 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1295 { WM_SETFOCUS, sent }, /* in MDI client */
1297 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1298 { WM_KILLFOCUS, sent }, /* in MDI client */
1299 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1300 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1301 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1302 { WM_SETFOCUS, sent }, /* in MDI client */
1304 { WM_NCDESTROY, sent },
1307 /* CreateWindow for MDI child window, initially invisible */
1308 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1309 { HCBT_CREATEWND, hook },
1310 { WM_NCCREATE, sent },
1311 { WM_NCCALCSIZE, sent|wparam, 0 },
1312 { WM_CREATE, sent },
1313 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1316 /* Win2k sends wparam set to
1317 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1318 * while Win9x doesn't bother to set child window id according to
1319 * CLIENTCREATESTRUCT.idFirstChild
1321 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1324 /* DestroyWindow for MDI child window, initially invisible */
1325 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1326 { HCBT_DESTROYWND, hook },
1327 /* Win2k sends wparam set to
1328 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1329 * while Win9x doesn't bother to set child window id according to
1330 * CLIENTCREATESTRUCT.idFirstChild
1332 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1333 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1334 { WM_DESTROY, sent },
1335 { WM_NCDESTROY, sent },
1338 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1339 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1340 { HCBT_CREATEWND, hook },
1341 { WM_NCCREATE, sent },
1342 { WM_NCCALCSIZE, sent|wparam, 0 },
1343 { WM_CREATE, sent },
1344 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1347 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1348 { WM_GETMINMAXINFO, sent },
1349 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1350 { WM_NCCALCSIZE, sent|wparam, 1 },
1351 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1352 { WM_SIZE, sent|defwinproc },
1354 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1355 { WM_NCCALCSIZE, sent|wparam, 1 },
1356 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1357 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1358 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1359 /* Win2k sends wparam set to
1360 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1361 * while Win9x doesn't bother to set child window id according to
1362 * CLIENTCREATESTRUCT.idFirstChild
1364 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1365 { WM_SHOWWINDOW, sent|wparam, 1 },
1366 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1367 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1368 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1369 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1370 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1371 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1372 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1374 /* Win9x: message sequence terminates here. */
1376 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1377 { HCBT_SETFOCUS, hook }, /* in MDI client */
1378 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1379 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1380 { WM_SETFOCUS, sent }, /* in MDI client */
1381 { HCBT_SETFOCUS, hook },
1382 { WM_KILLFOCUS, sent }, /* in MDI client */
1383 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1384 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1385 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1386 { WM_SETFOCUS, sent|defwinproc },
1387 { WM_MDIACTIVATE, sent|defwinproc },
1389 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1390 { WM_NCCALCSIZE, sent|wparam, 1 },
1391 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1392 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1395 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1396 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
1397 /* restore the 1st MDI child */
1398 { WM_SETREDRAW, sent|wparam, 0 },
1399 { HCBT_MINMAX, hook },
1400 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1401 { WM_NCCALCSIZE, sent|wparam, 1 },
1402 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1403 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1404 { WM_SIZE, sent|defwinproc },
1406 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1407 { WM_NCCALCSIZE, sent|wparam, 1 },
1408 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1409 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1410 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1411 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
1412 /* create the 2nd MDI child */
1413 { HCBT_CREATEWND, hook },
1414 { WM_NCCREATE, sent },
1415 { WM_NCCALCSIZE, sent|wparam, 0 },
1416 { WM_CREATE, sent },
1417 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1420 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1421 { WM_GETMINMAXINFO, sent },
1422 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1423 { WM_NCCALCSIZE, sent|wparam, 1 },
1424 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1425 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1426 { WM_SIZE, sent|defwinproc },
1428 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1429 { WM_NCCALCSIZE, sent|wparam, 1 },
1430 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1431 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1432 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1433 /* Win2k sends wparam set to
1434 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1435 * while Win9x doesn't bother to set child window id according to
1436 * CLIENTCREATESTRUCT.idFirstChild
1438 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1439 { WM_SHOWWINDOW, sent|wparam, 1 },
1440 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1441 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1442 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1443 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1444 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1445 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1447 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1448 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1450 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1452 /* Win9x: message sequence terminates here. */
1454 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1455 { HCBT_SETFOCUS, hook },
1456 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
1457 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
1458 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1459 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1460 { WM_SETFOCUS, sent }, /* in MDI client */
1461 { HCBT_SETFOCUS, hook },
1462 { WM_KILLFOCUS, sent }, /* in MDI client */
1463 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1464 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1465 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1466 { WM_SETFOCUS, sent|defwinproc },
1468 { WM_MDIACTIVATE, sent|defwinproc },
1470 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1471 { WM_NCCALCSIZE, sent|wparam, 1 },
1472 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1473 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1476 /* WM_MDICREATE MDI child window, initially visible and maximized */
1477 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
1478 { WM_MDICREATE, sent },
1479 { HCBT_CREATEWND, hook },
1480 { WM_NCCREATE, sent },
1481 { WM_NCCALCSIZE, sent|wparam, 0 },
1482 { WM_CREATE, sent },
1483 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1486 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1487 { WM_GETMINMAXINFO, sent },
1488 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1489 { WM_NCCALCSIZE, sent|wparam, 1 },
1490 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1491 { WM_SIZE, sent|defwinproc },
1494 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1495 { WM_NCCALCSIZE, sent|wparam, 1 },
1496 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1497 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1498 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1500 /* Win2k sends wparam set to
1501 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1502 * while Win9x doesn't bother to set child window id according to
1503 * CLIENTCREATESTRUCT.idFirstChild
1505 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1506 { WM_SHOWWINDOW, sent|wparam, 1 },
1507 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1509 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1511 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1512 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1513 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1515 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1516 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1518 /* Win9x: message sequence terminates here. */
1520 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1521 { HCBT_SETFOCUS, hook }, /* in MDI client */
1522 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1523 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1524 { WM_SETFOCUS, sent }, /* in MDI client */
1525 { HCBT_SETFOCUS, hook },
1526 { WM_KILLFOCUS, sent }, /* in MDI client */
1527 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1528 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1529 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1530 { WM_SETFOCUS, sent|defwinproc },
1532 { WM_MDIACTIVATE, sent|defwinproc },
1535 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1536 { WM_NCCALCSIZE, sent|wparam, 1 },
1537 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1538 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1541 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1542 { WM_NCCALCSIZE, sent|wparam, 1 },
1543 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1544 { WM_MOVE, sent|defwinproc },
1545 { WM_SIZE, sent|defwinproc },
1548 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1549 { WM_NCCALCSIZE, sent|wparam, 1 },
1550 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1554 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1555 { WM_NCCALCSIZE, sent|wparam, 1 },
1556 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1557 { WM_SIZE, sent|defwinproc },
1559 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1560 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1561 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1565 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1566 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
1567 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
1568 { HCBT_SYSCOMMAND, hook },
1569 { WM_CLOSE, sent|defwinproc },
1570 { WM_MDIDESTROY, sent }, /* in MDI client */
1572 /* bring the 1st MDI child to top */
1573 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
1574 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
1576 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1578 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
1579 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1580 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1582 /* maximize the 1st MDI child */
1583 { HCBT_MINMAX, hook },
1584 { WM_GETMINMAXINFO, sent|defwinproc },
1585 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
1586 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1587 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
1588 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1589 { WM_SIZE, sent|defwinproc },
1591 /* restore the 2nd MDI child */
1592 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
1593 { HCBT_MINMAX, hook },
1594 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOZORDER|0x8000 },
1595 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1597 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1599 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1600 { WM_SIZE, sent|defwinproc },
1602 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1604 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
1606 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1607 { WM_NCCALCSIZE, sent|wparam, 1 },
1608 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1609 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1610 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1612 /* bring the 1st MDI child to top */
1613 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1614 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1615 { HCBT_SETFOCUS, hook },
1616 { WM_KILLFOCUS, sent|defwinproc },
1617 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
1618 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1619 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1620 { WM_SETFOCUS, sent }, /* in MDI client */
1621 { HCBT_SETFOCUS, hook },
1622 { WM_KILLFOCUS, sent }, /* in MDI client */
1623 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1624 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1625 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1626 { WM_SETFOCUS, sent|defwinproc },
1627 { WM_MDIACTIVATE, sent|defwinproc },
1628 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1630 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1631 { WM_SHOWWINDOW, sent|wparam, 1 },
1632 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1633 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1634 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1635 { WM_MDIREFRESHMENU, sent },
1637 { HCBT_DESTROYWND, hook },
1638 /* Win2k sends wparam set to
1639 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1640 * while Win9x doesn't bother to set child window id according to
1641 * CLIENTCREATESTRUCT.idFirstChild
1643 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1644 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
1645 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1646 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1647 { WM_ERASEBKGND, sent|parent|optional },
1648 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1650 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1651 { WM_DESTROY, sent|defwinproc },
1652 { WM_NCDESTROY, sent|defwinproc },
1655 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1656 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
1657 { WM_MDIDESTROY, sent }, /* in MDI client */
1658 { WM_SHOWWINDOW, sent|wparam, 0 },
1659 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1660 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1661 { WM_ERASEBKGND, sent|parent|optional },
1662 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1664 { HCBT_SETFOCUS, hook },
1665 { WM_KILLFOCUS, sent },
1666 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1667 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1668 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1669 { WM_SETFOCUS, sent }, /* in MDI client */
1670 { HCBT_SETFOCUS, hook },
1671 { WM_KILLFOCUS, sent }, /* in MDI client */
1672 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1673 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1674 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1675 { WM_SETFOCUS, sent },
1678 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1679 { WM_NCCALCSIZE, sent|wparam, 1 },
1680 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1681 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1684 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1685 { WM_NCCALCSIZE, sent|wparam, 1 },
1686 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1687 { WM_MOVE, sent|defwinproc },
1688 { WM_SIZE, sent|defwinproc },
1691 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1692 { WM_NCCALCSIZE, sent|wparam, 1 },
1693 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1697 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1698 { WM_NCCALCSIZE, sent|wparam, 1 },
1699 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1700 { WM_SIZE, sent|defwinproc },
1703 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1704 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1705 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1706 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1709 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1710 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1711 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1712 { WM_MOVE, sent|defwinproc },
1713 { WM_SIZE, sent|defwinproc },
1716 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1717 { WM_NCCALCSIZE, sent|wparam, 1 },
1718 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1722 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOZORDER },
1723 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1724 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1725 { WM_SIZE, sent|defwinproc },
1726 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1727 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1728 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1729 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1730 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1731 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1734 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1735 { WM_NCCALCSIZE, sent|wparam, 1 },
1736 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1737 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1739 { WM_NCACTIVATE, sent|wparam, 0 },
1740 { WM_MDIACTIVATE, sent },
1742 { HCBT_MINMAX, hook },
1743 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
1744 { WM_NCCALCSIZE, sent|wparam, 1 },
1746 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1748 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1749 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE|0x8000 },
1750 { WM_SIZE, sent|defwinproc },
1753 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1754 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1755 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1756 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1759 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1760 { WM_NCCALCSIZE, sent|wparam, 1 },
1761 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1762 { WM_MOVE, sent|defwinproc },
1763 { WM_SIZE, sent|defwinproc },
1766 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1767 { WM_NCCALCSIZE, sent|wparam, 1 },
1768 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1770 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1771 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
1772 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1774 { HCBT_SETFOCUS, hook },
1775 { WM_KILLFOCUS, sent },
1776 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1777 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1778 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1779 { WM_SETFOCUS, sent }, /* in MDI client */
1781 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
1783 { HCBT_DESTROYWND, hook },
1784 /* Win2k sends wparam set to
1785 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1786 * while Win9x doesn't bother to set child window id according to
1787 * CLIENTCREATESTRUCT.idFirstChild
1789 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1791 { WM_SHOWWINDOW, sent|wparam, 0 },
1792 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1793 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1794 { WM_ERASEBKGND, sent|parent|optional },
1795 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1797 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1798 { WM_DESTROY, sent },
1799 { WM_NCDESTROY, sent },
1802 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1803 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
1804 { HCBT_MINMAX, hook },
1805 { WM_GETMINMAXINFO, sent },
1806 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1807 { WM_NCCALCSIZE, sent|wparam, 1 },
1808 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1809 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1811 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1812 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1813 { HCBT_SETFOCUS, hook },
1814 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1815 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1816 { WM_SETFOCUS, sent }, /* in MDI client */
1817 { HCBT_SETFOCUS, hook },
1818 { WM_KILLFOCUS, sent }, /* in MDI client */
1819 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1820 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1821 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1822 { WM_SETFOCUS, sent|defwinproc },
1823 { WM_MDIACTIVATE, sent|defwinproc },
1824 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1825 { WM_SIZE, sent|defwinproc },
1827 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1828 { WM_NCCALCSIZE, sent|wparam, 1 },
1829 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1830 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1831 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1834 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1835 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
1836 { HCBT_MINMAX, hook },
1837 { WM_GETMINMAXINFO, sent },
1838 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1839 { WM_NCCALCSIZE, sent|wparam, 1 },
1840 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1841 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1842 { WM_SIZE, sent|defwinproc },
1844 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1845 { WM_NCCALCSIZE, sent|wparam, 1 },
1846 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1847 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1848 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1851 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
1852 static const struct message WmRestoreMDIchildVisibleSeq[] = {
1853 { HCBT_MINMAX, hook },
1854 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1855 { WM_NCCALCSIZE, sent|wparam, 1 },
1856 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1857 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1858 { WM_SIZE, sent|defwinproc },
1860 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1861 { WM_NCCALCSIZE, sent|wparam, 1 },
1862 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1863 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1864 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1867 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1868 static const struct message WmRestoreMDIchildInisibleSeq[] = {
1869 { HCBT_MINMAX, hook },
1870 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1871 { WM_NCCALCSIZE, sent|wparam, 1 },
1872 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1873 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1874 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1875 { WM_SIZE, sent|defwinproc },
1877 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1878 { WM_NCCALCSIZE, sent|wparam, 1 },
1879 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1880 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
1881 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
1885 static HWND mdi_client;
1886 static WNDPROC old_mdi_client_proc;
1888 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1892 /* do not log painting messages */
1893 if (message != WM_PAINT &&
1894 message != WM_ERASEBKGND &&
1895 message != WM_NCPAINT &&
1896 message != WM_NCHITTEST &&
1897 message != WM_GETTEXT &&
1898 message != WM_MDIGETACTIVE)
1900 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1904 case WM_WINDOWPOSCHANGING:
1905 case WM_WINDOWPOSCHANGED:
1907 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1909 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1910 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1911 winpos->hwnd, winpos->hwndInsertAfter,
1912 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1914 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1915 * in the high word for internal purposes
1917 wParam = winpos->flags & 0xffff;
1922 msg.message = message;
1923 msg.flags = sent|wparam|lparam;
1924 msg.wParam = wParam;
1925 msg.lParam = lParam;
1929 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1932 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1934 static long defwndproc_counter = 0;
1938 /* do not log painting messages */
1939 if (message != WM_PAINT &&
1940 message != WM_ERASEBKGND &&
1941 message != WM_NCPAINT &&
1942 message != WM_NCHITTEST &&
1943 message != WM_GETTEXT)
1945 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1949 case WM_WINDOWPOSCHANGING:
1950 case WM_WINDOWPOSCHANGED:
1952 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1954 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1955 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1956 winpos->hwnd, winpos->hwndInsertAfter,
1957 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1959 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1960 * in the high word for internal purposes
1962 wParam = winpos->flags & 0xffff;
1966 case WM_MDIACTIVATE:
1968 HWND active, client = GetParent(hwnd);
1970 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1972 if (hwnd == (HWND)lParam) /* if we are being activated */
1973 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
1975 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
1980 msg.message = message;
1981 msg.flags = sent|wparam|lparam;
1982 if (defwndproc_counter) msg.flags |= defwinproc;
1983 msg.wParam = wParam;
1984 msg.lParam = lParam;
1988 defwndproc_counter++;
1989 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1990 defwndproc_counter--;
1995 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1997 static long defwndproc_counter = 0;
2001 /* do not log painting messages */
2002 if (message != WM_PAINT &&
2003 message != WM_ERASEBKGND &&
2004 message != WM_NCPAINT &&
2005 message != WM_NCHITTEST &&
2006 message != WM_GETTEXT)
2008 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2012 case WM_WINDOWPOSCHANGING:
2013 case WM_WINDOWPOSCHANGED:
2015 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2017 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2018 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2019 winpos->hwnd, winpos->hwndInsertAfter,
2020 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2022 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2023 * in the high word for internal purposes
2025 wParam = winpos->flags & 0xffff;
2030 msg.message = message;
2031 msg.flags = sent|wparam|lparam;
2032 if (defwndproc_counter) msg.flags |= defwinproc;
2033 msg.wParam = wParam;
2034 msg.lParam = lParam;
2038 defwndproc_counter++;
2039 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
2040 defwndproc_counter--;
2045 static BOOL mdi_RegisterWindowClasses(void)
2050 cls.lpfnWndProc = mdi_frame_wnd_proc;
2053 cls.hInstance = GetModuleHandleA(0);
2055 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
2056 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2057 cls.lpszMenuName = NULL;
2058 cls.lpszClassName = "MDI_frame_class";
2059 if (!RegisterClassA(&cls)) return FALSE;
2061 cls.lpfnWndProc = mdi_child_wnd_proc;
2062 cls.lpszClassName = "MDI_child_class";
2063 if (!RegisterClassA(&cls)) return FALSE;
2065 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
2066 old_mdi_client_proc = cls.lpfnWndProc;
2067 cls.hInstance = GetModuleHandleA(0);
2068 cls.lpfnWndProc = mdi_client_hook_proc;
2069 cls.lpszClassName = "MDI_client_class";
2070 if (!RegisterClassA(&cls)) assert(0);
2075 static void test_mdi_messages(void)
2077 MDICREATESTRUCTA mdi_cs;
2078 CLIENTCREATESTRUCT client_cs;
2079 HWND mdi_frame, mdi_child, mdi_child2, active_child;
2081 HMENU hMenu = CreateMenu();
2083 assert(mdi_RegisterWindowClasses());
2087 trace("creating MDI frame window\n");
2088 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
2089 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2090 WS_MAXIMIZEBOX | WS_VISIBLE,
2091 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2092 GetDesktopWindow(), hMenu,
2093 GetModuleHandleA(0), NULL);
2095 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
2097 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2098 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
2100 trace("creating MDI client window\n");
2101 client_cs.hWindowMenu = 0;
2102 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
2103 mdi_client = CreateWindowExA(0, "MDI_client_class",
2105 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
2107 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
2109 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
2111 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2112 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
2114 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2115 ok(!active_child, "wrong active MDI child %p\n", active_child);
2116 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2121 trace("creating invisible MDI child window\n");
2122 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2124 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2125 mdi_client, 0, GetModuleHandleA(0), NULL);
2129 ShowWindow(mdi_child, SW_SHOWNORMAL);
2130 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
2132 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2133 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2135 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2136 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2138 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2139 ok(!active_child, "wrong active MDI child %p\n", active_child);
2140 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2142 ShowWindow(mdi_child, SW_HIDE);
2143 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
2146 ShowWindow(mdi_child, SW_SHOW);
2147 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
2149 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2150 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2152 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2153 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2155 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2156 ok(!active_child, "wrong active MDI child %p\n", active_child);
2157 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2159 DestroyWindow(mdi_child);
2162 trace("creating visible MDI child window\n");
2163 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2164 WS_CHILD | WS_VISIBLE,
2165 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2166 mdi_client, 0, GetModuleHandleA(0), NULL);
2168 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", TRUE);
2170 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2171 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
2173 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2174 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2176 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2177 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2178 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2181 DestroyWindow(mdi_child);
2182 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2184 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2185 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2187 /* Win2k: MDI client still returns a just destroyed child as active
2188 * Win9x: MDI client returns 0
2190 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2191 ok(active_child == mdi_child || /* win2k */
2192 !active_child, /* win9x */
2193 "wrong active MDI child %p\n", active_child);
2194 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2198 trace("creating invisible MDI child window\n");
2199 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2201 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2202 mdi_client, 0, GetModuleHandleA(0), NULL);
2204 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
2206 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
2207 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
2209 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2210 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2212 /* Win2k: MDI client still returns a just destroyed child as active
2213 * Win9x: MDI client returns mdi_child2
2215 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2216 ok(active_child == mdi_child || /* win2k */
2217 active_child == mdi_child2, /* win9x */
2218 "wrong active MDI child %p\n", active_child);
2219 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2222 ShowWindow(mdi_child2, SW_MAXIMIZE);
2223 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
2225 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2226 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2228 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2229 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2230 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2233 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2234 ok(GetFocus() == mdi_child2 || /* win2k */
2235 GetFocus() == 0, /* win9x */
2236 "wrong focus window %p\n", GetFocus());
2241 ShowWindow(mdi_child2, SW_HIDE);
2242 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2244 ShowWindow(mdi_child2, SW_RESTORE);
2245 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
2248 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
2249 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
2251 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2252 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2253 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
2259 ShowWindow(mdi_child2, SW_HIDE);
2260 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2262 ShowWindow(mdi_child2, SW_SHOW);
2263 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
2265 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2266 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2268 ShowWindow(mdi_child2, SW_MAXIMIZE);
2269 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
2271 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2272 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2274 ShowWindow(mdi_child2, SW_RESTORE);
2275 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
2277 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2278 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2283 ShowWindow(mdi_child2, SW_HIDE);
2284 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
2286 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2287 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2289 DestroyWindow(mdi_child2);
2290 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
2292 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2293 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2295 /* test for maximized MDI children */
2296 trace("creating maximized visible MDI child window 1\n");
2297 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2298 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2299 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2300 mdi_client, 0, GetModuleHandleA(0), NULL);
2302 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
2303 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2305 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2306 ok(GetFocus() == mdi_child || /* win2k */
2307 GetFocus() == 0, /* win9x */
2308 "wrong focus window %p\n", GetFocus());
2310 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2311 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2312 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2315 trace("creating maximized visible MDI child window 2\n");
2316 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2317 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2318 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2319 mdi_client, 0, GetModuleHandleA(0), NULL);
2321 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2322 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2323 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2325 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2326 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2328 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2329 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2330 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2333 trace("destroying maximized visible MDI child window 2\n");
2334 DestroyWindow(mdi_child2);
2335 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2337 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2339 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2340 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2342 /* Win2k: MDI client still returns a just destroyed child as active
2343 * Win9x: MDI client returns 0
2345 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2346 ok(active_child == mdi_child2 || /* win2k */
2347 !active_child, /* win9x */
2348 "wrong active MDI child %p\n", active_child);
2351 ShowWindow(mdi_child, SW_MAXIMIZE);
2352 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2355 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2356 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2358 trace("re-creating maximized visible MDI child window 2\n");
2359 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2360 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2361 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2362 mdi_client, 0, GetModuleHandleA(0), NULL);
2364 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2365 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2366 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2368 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2369 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2371 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2372 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2373 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2376 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
2377 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
2378 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
2380 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2381 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2382 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2384 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2385 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2386 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2389 DestroyWindow(mdi_child);
2390 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2392 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2393 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2395 /* Win2k: MDI client still returns a just destroyed child as active
2396 * Win9x: MDI client returns 0
2398 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2399 ok(active_child == mdi_child || /* win2k */
2400 !active_child, /* win9x */
2401 "wrong active MDI child %p\n", active_child);
2403 /* end of test for maximized MDI children */
2405 mdi_cs.szClass = "MDI_child_Class";
2406 mdi_cs.szTitle = "MDI child";
2407 mdi_cs.hOwner = GetModuleHandleA(0);
2410 mdi_cs.cx = CW_USEDEFAULT;
2411 mdi_cs.cy = CW_USEDEFAULT;
2412 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
2414 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
2415 ok(mdi_child != 0, "MDI child creation failed\n");
2416 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
2418 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
2420 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2421 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2423 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
2424 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2425 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2427 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2428 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2429 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2432 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
2433 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
2435 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
2436 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2437 ok(!active_child, "wrong active MDI child %p\n", active_child);
2442 DestroyWindow(mdi_client);
2443 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
2445 DestroyWindow(mdi_frame);
2446 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
2448 /************************* End of MDI test **********************************/
2450 static void test_WM_SETREDRAW(HWND hwnd)
2452 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
2456 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
2457 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
2459 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
2460 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
2463 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
2464 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
2466 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2467 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
2469 /* restore original WS_VISIBLE state */
2470 SetWindowLongA(hwnd, GWL_STYLE, style);
2475 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2479 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2483 case WM_WINDOWPOSCHANGING:
2484 case WM_WINDOWPOSCHANGED:
2486 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
2488 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2489 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2490 winpos->hwnd, winpos->hwndInsertAfter,
2491 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2493 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2494 * in the high word for internal purposes
2496 wParam = winpos->flags & 0xffff;
2501 msg.message = message;
2502 msg.flags = sent|wparam|lparam;
2503 msg.wParam = wParam;
2504 msg.lParam = lParam;
2507 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2508 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2512 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2514 DWORD style, exstyle;
2518 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2519 style = GetWindowLongA(hwnd, GWL_STYLE);
2520 /* do not be confused by WS_DLGFRAME set */
2521 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2523 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2524 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2526 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2527 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2528 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2529 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
2531 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2533 style = GetWindowLongA(hwnd, GWL_STYLE);
2534 if (set) ok(style & set, "style %08lx should be set\n", set);
2535 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2537 /* a subsequent call should do nothing */
2538 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
2539 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2540 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2544 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2545 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax);
2546 ok( ret, "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
2547 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2548 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
2549 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
2552 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2554 DWORD style, exstyle;
2558 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2559 style = GetWindowLongA(hwnd, GWL_STYLE);
2560 /* do not be confused by WS_DLGFRAME set */
2561 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2563 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2564 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2566 si.cbSize = sizeof(si);
2567 si.fMask = SIF_RANGE;
2570 SetScrollInfo(hwnd, ctl, &si, TRUE);
2571 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2572 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
2574 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2576 style = GetWindowLongA(hwnd, GWL_STYLE);
2577 if (set) ok(style & set, "style %08lx should be set\n", set);
2578 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2580 /* a subsequent call should do nothing */
2581 SetScrollInfo(hwnd, ctl, &si, TRUE);
2582 if (style & WS_HSCROLL)
2583 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2584 else if (style & WS_VSCROLL)
2585 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2587 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2589 si.fMask = SIF_PAGE;
2591 SetScrollInfo(hwnd, ctl, &si, FALSE);
2592 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2596 SetScrollInfo(hwnd, ctl, &si, FALSE);
2597 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
2599 si.fMask = SIF_RANGE;
2600 si.nMin = 0xdeadbeef;
2601 si.nMax = 0xdeadbeef;
2602 ret = GetScrollInfo(hwnd, ctl, &si);
2603 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2604 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
2605 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
2606 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
2609 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2610 static void test_scroll_messages(HWND hwnd)
2618 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2619 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2620 if (sequence->message != WmGetScrollRangeSeq[0].message)
2621 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2622 /* values of min and max are undefined */
2625 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE);
2626 ok( ret, "SetScrollRange error %ld\n", GetLastError());
2627 if (sequence->message != WmSetScrollRangeSeq[0].message)
2628 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2633 ret = GetScrollRange(hwnd, SB_CTL, &min, &max);
2634 ok( ret, "GetScrollRange error %ld\n", GetLastError());
2635 if (sequence->message != WmGetScrollRangeSeq[0].message)
2636 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2637 /* values of min and max are undefined */
2640 si.cbSize = sizeof(si);
2641 si.fMask = SIF_RANGE;
2644 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2645 if (sequence->message != WmSetScrollRangeSeq[0].message)
2646 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2649 si.fMask = SIF_PAGE;
2651 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2652 if (sequence->message != WmSetScrollRangeSeq[0].message)
2653 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2658 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2659 if (sequence->message != WmSetScrollRangeSeq[0].message)
2660 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2663 si.fMask = SIF_RANGE;
2664 si.nMin = 0xdeadbeef;
2665 si.nMax = 0xdeadbeef;
2666 ret = GetScrollInfo(hwnd, SB_CTL, &si);
2667 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
2668 if (sequence->message != WmGetScrollInfoSeq[0].message)
2669 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2670 /* values of min and max are undefined */
2673 /* set WS_HSCROLL */
2674 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2675 /* clear WS_HSCROLL */
2676 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2678 /* set WS_HSCROLL */
2679 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2680 /* clear WS_HSCROLL */
2681 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2683 /* set WS_VSCROLL */
2684 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2685 /* clear WS_VSCROLL */
2686 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2688 /* set WS_VSCROLL */
2689 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2690 /* clear WS_VSCROLL */
2691 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2694 static void test_showwindow(void)
2698 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2699 100, 100, 200, 200, 0, 0, 0, NULL);
2700 ok (hwnd != 0, "Failed to create overlapped window\n");
2701 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2702 0, 0, 10, 10, hwnd, 0, 0, NULL);
2703 ok (hchild != 0, "Failed to create child\n");
2706 /* ShowWindow( SW_SHOWNA) for invisible top level window */
2707 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
2708 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2709 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window.\n", TRUE);
2712 /* ShowWindow( SW_SHOWNA) for now visible top level window */
2713 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
2714 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2715 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window.\n", FALSE);
2717 /* back to invisible */
2718 ShowWindow(hchild, SW_HIDE);
2719 ShowWindow(hwnd, SW_HIDE);
2721 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
2722 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
2723 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2724 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent\n", TRUE);
2726 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
2727 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
2729 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
2730 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2731 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent\n", TRUE);
2733 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
2734 ShowWindow( hwnd, SW_SHOW);
2736 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
2737 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
2738 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent\n", FALSE);
2741 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
2742 ShowWindow( hchild, SW_HIDE);
2744 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
2745 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
2746 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent\n", FALSE);
2749 DestroyWindow(hchild);
2750 DestroyWindow(hwnd);
2754 /* test if we receive the right sequence of messages */
2755 static void test_messages(void)
2757 HWND hwnd, hparent, hchild;
2758 HWND hchild2, hbutton;
2764 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2765 100, 100, 200, 200, 0, 0, 0, NULL);
2766 ok (hwnd != 0, "Failed to create overlapped window\n");
2767 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2769 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2770 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
2771 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
2773 /* test WM_SETREDRAW on a not visible top level window */
2774 test_WM_SETREDRAW(hwnd);
2776 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2777 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
2778 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
2780 ok(GetActiveWindow() == hwnd, "window should be active\n");
2781 ok(GetFocus() == hwnd, "window should have input focus\n");
2782 ShowWindow(hwnd, SW_HIDE);
2783 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
2785 ShowWindow(hwnd, SW_SHOW);
2786 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
2788 ok(GetActiveWindow() == hwnd, "window should be active\n");
2789 ok(GetFocus() == hwnd, "window should have input focus\n");
2790 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2791 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
2792 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
2794 /* test WM_SETREDRAW on a visible top level window */
2795 ShowWindow(hwnd, SW_SHOW);
2796 test_WM_SETREDRAW(hwnd);
2798 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
2799 test_scroll_messages(hwnd);
2801 DestroyWindow(hwnd);
2802 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
2804 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2805 100, 100, 200, 200, 0, 0, 0, NULL);
2806 ok (hparent != 0, "Failed to create parent window\n");
2809 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
2810 0, 0, 10, 10, hparent, 0, 0, NULL);
2811 ok (hchild != 0, "Failed to create child window\n");
2812 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
2813 DestroyWindow(hchild);
2816 /* visible child window with a caption */
2817 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
2818 WS_CHILD | WS_VISIBLE | WS_CAPTION,
2819 0, 0, 10, 10, hparent, 0, 0, NULL);
2820 ok (hchild != 0, "Failed to create child window\n");
2821 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
2823 trace("testing scroll APIs on a visible child window %p\n", hchild);
2824 test_scroll_messages(hchild);
2826 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2827 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
2829 DestroyWindow(hchild);
2832 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2833 0, 0, 10, 10, hparent, 0, 0, NULL);
2834 ok (hchild != 0, "Failed to create child window\n");
2835 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2837 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
2838 100, 100, 50, 50, hparent, 0, 0, NULL);
2839 ok (hchild2 != 0, "Failed to create child2 window\n");
2842 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
2843 0, 100, 50, 50, hchild, 0, 0, NULL);
2844 ok (hbutton != 0, "Failed to create button window\n");
2846 /* test WM_SETREDRAW on a not visible child window */
2847 test_WM_SETREDRAW(hchild);
2849 ShowWindow(hchild, SW_SHOW);
2850 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2852 ShowWindow(hchild, SW_HIDE);
2853 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
2855 ShowWindow(hchild, SW_SHOW);
2856 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2858 /* test WM_SETREDRAW on a visible child window */
2859 test_WM_SETREDRAW(hchild);
2861 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
2862 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
2864 ShowWindow(hchild, SW_HIDE);
2866 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2867 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
2869 ShowWindow(hchild, SW_HIDE);
2871 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2872 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
2874 /* DestroyWindow sequence below expects that a child has focus */
2878 DestroyWindow(hchild);
2879 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
2880 DestroyWindow(hchild2);
2881 DestroyWindow(hbutton);
2884 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
2885 0, 0, 100, 100, hparent, 0, 0, NULL);
2886 ok (hchild != 0, "Failed to create child popup window\n");
2887 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
2888 DestroyWindow(hchild);
2890 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
2892 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
2893 0, 0, 100, 100, hparent, 0, 0, NULL);
2894 ok (hchild != 0, "Failed to create popup window\n");
2895 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2896 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2897 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2899 ShowWindow(hchild, SW_SHOW);
2900 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2902 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2903 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2905 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2906 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
2907 DestroyWindow(hchild);
2909 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2910 * changes nothing in message sequences.
2913 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
2914 0, 0, 100, 100, hparent, 0, 0, NULL);
2915 ok (hchild != 0, "Failed to create popup window\n");
2916 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2917 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2918 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2920 ShowWindow(hchild, SW_SHOW);
2921 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2923 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2924 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2925 DestroyWindow(hchild);
2928 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
2929 0, 0, 100, 100, hparent, 0, 0, NULL);
2930 ok(hwnd != 0, "Failed to create custom dialog window\n");
2931 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
2934 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
2935 test_scroll_messages(hwnd);
2939 after_end_dialog = 1;
2940 EndDialog( hwnd, 0 );
2941 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
2943 DestroyWindow(hwnd);
2944 after_end_dialog = 0;
2946 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP,
2947 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
2948 ok(hwnd != 0, "Failed to create custom dialog window\n");
2950 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
2951 ShowWindow(hwnd, SW_SHOW);
2952 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
2953 DestroyWindow(hwnd);
2956 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
2957 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
2959 /* test showing child with hidden parent */
2960 ShowWindow( hparent, SW_HIDE );
2963 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2964 0, 0, 10, 10, hparent, 0, 0, NULL);
2965 ok (hchild != 0, "Failed to create child window\n");
2966 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2968 ShowWindow( hchild, SW_SHOW );
2969 ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", TRUE);
2970 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2971 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2973 ShowWindow( hchild, SW_HIDE );
2974 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", TRUE);
2975 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
2976 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2978 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2979 ok_sequence(WmShowChildInvisibleParentSeq_2, "SetWindowPos:show child with invisible parent", FALSE);
2980 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2981 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2983 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2984 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE);
2985 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
2986 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2988 DestroyWindow(hchild);
2989 DestroyWindow(hparent);
2992 /* Message sequence for SetMenu */
2993 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
2994 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
2996 hmenu = CreateMenu();
2997 ok (hmenu != 0, "Failed to create menu\n");
2998 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
2999 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3000 100, 100, 200, 200, 0, hmenu, 0, NULL);
3001 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
3002 ok (SetMenu(hwnd, 0), "SetMenu\n");
3003 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
3004 ok (SetMenu(hwnd, 0), "SetMenu\n");
3005 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
3006 ShowWindow(hwnd, SW_SHOW);
3008 ok (SetMenu(hwnd, 0), "SetMenu\n");
3009 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
3010 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
3011 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
3013 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
3014 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
3016 DestroyWindow(hwnd);
3019 /* Message sequence for EnableWindow */
3020 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3021 100, 100, 200, 200, 0, 0, 0, NULL);
3022 ok (hparent != 0, "Failed to create parent window\n");
3023 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
3024 0, 0, 10, 10, hparent, 0, 0, NULL);
3025 ok (hchild != 0, "Failed to create child window\n");
3030 EnableWindow(hparent, FALSE);
3031 ok_sequence(WmEnableWindowSeq, "EnableWindow", FALSE);
3033 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3036 /* the following test causes an exception in user.exe under win9x */
3037 if (!PostMessageW( hparent, WM_USER, 0, 0 )) return;
3038 PostMessageW( hparent, WM_USER+1, 0, 0 );
3039 /* PeekMessage(NULL) fails, but still removes the message */
3040 SetLastError(0xdeadbeef);
3041 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
3042 ok( GetLastError() == ERROR_NOACCESS, "last error is %ld\n", GetLastError() );
3043 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
3044 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
3046 DestroyWindow(hchild);
3047 DestroyWindow(hparent);
3053 /****************** button message test *************************/
3054 static const struct message WmSetFocusButtonSeq[] =
3056 { HCBT_SETFOCUS, hook },
3057 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3058 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3059 { WM_SETFOCUS, sent|wparam, 0 },
3060 { WM_CTLCOLORBTN, sent|defwinproc },
3063 static const struct message WmKillFocusButtonSeq[] =
3065 { HCBT_SETFOCUS, hook },
3066 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3067 { WM_KILLFOCUS, sent|wparam, 0 },
3068 { WM_CTLCOLORBTN, sent|defwinproc },
3069 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3072 static const struct message WmSetFocusStaticSeq[] =
3074 { HCBT_SETFOCUS, hook },
3075 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
3076 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3077 { WM_SETFOCUS, sent|wparam, 0 },
3078 { WM_CTLCOLORSTATIC, sent|defwinproc },
3081 static const struct message WmKillFocusStaticSeq[] =
3083 { HCBT_SETFOCUS, hook },
3084 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3085 { WM_KILLFOCUS, sent|wparam, 0 },
3086 { WM_CTLCOLORSTATIC, sent|defwinproc },
3087 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
3090 static const struct message WmLButtonDownSeq[] =
3092 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
3093 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
3094 { HCBT_SETFOCUS, hook },
3095 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
3096 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3097 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
3098 { WM_CTLCOLORBTN, sent|defwinproc },
3099 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
3100 { WM_CTLCOLORBTN, sent|defwinproc },
3101 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3104 static const struct message WmLButtonUpSeq[] =
3106 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
3107 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
3108 { WM_CTLCOLORBTN, sent|defwinproc },
3109 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3110 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
3111 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
3115 static WNDPROC old_button_proc;
3117 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3119 static long defwndproc_counter = 0;
3123 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3125 msg.message = message;
3126 msg.flags = sent|wparam|lparam;
3127 if (defwndproc_counter) msg.flags |= defwinproc;
3128 msg.wParam = wParam;
3129 msg.lParam = lParam;
3132 if (message == BM_SETSTATE)
3133 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
3135 defwndproc_counter++;
3136 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
3137 defwndproc_counter--;
3142 static void subclass_button(void)
3146 if (!GetClassInfoA(0, "button", &cls)) assert(0);
3148 old_button_proc = cls.lpfnWndProc;
3150 cls.hInstance = GetModuleHandle(0);
3151 cls.lpfnWndProc = button_hook_proc;
3152 cls.lpszClassName = "my_button_class";
3153 if (!RegisterClassA(&cls)) assert(0);
3156 static void test_button_messages(void)
3162 const struct message *setfocus;
3163 const struct message *killfocus;
3165 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3166 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3167 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
3168 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3169 { BS_CHECKBOX, DLGC_BUTTON,
3170 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3171 { BS_AUTOCHECKBOX, DLGC_BUTTON,
3172 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3173 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3174 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3175 { BS_3STATE, DLGC_BUTTON,
3176 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3177 { BS_AUTO3STATE, DLGC_BUTTON,
3178 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3179 { BS_GROUPBOX, DLGC_STATIC,
3180 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3181 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
3182 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
3183 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
3184 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
3185 { BS_OWNERDRAW, DLGC_BUTTON,
3186 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
3194 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
3196 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
3197 0, 0, 50, 14, 0, 0, 0, NULL);
3198 ok(hwnd != 0, "Failed to create button window\n");
3200 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
3201 ok(dlg_code == button[i].dlg_code, "%d: wrong dlg_code %08lx\n", i, dlg_code);
3203 ShowWindow(hwnd, SW_SHOW);
3208 trace("button style %08lx\n", button[i].style);
3210 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
3213 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
3215 DestroyWindow(hwnd);
3218 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
3219 0, 0, 50, 14, 0, 0, 0, NULL);
3220 ok(hwnd != 0, "Failed to create button window\n");
3225 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
3226 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
3228 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
3229 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONUP on a button", FALSE);
3230 DestroyWindow(hwnd);
3233 /************* painting message test ********************/
3235 static void dump_region(HRGN hrgn)
3238 RGNDATA *data = NULL;
3243 printf( "null region\n" );
3246 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
3247 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
3248 GetRegionData( hrgn, size, data );
3249 printf("%ld rects:", data->rdh.nCount );
3250 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
3251 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
3253 HeapFree( GetProcessHeap(), 0, data );
3256 static void check_update_rgn( HWND hwnd, HRGN hrgn )
3260 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
3261 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
3263 ret = GetUpdateRgn( hwnd, update, FALSE );
3264 ok( ret != ERROR, "GetUpdateRgn failed\n" );
3265 if (ret == NULLREGION)
3267 ok( !hrgn, "Update region shouldn't be empty\n" );
3271 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
3273 ok( 0, "Regions are different\n" );
3274 if (winetest_debug > 0)
3276 printf( "Update region: " );
3277 dump_region( update );
3278 printf( "Wanted region: " );
3279 dump_region( hrgn );
3283 GetRgnBox( update, &r1 );
3284 GetUpdateRect( hwnd, &r2, FALSE );
3285 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
3286 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
3287 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
3289 DeleteObject( tmp );
3290 DeleteObject( update );
3293 static const struct message WmInvalidateRgn[] = {
3294 { WM_NCPAINT, sent },
3295 { WM_GETTEXT, sent|defwinproc|optional },
3299 static const struct message WmGetUpdateRect[] = {
3300 { WM_NCPAINT, sent },
3301 { WM_GETTEXT, sent|defwinproc|optional },
3306 static const struct message WmInvalidateFull[] = {
3307 { WM_NCPAINT, sent|wparam, 1 },
3308 { WM_GETTEXT, sent|defwinproc|optional },
3312 static const struct message WmInvalidateErase[] = {
3313 { WM_NCPAINT, sent|wparam, 1 },
3314 { WM_GETTEXT, sent|defwinproc|optional },
3315 { WM_ERASEBKGND, sent },
3319 static const struct message WmInvalidatePaint[] = {
3321 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3322 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3326 static const struct message WmInvalidateErasePaint[] = {
3328 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
3329 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3330 { WM_ERASEBKGND, sent|beginpaint },
3334 static const struct message WmInvalidateErasePaint2[] = {
3336 { WM_NCPAINT, sent|beginpaint },
3337 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3338 { WM_ERASEBKGND, sent|beginpaint },
3342 static const struct message WmErase[] = {
3343 { WM_ERASEBKGND, sent },
3347 static const struct message WmPaint[] = {
3352 static const struct message WmParentOnlyPaint[] = {
3353 { WM_PAINT, sent|parent },
3357 static const struct message WmInvalidateParent[] = {
3358 { WM_NCPAINT, sent|parent },
3359 { WM_GETTEXT, sent|defwinproc|parent|optional },
3360 { WM_ERASEBKGND, sent|parent },
3364 static const struct message WmInvalidateParentChild[] = {
3365 { WM_NCPAINT, sent|parent },
3366 { WM_GETTEXT, sent|defwinproc|parent|optional },
3367 { WM_ERASEBKGND, sent|parent },
3368 { WM_NCPAINT, sent },
3369 { WM_GETTEXT, sent|defwinproc|optional },
3370 { WM_ERASEBKGND, sent },
3374 static const struct message WmInvalidateParentChild2[] = {
3375 { WM_ERASEBKGND, sent|parent },
3376 { WM_NCPAINT, sent },
3377 { WM_GETTEXT, sent|defwinproc|optional },
3378 { WM_ERASEBKGND, sent },
3382 static const struct message WmParentPaint[] = {
3383 { WM_PAINT, sent|parent },
3388 static const struct message WmParentPaintNc[] = {
3389 { WM_PAINT, sent|parent },
3391 { WM_NCPAINT, sent|beginpaint },
3392 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3393 { WM_ERASEBKGND, sent|beginpaint },
3397 static const struct message WmChildPaintNc[] = {
3399 { WM_NCPAINT, sent|beginpaint },
3400 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3401 { WM_ERASEBKGND, sent|beginpaint },
3405 static const struct message WmParentErasePaint[] = {
3406 { WM_PAINT, sent|parent },
3407 { WM_NCPAINT, sent|parent|beginpaint },
3408 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3409 { WM_ERASEBKGND, sent|parent|beginpaint },
3411 { WM_NCPAINT, sent|beginpaint },
3412 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
3413 { WM_ERASEBKGND, sent|beginpaint },
3417 static const struct message WmParentOnlyNcPaint[] = {
3418 { WM_PAINT, sent|parent },
3419 { WM_NCPAINT, sent|parent|beginpaint },
3420 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
3424 static const struct message WmSetParentStyle[] = {
3425 { WM_STYLECHANGING, sent|parent },
3426 { WM_STYLECHANGED, sent|parent },
3430 static void test_paint_messages(void)
3435 HWND hparent, hchild;
3436 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
3437 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
3438 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
3439 100, 100, 200, 200, 0, 0, 0, NULL);
3440 ok (hwnd != 0, "Failed to create overlapped window\n");
3442 ShowWindow( hwnd, SW_SHOW );
3443 UpdateWindow( hwnd );
3445 /* try to flush pending X expose events */
3446 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3447 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3449 check_update_rgn( hwnd, 0 );
3450 SetRectRgn( hrgn, 10, 10, 20, 20 );
3451 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3452 check_update_rgn( hwnd, hrgn );
3453 SetRectRgn( hrgn2, 20, 20, 30, 30 );
3454 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
3455 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
3456 check_update_rgn( hwnd, hrgn );
3457 /* validate everything */
3458 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3459 check_update_rgn( hwnd, 0 );
3460 /* now with frame */
3461 SetRectRgn( hrgn, -5, -5, 20, 20 );
3463 /* flush pending messages */
3464 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3467 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3468 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3470 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
3471 check_update_rgn( hwnd, hrgn );
3474 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3475 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3478 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3479 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
3481 GetClientRect( hwnd, &rect );
3482 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
3483 check_update_rgn( hwnd, hrgn );
3486 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
3487 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3490 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
3491 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
3492 check_update_rgn( hwnd, 0 );
3495 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
3496 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
3497 check_update_rgn( hwnd, 0 );
3500 SetRectRgn( hrgn, 0, 0, 100, 100 );
3501 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3502 SetRectRgn( hrgn, 0, 0, 50, 100 );
3503 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
3504 SetRectRgn( hrgn, 50, 0, 100, 100 );
3505 check_update_rgn( hwnd, hrgn );
3506 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3507 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
3508 check_update_rgn( hwnd, 0 );
3511 SetRectRgn( hrgn, 0, 0, 100, 100 );
3512 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3513 SetRectRgn( hrgn, 0, 0, 100, 50 );
3514 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3515 ok_sequence( WmErase, "Erase", FALSE );
3516 SetRectRgn( hrgn, 0, 50, 100, 100 );
3517 check_update_rgn( hwnd, hrgn );
3520 SetRectRgn( hrgn, 0, 0, 100, 100 );
3521 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3522 SetRectRgn( hrgn, 0, 0, 50, 50 );
3523 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
3524 ok_sequence( WmPaint, "Paint", FALSE );
3527 SetRectRgn( hrgn, -4, -4, -2, -2 );
3528 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3529 SetRectRgn( hrgn, -200, -200, -198, -198 );
3530 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
3531 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3534 SetRectRgn( hrgn, -4, -4, -2, -2 );
3535 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3536 SetRectRgn( hrgn, -4, -4, -3, -3 );
3537 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
3538 SetRectRgn( hrgn, 0, 0, 1, 1 );
3539 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
3540 ok_sequence( WmPaint, "Paint", FALSE );
3543 SetRectRgn( hrgn, -4, -4, -1, -1 );
3544 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3545 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
3546 /* make sure no WM_PAINT was generated */
3547 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3548 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3551 SetRectRgn( hrgn, -4, -4, -1, -1 );
3552 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3553 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
3555 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
3557 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
3558 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
3559 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
3560 ret = GetUpdateRect( hwnd, &rect, FALSE );
3561 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
3562 /* this will send WM_NCPAINT and validate the non client area */
3563 ret = GetUpdateRect( hwnd, &rect, TRUE );
3564 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
3566 DispatchMessage( &msg );
3568 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
3570 DestroyWindow( hwnd );
3572 /* now test with a child window */
3574 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
3575 100, 100, 200, 200, 0, 0, 0, NULL);
3576 ok (hparent != 0, "Failed to create parent window\n");
3578 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
3579 10, 10, 100, 100, hparent, 0, 0, NULL);
3580 ok (hchild != 0, "Failed to create child window\n");
3582 ShowWindow( hparent, SW_SHOW );
3583 UpdateWindow( hparent );
3584 UpdateWindow( hchild );
3585 /* try to flush pending X expose events */
3586 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3587 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3590 log_all_parent_messages++;
3592 SetRect( &rect, 0, 0, 50, 50 );
3593 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3594 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3595 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
3597 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3599 MapWindowPoints( hchild, hparent, &pt, 1 );
3600 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
3601 check_update_rgn( hchild, hrgn );
3602 SetRectRgn( hrgn, 0, 0, 50, 50 );
3603 check_update_rgn( hparent, hrgn );
3604 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3605 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
3606 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3607 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3609 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3610 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
3612 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3613 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3614 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
3615 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3616 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3618 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
3619 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3620 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
3622 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3624 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3625 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3626 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
3628 /* flush all paint messages */
3629 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3632 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
3633 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3634 SetRectRgn( hrgn, 0, 0, 50, 50 );
3635 check_update_rgn( hparent, hrgn );
3636 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3637 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3638 SetRectRgn( hrgn, 0, 0, 50, 50 );
3639 check_update_rgn( hparent, hrgn );
3641 /* flush all paint messages */
3642 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3643 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3646 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
3647 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3648 SetRectRgn( hrgn, 0, 0, 50, 50 );
3649 check_update_rgn( hparent, hrgn );
3650 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3651 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3652 SetRectRgn( hrgn2, 10, 10, 50, 50 );
3653 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
3654 check_update_rgn( hparent, hrgn );
3655 /* flush all paint messages */
3656 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3659 /* same as above but parent gets completely validated */
3660 SetRect( &rect, 20, 20, 30, 30 );
3661 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3662 SetRectRgn( hrgn, 20, 20, 30, 30 );
3663 check_update_rgn( hparent, hrgn );
3664 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3665 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3666 check_update_rgn( hparent, 0 ); /* no update region */
3667 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3668 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
3670 /* make sure RDW_VALIDATE on child doesn't have the same effect */
3672 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3673 SetRectRgn( hrgn, 20, 20, 30, 30 );
3674 check_update_rgn( hparent, hrgn );
3675 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
3676 SetRectRgn( hrgn, 20, 20, 30, 30 );
3677 check_update_rgn( hparent, hrgn );
3679 /* same as above but normal WM_PAINT doesn't validate parent */
3681 SetRect( &rect, 20, 20, 30, 30 );
3682 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3683 SetRectRgn( hrgn, 20, 20, 30, 30 );
3684 check_update_rgn( hparent, hrgn );
3685 /* no WM_PAINT in child while parent still pending */
3686 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3687 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3688 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3689 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
3692 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3693 /* no WM_PAINT in child while parent still pending */
3694 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3695 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3696 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
3697 /* now that parent is valid child should get WM_PAINT */
3698 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3699 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3700 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3701 ok_sequence( WmEmptySeq, "No other message", FALSE );
3703 /* same thing with WS_CLIPCHILDREN in parent */
3705 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3706 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3707 /* changing style invalidates non client area, but we need to invalidate something else to see it */
3708 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
3709 ok_sequence( WmEmptySeq, "No message", FALSE );
3710 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
3711 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
3714 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
3715 SetRectRgn( hrgn, 20, 20, 30, 30 );
3716 check_update_rgn( hparent, hrgn );
3717 /* no WM_PAINT in child while parent still pending */
3718 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3719 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3720 /* WM_PAINT in parent first */
3721 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3722 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
3724 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
3726 SetRect( &rect, 0, 0, 30, 30 );
3727 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
3728 SetRectRgn( hrgn, 0, 0, 30, 30 );
3729 check_update_rgn( hparent, hrgn );
3730 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3731 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
3733 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3735 SetRect( &rect, -10, 0, 30, 30 );
3736 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3737 SetRect( &rect, 0, 0, 20, 20 );
3738 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3739 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3740 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
3742 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3744 SetRect( &rect, -10, 0, 30, 30 );
3745 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3746 SetRect( &rect, 0, 0, 100, 100 );
3747 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3748 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3749 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
3750 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3751 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
3753 /* test RDW_INTERNALPAINT behavior */
3756 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
3757 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3758 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3760 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
3761 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3762 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3764 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3765 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3766 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3768 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3769 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3770 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3771 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3772 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3774 log_all_parent_messages--;
3775 DestroyWindow( hparent );
3777 DeleteObject( hrgn );
3778 DeleteObject( hrgn2 );
3787 static DWORD WINAPI thread_proc(void *param)
3790 struct wnd_event *wnd_event = (struct wnd_event *)param;
3792 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
3793 100, 100, 200, 200, 0, 0, 0, NULL);
3794 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
3796 SetEvent(wnd_event->event);
3798 while (GetMessage(&msg, 0, 0, 0))
3800 TranslateMessage(&msg);
3801 DispatchMessage(&msg);
3804 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
3809 static void test_interthread_messages(void)
3816 int len, expected_len;
3817 struct wnd_event wnd_event;
3820 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
3821 if (!wnd_event.event)
3823 trace("skipping interthread message test under win9x\n");
3827 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
3828 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
3830 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3832 CloseHandle(wnd_event.event);
3834 SetLastError(0xdeadbeef);
3835 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
3836 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
3838 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3839 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
3841 expected_len = lstrlenA("window caption text");
3842 memset(buf, 0, sizeof(buf));
3843 SetLastError(0xdeadbeef);
3844 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
3845 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
3846 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
3848 msg.hwnd = wnd_event.hwnd;
3849 msg.message = WM_GETTEXT;
3850 msg.wParam = sizeof(buf);
3851 msg.lParam = (LPARAM)buf;
3852 memset(buf, 0, sizeof(buf));
3853 SetLastError(0xdeadbeef);
3854 len = DispatchMessageA(&msg);
3855 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3856 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
3858 /* the following test causes an exception in user.exe under win9x */
3859 msg.hwnd = wnd_event.hwnd;
3860 msg.message = WM_TIMER;
3862 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3863 SetLastError(0xdeadbeef);
3864 len = DispatchMessageA(&msg);
3865 ok(!len && GetLastError() == 0xdeadbeef,
3866 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
3868 ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0);
3869 ok( ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
3871 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3872 CloseHandle(hThread);
3874 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
3878 static const struct message WmVkN[] = {
3879 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3880 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3881 { WM_CHAR, wparam|lparam, 'n', 1 },
3882 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
3883 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3884 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3887 static const struct message WmShiftVkN[] = {
3888 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
3889 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
3890 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3891 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3892 { WM_CHAR, wparam|lparam, 'N', 1 },
3893 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
3894 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3895 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3896 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
3897 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
3900 static const struct message WmCtrlVkN[] = {
3901 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3902 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3903 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3904 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3905 { WM_CHAR, wparam|lparam, 0x000e, 1 },
3906 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3907 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3908 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3909 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3910 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3913 static const struct message WmCtrlVkN_2[] = {
3914 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3915 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3916 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3917 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3918 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3919 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3920 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3921 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3924 static const struct message WmAltVkN[] = {
3925 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3926 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3927 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3928 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3929 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
3930 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
3931 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
3932 { HCBT_SYSCOMMAND, hook },
3933 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
3934 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
3935 { WM_INITMENU, sent|defwinproc },
3936 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
3937 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
3938 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
3939 { WM_CAPTURECHANGED, sent|defwinproc },
3940 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
3941 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
3942 { WM_EXITMENULOOP, sent|defwinproc },
3943 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
3944 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
3945 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3946 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3947 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3948 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3951 static const struct message WmAltVkN_2[] = {
3952 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3953 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3954 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3955 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
3956 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3957 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3958 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3959 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3962 static const struct message WmCtrlAltVkN[] = {
3963 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3964 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3965 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3966 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3967 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
3968 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3969 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
3970 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3971 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3972 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3973 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3974 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3977 static const struct message WmAltPressRelease[] = {
3978 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3979 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3980 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3981 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3982 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 },
3983 { HCBT_SYSCOMMAND, hook },
3984 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
3985 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
3986 { WM_INITMENU, sent|defwinproc },
3987 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
3988 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE) },
3989 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
3991 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
3992 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
3993 { WM_CAPTURECHANGED, sent|defwinproc },
3994 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) },
3995 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
3996 { WM_EXITMENULOOP, sent|defwinproc },
3997 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3998 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4001 static const struct message WmAltMouseButton[] = {
4002 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
4003 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
4004 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
4005 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
4006 { WM_LBUTTONDOWN, wparam, MK_LBUTTON, 0 },
4007 { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON, 0 },
4008 { WM_LBUTTONUP, wparam, 0, 0 },
4009 { WM_LBUTTONUP, sent|wparam, 0, 0 },
4010 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
4011 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
4015 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
4019 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
4021 struct message log_msg;
4023 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
4025 /* ignore some unwanted messages */
4026 if (msg.message == WM_MOUSEMOVE)
4029 log_msg.message = msg.message;
4030 log_msg.flags = wparam|lparam;
4031 log_msg.wParam = msg.wParam;
4032 log_msg.lParam = msg.lParam;
4033 add_message(&log_msg);
4035 if (!hAccel || !TranslateAccelerator(hwnd, hAccel, &msg))
4037 TranslateMessage(&msg);
4038 DispatchMessage(&msg);
4043 static void test_accelerators(void)
4048 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4049 100, 100, 200, 200, 0, 0, 0, NULL);
4055 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
4057 state = GetKeyState(VK_SHIFT);
4058 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
4059 state = GetKeyState(VK_CAPITAL);
4060 ok(state == 0, "wrong CapsLock state %04x\n", state);
4062 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
4063 assert(hAccel != 0);
4065 pump_msg_loop(hwnd, 0);
4068 trace("testing VK_N press/release\n");
4070 keybd_event('N', 0, 0, 0);
4071 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4072 pump_msg_loop(hwnd, hAccel);
4073 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4075 trace("testing Shift+VK_N press/release\n");
4077 keybd_event(VK_SHIFT, 0, 0, 0);
4078 keybd_event('N', 0, 0, 0);
4079 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4080 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4081 pump_msg_loop(hwnd, hAccel);
4082 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4084 trace("testing Ctrl+VK_N press/release\n");
4086 keybd_event(VK_CONTROL, 0, 0, 0);
4087 keybd_event('N', 0, 0, 0);
4088 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4089 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4090 pump_msg_loop(hwnd, hAccel);
4091 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
4093 trace("testing Alt+VK_N press/release\n");
4095 keybd_event(VK_MENU, 0, 0, 0);
4096 keybd_event('N', 0, 0, 0);
4097 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4098 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4099 pump_msg_loop(hwnd, hAccel);
4100 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
4102 trace("testing Ctrl+Alt+VK_N press/release\n");
4104 keybd_event(VK_CONTROL, 0, 0, 0);
4105 keybd_event(VK_MENU, 0, 0, 0);
4106 keybd_event('N', 0, 0, 0);
4107 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4108 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4109 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4110 pump_msg_loop(hwnd, hAccel);
4111 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
4113 ret = DestroyAcceleratorTable(hAccel);
4114 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4116 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
4117 assert(hAccel != 0);
4119 trace("testing VK_N press/release\n");
4121 keybd_event('N', 0, 0, 0);
4122 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4123 pump_msg_loop(hwnd, hAccel);
4124 ok_sequence(WmVkN, "VK_N press/release", FALSE);
4126 trace("testing Shift+VK_N press/release\n");
4128 keybd_event(VK_SHIFT, 0, 0, 0);
4129 keybd_event('N', 0, 0, 0);
4130 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4131 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
4132 pump_msg_loop(hwnd, hAccel);
4133 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
4135 trace("testing Ctrl+VK_N press/release 2\n");
4137 keybd_event(VK_CONTROL, 0, 0, 0);
4138 keybd_event('N', 0, 0, 0);
4139 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4140 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4141 pump_msg_loop(hwnd, hAccel);
4142 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
4144 trace("testing Alt+VK_N press/release 2\n");
4146 keybd_event(VK_MENU, 0, 0, 0);
4147 keybd_event('N', 0, 0, 0);
4148 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4149 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4150 pump_msg_loop(hwnd, hAccel);
4151 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
4153 trace("testing Ctrl+Alt+VK_N press/release\n");
4155 keybd_event(VK_CONTROL, 0, 0, 0);
4156 keybd_event(VK_MENU, 0, 0, 0);
4157 keybd_event('N', 0, 0, 0);
4158 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
4159 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4160 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
4161 pump_msg_loop(hwnd, hAccel);
4162 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
4164 ret = DestroyAcceleratorTable(hAccel);
4165 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
4167 trace("testing Alt press/release\n");
4169 keybd_event(VK_MENU, 0, 0, 0);
4170 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4171 keybd_event(VK_MENU, 0, 0, 0);
4172 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4173 pump_msg_loop(hwnd, 0);
4174 /* this test doesn't pass in Wine for managed windows */
4175 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
4177 trace("testing Alt+MouseButton press/release\n");
4178 /* first, move mouse pointer inside of the window client area */
4179 GetClientRect(hwnd, &rc);
4180 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
4181 rc.left += (rc.right - rc.left)/2;
4182 rc.top += (rc.bottom - rc.top)/2;
4183 SetCursorPos(rc.left, rc.top);
4185 pump_msg_loop(hwnd, 0);
4187 keybd_event(VK_MENU, 0, 0, 0);
4188 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
4189 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
4190 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
4191 pump_msg_loop(hwnd, 0);
4192 ok_sequence(WmAltMouseButton, "Alt+MouseButton press/release", FALSE);
4194 DestroyWindow(hwnd);
4197 /************* window procedures ********************/
4199 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4201 static long defwndproc_counter = 0;
4202 static long beginpaint_counter = 0;
4206 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4210 /* test_accelerators() depends on this */
4219 case WM_WINDOWPOSCHANGING:
4220 case WM_WINDOWPOSCHANGED:
4222 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4224 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4225 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4226 winpos->hwnd, winpos->hwndInsertAfter,
4227 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4229 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4230 * in the high word for internal purposes
4232 wParam = winpos->flags & 0xffff;
4237 msg.message = message;
4238 msg.flags = sent|wparam|lparam;
4239 if (defwndproc_counter) msg.flags |= defwinproc;
4240 if (beginpaint_counter) msg.flags |= beginpaint;
4241 msg.wParam = wParam;
4242 msg.lParam = lParam;
4245 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
4247 HWND parent = GetParent(hwnd);
4249 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
4251 GetClientRect(parent, &rc);
4252 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
4254 trace("ptReserved = (%ld,%ld)\n"
4255 "ptMaxSize = (%ld,%ld)\n"
4256 "ptMaxPosition = (%ld,%ld)\n"
4257 "ptMinTrackSize = (%ld,%ld)\n"
4258 "ptMaxTrackSize = (%ld,%ld)\n",
4259 minmax->ptReserved.x, minmax->ptReserved.y,
4260 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
4261 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
4262 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
4263 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
4265 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
4266 minmax->ptMaxSize.x, rc.right);
4267 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
4268 minmax->ptMaxSize.y, rc.bottom);
4271 if (message == WM_PAINT)
4274 beginpaint_counter++;
4275 BeginPaint( hwnd, &ps );
4276 beginpaint_counter--;
4277 EndPaint( hwnd, &ps );
4281 defwndproc_counter++;
4282 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4283 defwndproc_counter--;
4288 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4290 static long defwndproc_counter = 0;
4294 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4296 msg.message = message;
4297 msg.flags = sent|wparam|lparam;
4298 if (defwndproc_counter) msg.flags |= defwinproc;
4299 msg.wParam = wParam;
4300 msg.lParam = lParam;
4303 if (message == WM_CREATE)
4305 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
4306 SetWindowLongA(hwnd, GWL_STYLE, style);
4309 defwndproc_counter++;
4310 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4311 defwndproc_counter--;
4316 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4318 static long defwndproc_counter = 0;
4319 static long beginpaint_counter = 0;
4323 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4325 if (log_all_parent_messages ||
4326 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
4327 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
4328 message == WM_ENABLE || message == WM_ENTERIDLE ||
4329 message == WM_IME_SETCONTEXT)
4331 msg.message = message;
4332 msg.flags = sent|parent|wparam|lparam;
4333 if (defwndproc_counter) msg.flags |= defwinproc;
4334 if (beginpaint_counter) msg.flags |= beginpaint;
4335 msg.wParam = wParam;
4336 msg.lParam = lParam;
4340 if (message == WM_PAINT)
4343 beginpaint_counter++;
4344 BeginPaint( hwnd, &ps );
4345 beginpaint_counter--;
4346 EndPaint( hwnd, &ps );
4350 defwndproc_counter++;
4351 ret = DefWindowProcA(hwnd, message, wParam, lParam);
4352 defwndproc_counter--;
4357 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
4359 static long defwndproc_counter = 0;
4363 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
4365 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
4366 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4367 if (after_end_dialog)
4368 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
4370 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
4374 case WM_WINDOWPOSCHANGING:
4375 case WM_WINDOWPOSCHANGED:
4377 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
4379 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4380 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4381 winpos->hwnd, winpos->hwndInsertAfter,
4382 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
4384 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4385 * in the high word for internal purposes
4387 wParam = winpos->flags & 0xffff;
4392 msg.message = message;
4393 msg.flags = sent|wparam|lparam;
4394 if (defwndproc_counter) msg.flags |= defwinproc;
4395 msg.wParam = wParam;
4396 msg.lParam = lParam;
4399 defwndproc_counter++;
4400 ret = DefDlgProcA(hwnd, message, wParam, lParam);
4401 defwndproc_counter--;
4406 static BOOL RegisterWindowClasses(void)
4411 cls.lpfnWndProc = MsgCheckProcA;
4414 cls.hInstance = GetModuleHandleA(0);
4416 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
4417 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4418 cls.lpszMenuName = NULL;
4419 cls.lpszClassName = "TestWindowClass";
4420 if(!RegisterClassA(&cls)) return FALSE;
4422 cls.lpfnWndProc = PopupMsgCheckProcA;
4423 cls.lpszClassName = "TestPopupClass";
4424 if(!RegisterClassA(&cls)) return FALSE;
4426 cls.lpfnWndProc = ParentMsgCheckProcA;
4427 cls.lpszClassName = "TestParentClass";
4428 if(!RegisterClassA(&cls)) return FALSE;
4430 cls.lpfnWndProc = DefWindowProcA;
4431 cls.lpszClassName = "SimpleWindowClass";
4432 if(!RegisterClassA(&cls)) return FALSE;
4434 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
4436 cls.hInstance = GetModuleHandleA(0);
4437 cls.hbrBackground = 0;
4438 cls.lpfnWndProc = TestDlgProcA;
4439 cls.lpszClassName = "TestDialogClass";
4440 if(!RegisterClassA(&cls)) return FALSE;
4445 static HHOOK hCBT_hook;
4447 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
4451 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
4453 if (nCode == HCBT_SYSCOMMAND)
4457 msg.message = nCode;
4459 msg.wParam = wParam;
4460 msg.lParam = lParam;
4463 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
4466 /* Log also SetFocus(0) calls */
4467 if (!wParam) wParam = lParam;
4469 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
4471 if (!strcmp(buf, "TestWindowClass") ||
4472 !strcmp(buf, "TestParentClass") ||
4473 !strcmp(buf, "TestPopupClass") ||
4474 !strcmp(buf, "SimpleWindowClass") ||
4475 !strcmp(buf, "TestDialogClass") ||
4476 !strcmp(buf, "MDI_frame_class") ||
4477 !strcmp(buf, "MDI_client_class") ||
4478 !strcmp(buf, "MDI_child_class") ||
4479 !strcmp(buf, "my_button_class") ||
4480 !strcmp(buf, "#32770"))
4484 msg.message = nCode;
4485 msg.flags = hook|wparam|lparam;
4486 msg.wParam = wParam;
4487 msg.lParam = lParam;
4491 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
4494 static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
4504 trace("WEH:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
4505 hevent, event, hwnd, object_id, child_id, thread_id, event_time);
4507 /* ignore mouse cursor events */
4508 if (object_id == OBJID_CURSOR) return;
4510 if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf)))
4513 !strcmp(buf, "TestWindowClass") ||
4514 !strcmp(buf, "TestParentClass") ||
4515 !strcmp(buf, "TestPopupClass") ||
4516 !strcmp(buf, "SimpleWindowClass") ||
4517 !strcmp(buf, "TestDialogClass") ||
4518 !strcmp(buf, "MDI_frame_class") ||
4519 !strcmp(buf, "MDI_client_class") ||
4520 !strcmp(buf, "MDI_child_class") ||
4521 !strcmp(buf, "my_button_class") ||
4522 !strcmp(buf, "#32770"))
4526 msg.message = event;
4527 msg.flags = winevent_hook|wparam|lparam;
4528 msg.wParam = object_id;
4529 msg.lParam = child_id;
4535 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
4536 static const WCHAR wszAnsi[] = {'U',0};
4538 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4542 case CB_FINDSTRINGEXACT:
4543 trace("String: %p\n", (LPCWSTR)lParam);
4544 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
4546 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
4550 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
4553 static void test_message_conversion(void)
4555 static const WCHAR wszMsgConversionClass[] =
4556 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
4563 cls.lpfnWndProc = MsgConversionProcW;
4566 cls.hInstance = GetModuleHandleW(NULL);
4568 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
4569 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
4570 cls.lpszMenuName = NULL;
4571 cls.lpszClassName = wszMsgConversionClass;
4572 /* this call will fail on Win9x, but that doesn't matter as this test is
4573 * meaningless on those platforms */
4574 if(!RegisterClassW(&cls)) return;
4576 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
4577 100, 100, 200, 200, 0, 0, 0, NULL);
4578 ok(hwnd != NULL, "Window creation failed\n");
4582 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
4583 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4584 ok(lRes == 0, "String should have been converted\n");
4585 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4586 ok(lRes == 1, "String shouldn't have been converted\n");
4590 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
4591 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4592 ok(lRes == 1, "String shouldn't have been converted\n");
4593 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4594 ok(lRes == 1, "String shouldn't have been converted\n");
4596 /* Synchronous messages */
4598 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4599 ok(lRes == 0, "String should have been converted\n");
4600 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4601 ok(lRes == 1, "String shouldn't have been converted\n");
4603 /* Asynchronous messages */
4606 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4607 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4608 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4610 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4611 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4612 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4614 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4615 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4616 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4618 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4619 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4620 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4622 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4623 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4624 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4626 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4627 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4628 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4630 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4631 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4632 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4634 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4635 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4636 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4639 typedef struct _thread_info
4646 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
4650 #define TIMER_ID 0x19
4652 static DWORD WINAPI timer_thread_proc(LPVOID x)
4654 thread_info *info = x;
4657 r = KillTimer(info->hWnd, 0x19);
4658 ok(r,"KillTimer failed in thread\n");
4659 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
4660 ok(r,"SetTimer failed in thread\n");
4661 ok(r==TIMER_ID,"SetTimer id different\n");
4662 r = SetEvent(info->handles[0]);
4663 ok(r,"SetEvent failed in thread\n");
4667 static void test_timers(void)
4672 info.hWnd = CreateWindow ("TestWindowClass", NULL,
4673 WS_OVERLAPPEDWINDOW ,
4674 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4677 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
4678 ok(info.id, "SetTimer failed\n");
4679 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
4680 info.handles[0] = CreateEvent(NULL,0,0,NULL);
4681 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
4683 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
4685 WaitForSingleObject(info.handles[1], INFINITE);
4687 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
4689 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
4692 /* Various win events with arbitrary parameters */
4693 static const struct message WmWinEventsSeq[] = {
4694 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
4695 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4696 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
4697 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
4698 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
4699 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
4700 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
4701 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
4702 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
4703 /* our win event hook ignores OBJID_CURSOR events */
4704 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
4705 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
4706 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
4707 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
4708 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
4709 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
4710 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
4711 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
4712 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
4713 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
4714 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
4715 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
4716 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
4717 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
4721 static void test_winevents(void)
4725 const struct message *events = WmWinEventsSeq;
4726 HMODULE user32 = GetModuleHandleA("user32.dll");
4727 FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
4729 if (!pNotifyWinEvent) return;
4731 hwnd = CreateWindow ("TestWindowClass", NULL,
4732 WS_OVERLAPPEDWINDOW,
4733 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4739 /* Windows ignores events with hwnd == 0 */
4740 SetLastError(0xdeadbeef);
4741 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
4742 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
4743 GetLastError() == 0xdeadbeef, /* Win9x */
4744 "unexpected error %ld\n", GetLastError());
4745 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
4747 for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
4748 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
4750 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
4751 ok(DestroyWindow(hwnd), "failed to destroy window\n");
4756 HMODULE user32 = GetModuleHandleA("user32.dll");
4757 FARPROC pSetWinEventHook = 0;/*GetProcAddress(user32, "SetWinEventHook");*/
4758 FARPROC pUnhookWinEvent = 0;/*GetProcAddress(user32, "UnhookWinEvent");*/
4759 FARPROC pIsWinEventHookInstalled = GetProcAddress(user32, "IsWinEventHookInstalled");
4761 if (!RegisterWindowClasses()) assert(0);
4763 if (pSetWinEventHook)
4766 hEvent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
4767 GetModuleHandleA(0),
4769 GetCurrentProcessId(),
4771 WINEVENT_INCONTEXT);
4772 assert(hEvent_hook);
4774 if (pIsWinEventHookInstalled)
4776 for (event = EVENT_MIN; event <= EVENT_MAX; event++)
4777 ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
4781 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
4785 test_mdi_messages();
4786 test_button_messages();
4787 test_paint_messages();
4788 test_interthread_messages();
4789 test_message_conversion();
4790 test_accelerators();
4794 UnhookWindowsHookEx(hCBT_hook);
4795 if (pUnhookWinEvent)
4797 ok(pUnhookWinEvent(hEvent_hook), "UnhookWinEvent error %ld\n", GetLastError());
4798 SetLastError(0xdeadbeef);
4799 ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n");
4800 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
4801 GetLastError() == 0xdeadbeef, /* Win9x */
4802 "unexpected error %ld\n", GetLastError());