2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004 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
43 FIXME: add tests for these
44 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
45 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
46 WS_THICKFRAME: thick border
47 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
48 WS_BORDER (default for overlapped windows): single black border
49 none (default for child (and popup?) windows): no border
65 UINT message; /* the WM_* code */
66 msg_flags_t flags; /* message props */
67 WPARAM wParam; /* expected value of wParam */
68 LPARAM lParam; /* expected value of lParam */
71 /* Empty message sequence */
72 static const struct message WmEmptySeq[] =
76 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
77 static const struct message WmCreateOverlappedSeq[] = {
78 { HCBT_CREATEWND, hook },
79 { WM_GETMINMAXINFO, sent },
80 { WM_NCCREATE, sent },
81 { WM_NCCALCSIZE, sent|wparam, 0 },
85 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
86 * for a not visible overlapped window.
88 static const struct message WmSWP_ShowOverlappedSeq[] = {
89 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
90 { WM_NCPAINT, sent|wparam|optional, 1 },
91 { WM_GETTEXT, sent|defwinproc|optional },
92 { WM_ERASEBKGND, sent|optional },
93 { HCBT_ACTIVATE, hook },
94 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
95 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
96 { WM_ACTIVATEAPP, sent|wparam, 1 },
97 { WM_NCACTIVATE, sent|wparam, 1 },
98 { WM_GETTEXT, sent|defwinproc|optional },
99 { WM_ACTIVATE, sent|wparam, 1 },
100 { HCBT_SETFOCUS, hook },
101 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
102 { WM_IME_NOTIFY, sent|defwinproc|optional },
103 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
104 { WM_NCPAINT, sent|wparam|optional, 1 },
105 { WM_GETTEXT, sent|defwinproc|optional },
106 { WM_ERASEBKGND, sent|optional },
107 /* Win9x adds SWP_NOZORDER below */
108 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
109 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
110 { WM_NCPAINT, sent|wparam|optional, 1 },
111 { WM_ERASEBKGND, sent|optional },
114 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
115 * for a visible overlapped window.
117 static const struct message WmSWP_HideOverlappedSeq[] = {
118 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
119 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
122 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
123 static const struct message WmShowOverlappedSeq[] = {
124 { WM_SHOWWINDOW, sent|wparam, 1 },
125 { WM_NCPAINT, sent|wparam|optional, 1 },
126 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
127 { WM_NCPAINT, sent|wparam|optional, 1 },
128 { WM_GETTEXT, sent|defwinproc|optional },
129 { WM_ERASEBKGND, sent|optional },
130 { HCBT_ACTIVATE, hook },
131 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
132 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
133 { WM_ACTIVATEAPP, sent|wparam, 1 },
134 { WM_NCACTIVATE, sent|wparam, 1 },
135 { WM_GETTEXT, sent|defwinproc|optional },
136 { WM_ACTIVATE, sent|wparam, 1 },
137 { HCBT_SETFOCUS, hook },
138 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
139 { WM_IME_NOTIFY, sent|defwinproc|optional },
140 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
141 { WM_NCPAINT, sent|wparam|optional, 1 },
142 { WM_GETTEXT, sent|defwinproc|optional },
143 { WM_ERASEBKGND, sent|optional },
144 /* Win9x adds SWP_NOZORDER below */
145 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
146 { WM_NCCALCSIZE, sent|optional },
147 { WM_NCPAINT, sent|optional },
148 { WM_ERASEBKGND, sent|optional },
149 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
150 * messages. Does that mean that CreateWindow doesn't set initial
151 * window dimensions for overlapped windows?
158 /* ShowWindow(SW_HIDE) for a visible overlapped window */
159 static const struct message WmHideOverlappedSeq[] = {
160 { WM_SHOWWINDOW, sent|wparam, 0 },
161 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
162 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
165 { WM_NCACTIVATE, sent|wparam, 0 },
166 { WM_ACTIVATE, sent|wparam, 0 },
167 { WM_ACTIVATEAPP, sent|wparam, 0 },
168 { WM_KILLFOCUS, sent|wparam, 0 },
169 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
170 { WM_IME_NOTIFY, sent|optional|defwinproc },
173 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
174 static const struct message WmHideInvisibleOverlappedSeq[] = {
177 /* DestroyWindow for a visible overlapped window */
178 static const struct message WmDestroyOverlappedSeq[] = {
179 { HCBT_DESTROYWND, hook },
180 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
181 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
182 { WM_NCACTIVATE, sent|wparam, 0 },
183 { WM_ACTIVATE, sent|wparam, 0 },
184 { WM_ACTIVATEAPP, sent|wparam, 0 },
185 { WM_KILLFOCUS, sent|wparam, 0 },
186 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
187 { WM_IME_NOTIFY, sent|optional|defwinproc },
188 { WM_DESTROY, sent },
189 { WM_NCDESTROY, sent },
192 /* CreateWindow (for a child popup window, not initially visible) */
193 static const struct message WmCreateChildPopupSeq[] = {
194 { HCBT_CREATEWND, hook },
195 { WM_NCCREATE, sent },
196 { WM_NCCALCSIZE, sent|wparam, 0 },
202 /* CreateWindow (for a popup window, not initially visible,
203 * which sets WS_VISIBLE in WM_CREATE handler)
205 static const struct message WmCreateInvisiblePopupSeq[] = {
206 { HCBT_CREATEWND, hook },
207 { WM_NCCREATE, sent },
208 { WM_NCCALCSIZE, sent|wparam, 0 },
210 { WM_STYLECHANGING, sent },
211 { WM_STYLECHANGED, sent },
216 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
217 * for a popup window with WS_VISIBLE style set
219 static const struct message WmShowVisiblePopupSeq_2[] = {
220 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
223 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
224 * for a popup window with WS_VISIBLE style set
226 static const struct message WmShowVisiblePopupSeq_3[] = {
227 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
228 { HCBT_ACTIVATE, hook },
229 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
230 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
231 { WM_NCACTIVATE, sent|wparam, 1 },
232 { WM_ACTIVATE, sent|wparam, 1 },
233 { HCBT_SETFOCUS, hook },
234 { WM_KILLFOCUS, sent|parent },
235 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
236 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
237 { WM_IME_NOTIFY, sent|defwinproc|optional },
238 { WM_SETFOCUS, sent|defwinproc },
241 /* CreateWindow (for child window, not initially visible) */
242 static const struct message WmCreateChildSeq[] = {
243 { HCBT_CREATEWND, hook },
244 { WM_NCCREATE, sent },
245 /* child is inserted into parent's child list after WM_NCCREATE returns */
246 { WM_NCCALCSIZE, sent|wparam, 0 },
250 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
253 /* CreateWindow (for maximized child window, not initially visible) */
254 static const struct message WmCreateMaximizedChildSeq[] = {
255 { HCBT_CREATEWND, hook },
256 { WM_NCCREATE, sent },
257 { WM_NCCALCSIZE, sent|wparam, 0 },
261 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
262 { WM_GETMINMAXINFO, sent },
263 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
264 { WM_NCCALCSIZE, sent|wparam, 1 },
265 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 },
266 { WM_SIZE, sent|defwinproc },
267 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
270 /* CreateWindow (for a child window, initially visible) */
271 static const struct message WmCreateVisibleChildSeq[] = {
272 { HCBT_CREATEWND, hook },
273 { WM_NCCREATE, sent },
274 /* child is inserted into parent's child list after WM_NCCREATE returns */
275 { WM_NCCALCSIZE, sent|wparam, 0 },
279 { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
280 { WM_SHOWWINDOW, sent|wparam, 1 },
281 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
282 { WM_ERASEBKGND, sent|parent|optional },
283 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
286 /* ShowWindow(SW_SHOW) for a not visible child window */
287 static const struct message WmShowChildSeq[] = {
288 { WM_SHOWWINDOW, sent|wparam, 1 },
289 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
290 { WM_ERASEBKGND, sent|parent|optional },
291 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
294 /* ShowWindow(SW_HIDE) for a visible child window */
295 static const struct message WmHideChildSeq[] = {
296 { WM_SHOWWINDOW, sent|wparam, 0 },
297 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
298 { WM_ERASEBKGND, sent|parent|optional },
299 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
302 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
303 * for a not visible child window
305 static const struct message WmShowChildSeq_2[] = {
306 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
307 { WM_CHILDACTIVATE, sent },
308 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
311 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
312 * for a not visible child window
314 static const struct message WmShowChildSeq_3[] = {
315 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE },
316 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
319 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
320 * for a visible child window with a caption
322 static const struct message WmShowChildSeq_4[] = {
323 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
324 { WM_CHILDACTIVATE, sent },
327 /* ShowWindow(SW_SHOW) for child with invisible parent */
328 static const struct message WmShowChildInvisibleParentSeq[] = {
329 { WM_SHOWWINDOW, sent|wparam, 1 },
332 /* ShowWindow(SW_HIDE) for child with invisible parent */
333 static const struct message WmHideChildInvisibleParentSeq[] = {
334 { WM_SHOWWINDOW, sent|wparam, 0 },
337 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
338 static const struct message WmShowChildInvisibleParentSeq_2[] = {
339 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER },
340 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
343 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
344 static const struct message WmHideChildInvisibleParentSeq_2[] = {
345 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
346 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
349 /* DestroyWindow for a visible child window */
350 static const struct message WmDestroyChildSeq[] = {
351 { HCBT_DESTROYWND, hook },
352 { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
353 { WM_SHOWWINDOW, sent|wparam, 0 },
354 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
355 { WM_ERASEBKGND, sent|parent|optional },
356 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
357 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
358 { WM_KILLFOCUS, sent },
359 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
360 { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
361 { WM_SETFOCUS, sent|parent },
362 { WM_DESTROY, sent },
363 { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
364 { WM_NCDESTROY, sent },
365 { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
368 /* Moving the mouse in nonclient area */
369 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
370 { WM_NCHITTEST, sent },
371 { WM_SETCURSOR, sent },
372 { WM_NCMOUSEMOVE, posted },
375 /* Moving the mouse in client area */
376 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
377 { WM_NCHITTEST, sent },
378 { WM_SETCURSOR, sent },
379 { WM_MOUSEMOVE, posted },
382 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
383 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
384 { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
385 { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
386 { WM_GETMINMAXINFO, sent|defwinproc },
387 { WM_ENTERSIZEMOVE, sent|defwinproc },
388 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
389 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
390 { WM_MOVE, sent|defwinproc },
391 { WM_EXITSIZEMOVE, sent|defwinproc },
394 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
395 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
396 { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
397 { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
398 { WM_GETMINMAXINFO, sent|defwinproc },
399 { WM_ENTERSIZEMOVE, sent|defwinproc },
400 { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
401 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
402 { WM_GETMINMAXINFO, sent|defwinproc },
403 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
404 { WM_NCPAINT, sent|defwinproc|wparam, 1 },
405 { WM_GETTEXT, sent|defwinproc },
406 { WM_ERASEBKGND, sent|defwinproc },
407 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
408 { WM_MOVE, sent|defwinproc },
409 { WM_SIZE, sent|defwinproc },
410 { WM_EXITSIZEMOVE, sent|defwinproc },
413 /* Resizing child window with MoveWindow (32) */
414 static const struct message WmResizingChildWithMoveWindowSeq[] = {
415 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
416 { WM_NCCALCSIZE, sent|wparam, 1 },
417 { WM_ERASEBKGND, sent|optional },
418 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
419 { WM_MOVE, sent|defwinproc },
420 { WM_SIZE, sent|defwinproc },
423 /* Clicking on inactive button */
424 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
425 { WM_NCHITTEST, sent },
426 { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
427 { WM_MOUSEACTIVATE, sent },
428 { WM_MOUSEACTIVATE, sent|parent|defwinproc },
429 { WM_SETCURSOR, sent },
430 { WM_SETCURSOR, sent|parent|defwinproc },
431 { WM_LBUTTONDOWN, posted },
432 { WM_KILLFOCUS, posted|parent },
433 { WM_SETFOCUS, posted },
434 { WM_CTLCOLORBTN, posted|parent },
435 { BM_SETSTATE, posted },
436 { WM_CTLCOLORBTN, posted|parent },
437 { WM_LBUTTONUP, posted },
438 { BM_SETSTATE, posted },
439 { WM_CTLCOLORBTN, posted|parent },
440 { WM_COMMAND, posted|parent },
443 /* Reparenting a button (16/32) */
444 /* The last child (button) reparented gets topmost for its new parent. */
445 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
446 { WM_SHOWWINDOW, sent|wparam, 0 },
447 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
448 { WM_ERASEBKGND, sent|parent },
449 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
450 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
451 { WM_CHILDACTIVATE, sent },
452 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
453 { WM_MOVE, sent|defwinproc },
454 { WM_SHOWWINDOW, sent|wparam, 1 },
457 /* Creation of a custom dialog (32) */
458 static const struct message WmCreateCustomDialogSeq[] = {
459 { HCBT_CREATEWND, hook },
460 { WM_GETMINMAXINFO, sent },
461 { WM_NCCREATE, sent },
462 { WM_NCCALCSIZE, sent|wparam, 0 },
464 { WM_SHOWWINDOW, sent|wparam, 1 },
465 { HCBT_ACTIVATE, hook },
466 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
467 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
468 { WM_NCACTIVATE, sent|wparam, 1 },
469 { WM_GETTEXT, sent|optional|defwinproc },
470 { WM_GETICON, sent|optional|defwinproc },
471 { WM_GETICON, sent|optional|defwinproc },
472 { WM_GETICON, sent|optional|defwinproc },
473 { WM_GETTEXT, sent|optional|defwinproc },
474 { WM_ACTIVATE, sent|wparam, 1 },
475 { WM_KILLFOCUS, sent|parent },
476 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
477 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
478 { WM_IME_NOTIFY, sent|optional|defwinproc },
479 { WM_SETFOCUS, sent },
480 { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
481 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
482 { WM_NCPAINT, sent|wparam, 1 },
483 { WM_GETTEXT, sent|optional|defwinproc },
484 { WM_GETICON, sent|optional|defwinproc },
485 { WM_GETICON, sent|optional|defwinproc },
486 { WM_GETICON, sent|optional|defwinproc },
487 { WM_GETTEXT, sent|optional|defwinproc },
488 { WM_ERASEBKGND, sent },
489 { WM_CTLCOLORDLG, sent|defwinproc },
490 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
491 { WM_GETTEXT, sent|optional },
492 { WM_GETICON, sent|optional },
493 { WM_GETICON, sent|optional },
494 { WM_GETICON, sent|optional },
495 { WM_GETTEXT, sent|optional },
496 { WM_NCCALCSIZE, sent|optional },
497 { WM_NCPAINT, sent|optional },
498 { WM_GETTEXT, sent|optional|defwinproc },
499 { WM_GETICON, sent|optional|defwinproc },
500 { WM_GETICON, sent|optional|defwinproc },
501 { WM_GETICON, sent|optional|defwinproc },
502 { WM_GETTEXT, sent|optional|defwinproc },
503 { WM_ERASEBKGND, sent|optional },
504 { WM_CTLCOLORDLG, sent|optional|defwinproc },
509 /* Calling EndDialog for a custom dialog (32) */
510 static const struct message WmEndCustomDialogSeq[] = {
511 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
512 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
513 { WM_GETTEXT, sent|optional },
514 { WM_GETICON, sent|optional },
515 { WM_GETICON, sent|optional },
516 { WM_GETICON, sent|optional },
517 { HCBT_ACTIVATE, hook },
518 { WM_NCACTIVATE, sent|wparam, 0 },
519 { WM_GETTEXT, sent|optional|defwinproc },
520 { WM_GETICON, sent|optional|defwinproc },
521 { WM_GETICON, sent|optional|defwinproc },
522 { WM_GETICON, sent|optional|defwinproc },
523 { WM_GETTEXT, sent|optional|defwinproc },
524 { WM_ACTIVATE, sent|wparam, 0 },
525 { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 },
526 { HCBT_SETFOCUS, hook },
527 { WM_KILLFOCUS, sent },
528 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
529 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
530 { WM_IME_NOTIFY, sent|optional },
531 { WM_SETFOCUS, sent|parent|defwinproc },
534 /* Creation and destruction of a modal dialog (32) */
535 static const struct message WmModalDialogSeq[] = {
536 { WM_CANCELMODE, sent|parent },
537 { HCBT_SETFOCUS, hook },
538 { WM_KILLFOCUS, sent|parent },
539 { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
540 { WM_ENABLE, sent|parent|wparam, 0 },
541 { HCBT_CREATEWND, hook },
542 { WM_SETFONT, sent },
543 { WM_INITDIALOG, sent },
544 { WM_CHANGEUISTATE, sent|optional },
545 { WM_SHOWWINDOW, sent },
546 { HCBT_ACTIVATE, hook },
547 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
548 { WM_NCACTIVATE, sent|wparam, 1 },
549 { WM_GETICON, sent|optional },
550 { WM_GETICON, sent|optional },
551 { WM_GETICON, sent|optional },
552 { WM_GETTEXT, sent|optional },
553 { WM_ACTIVATE, sent|wparam, 1 },
554 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
555 { WM_NCPAINT, sent },
556 { WM_GETICON, sent|optional },
557 { WM_GETICON, sent|optional },
558 { WM_GETICON, sent|optional },
559 { WM_GETTEXT, sent|optional },
560 { WM_ERASEBKGND, sent },
561 { WM_CTLCOLORDLG, sent },
562 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
563 { WM_GETICON, sent|optional },
564 { WM_GETICON, sent|optional },
565 { WM_GETICON, sent|optional },
566 { WM_GETTEXT, sent|optional },
567 { WM_NCCALCSIZE, sent|optional },
568 { WM_NCPAINT, sent|optional },
569 { WM_GETICON, sent|optional },
570 { WM_GETICON, sent|optional },
571 { WM_GETICON, sent|optional },
572 { WM_GETTEXT, sent|optional },
573 { WM_ERASEBKGND, sent|optional },
574 { WM_CTLCOLORDLG, sent|optional },
575 { WM_PAINT, sent|optional },
576 { WM_CTLCOLORBTN, sent },
577 { WM_ENTERIDLE, sent|parent|optional },
579 { WM_ENABLE, sent|parent|wparam, 1 },
580 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
581 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
582 { WM_GETICON, sent|optional },
583 { WM_GETICON, sent|optional },
584 { WM_GETICON, sent|optional },
585 { WM_GETTEXT, sent|optional },
586 { HCBT_ACTIVATE, hook },
587 { WM_NCACTIVATE, sent|wparam, 0 },
588 { WM_GETICON, sent|optional },
589 { WM_GETICON, sent|optional },
590 { WM_GETICON, sent|optional },
591 { WM_GETTEXT, sent|optional },
592 { WM_ACTIVATE, sent|wparam, 0 },
593 { WM_WINDOWPOSCHANGING, sent|optional },
594 { HCBT_SETFOCUS, hook },
595 { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
596 { WM_SETFOCUS, sent|parent|defwinproc },
597 { HCBT_DESTROYWND, hook },
598 { WM_DESTROY, sent },
599 { WM_NCDESTROY, sent },
602 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
603 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
604 /* (inside dialog proc, handling WM_INITDIALOG) */
605 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
606 { WM_NCCALCSIZE, sent },
607 { WM_NCACTIVATE, sent|parent|wparam, 0 },
608 { WM_GETTEXT, sent|defwinproc },
609 { WM_ACTIVATE, sent|parent|wparam, 0 },
610 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
611 { WM_WINDOWPOSCHANGING, sent|parent },
612 { WM_NCACTIVATE, sent|wparam, 1 },
613 { WM_ACTIVATE, sent|wparam, 1 },
614 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
615 { WM_SIZE, sent|defwinproc },
616 /* (setting focus) */
617 { WM_SHOWWINDOW, sent|wparam, 1 },
618 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
619 { WM_NCPAINT, sent },
620 { WM_GETTEXT, sent|defwinproc },
621 { WM_ERASEBKGND, sent },
622 { WM_CTLCOLORDLG, sent|defwinproc },
623 { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
625 /* (bunch of WM_CTLCOLOR* for each control) */
626 { WM_PAINT, sent|parent },
627 { WM_ENTERIDLE, sent|parent|wparam, 0 },
628 { WM_SETCURSOR, sent|parent },
631 /* SetMenu for NonVisible windows with size change*/
632 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
633 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
634 { WM_NCCALCSIZE, sent|wparam, 1 },
635 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW },
636 { WM_MOVE, sent|defwinproc },
637 { WM_SIZE, sent|defwinproc },
638 { WM_GETICON, sent|optional },
639 { WM_GETICON, sent|optional },
640 { WM_GETICON, sent|optional },
641 { WM_GETTEXT, sent|optional },
642 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
645 /* SetMenu for NonVisible windows with no size change */
646 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
647 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
648 { WM_NCCALCSIZE, sent|wparam, 1 },
649 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
652 /* SetMenu for Visible windows with size change */
653 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
654 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
655 { WM_NCCALCSIZE, sent|wparam, 1 },
656 { WM_NCPAINT, sent|wparam, 1 },
657 { WM_GETTEXT, sent|defwinproc|optional },
658 { WM_ERASEBKGND, sent|optional },
659 { WM_ACTIVATE, sent|optional },
660 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
661 { WM_MOVE, sent|defwinproc },
662 { WM_SIZE, sent|defwinproc },
663 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
664 { WM_NCPAINT, sent|wparam|optional, 1 },
665 { WM_ERASEBKGND, sent|optional },
668 /* SetMenu for Visible windows with no size change */
669 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
670 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
671 { WM_NCCALCSIZE, sent|wparam, 1 },
672 { WM_NCPAINT, sent|wparam, 1 },
673 { WM_GETTEXT, sent|defwinproc|optional },
674 { WM_ERASEBKGND, sent|optional },
675 { WM_ACTIVATE, sent|optional },
676 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
679 /* DrawMenuBar for a visible window */
680 static const struct message WmDrawMenuBarSeq[] =
682 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
683 { WM_NCCALCSIZE, sent|wparam, 1 },
684 { WM_NCPAINT, sent|wparam, 1 },
685 { WM_GETTEXT, sent|defwinproc|optional },
686 { WM_ERASEBKGND, sent|optional },
687 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
691 static const struct message WmSetRedrawFalseSeq[] =
693 { WM_SETREDRAW, sent|wparam, 0 },
697 static const struct message WmSetRedrawTrueSeq[] =
699 { WM_SETREDRAW, sent|wparam, 1 },
703 static const struct message WmEnableWindowSeq[] =
705 { WM_CANCELMODE, sent },
710 static const struct message WmGetScrollRangeSeq[] =
712 { SBM_GETRANGE, sent },
715 static const struct message WmGetScrollInfoSeq[] =
717 { SBM_GETSCROLLINFO, sent },
720 static const struct message WmSetScrollRangeSeq[] =
722 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
723 sends SBM_SETSCROLLINFO.
725 { SBM_SETSCROLLINFO, sent },
728 /* SetScrollRange for a window without a non-client area */
729 static const struct message WmSetScrollRangeHVSeq[] =
731 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
732 { WM_NCCALCSIZE, sent|wparam, 1 },
733 { WM_GETTEXT, sent|defwinproc|optional },
734 { WM_ERASEBKGND, sent|optional },
735 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
738 /* SetScrollRange for a window with a non-client area */
739 static const struct message WmSetScrollRangeHV_NC_Seq[] =
741 { WM_WINDOWPOSCHANGING, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
742 { WM_NCCALCSIZE, sent|wparam, 1 },
743 { WM_NCPAINT, sent|optional },
744 { WM_GETTEXT, sent|defwinproc|optional },
745 { WM_GETICON, sent|optional|defwinproc },
746 { WM_GETICON, sent|optional|defwinproc },
747 { WM_GETICON, sent|optional|defwinproc },
748 { WM_GETTEXT, sent|defwinproc|optional },
749 { WM_ERASEBKGND, sent|optional },
750 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
751 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
752 { WM_SIZE, sent|defwinproc },
753 { WM_GETTEXT, sent|optional },
754 { WM_GETICON, sent|optional },
755 { WM_GETICON, sent|optional },
756 { WM_GETICON, sent|optional },
757 { WM_GETTEXT, sent|optional },
758 { WM_GETICON, sent|optional },
759 { WM_GETICON, sent|optional },
760 { WM_GETICON, sent|optional },
761 { WM_GETTEXT, sent|optional },
762 { WM_GETICON, sent|optional },
763 { WM_GETICON, sent|optional },
764 { WM_GETICON, sent|optional },
765 { WM_GETTEXT, sent|optional },
769 static int after_end_dialog;
770 static int sequence_cnt, sequence_size;
771 static struct message* sequence;
772 static int log_all_parent_messages;
774 static void add_message(const struct message *msg)
779 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
781 if (sequence_cnt == sequence_size)
784 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
788 sequence[sequence_cnt].message = msg->message;
789 sequence[sequence_cnt].flags = msg->flags;
790 sequence[sequence_cnt].wParam = msg->wParam;
791 sequence[sequence_cnt].lParam = msg->lParam;
796 static void flush_sequence()
798 HeapFree(GetProcessHeap(), 0, sequence);
800 sequence_cnt = sequence_size = 0;
803 static void ok_sequence(const struct message *expected, const char *context, int todo)
805 static const struct message end_of_sequence = { 0, 0, 0, 0 };
806 const struct message *actual;
808 add_message(&end_of_sequence);
812 while (expected->message && actual->message)
814 trace("expected %04x - actual %04x\n", expected->message, actual->message);
816 if (expected->message == actual->message)
818 if (expected->flags & wparam)
820 if (expected->wParam != actual->wParam && todo)
824 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
825 context, expected->message, expected->wParam, actual->wParam);
829 ok (expected->wParam == actual->wParam,
830 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
831 context, expected->message, expected->wParam, actual->wParam);
833 if (expected->flags & lparam)
834 ok (expected->lParam == actual->lParam,
835 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
836 context, expected->message, expected->lParam, actual->lParam);
837 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
838 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
839 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
840 ok ((expected->flags & beginpaint) == (actual->flags & beginpaint),
841 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
842 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
843 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
844 "%s: the msg 0x%04x should have been %s\n",
845 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
846 ok ((expected->flags & parent) == (actual->flags & parent),
847 "%s: the msg 0x%04x was expected in %s\n",
848 context, expected->message, (expected->flags & parent) ? "parent" : "child");
849 ok ((expected->flags & hook) == (actual->flags & hook),
850 "%s: the msg 0x%04x should have been sent by a hook\n",
851 context, expected->message);
855 else if (expected->flags & optional)
860 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
861 context, expected->message, actual->message);
868 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
869 context, expected->message, actual->message);
875 /* skip all optional trailing messages */
876 while (expected->message && (expected->flags & optional))
882 if (expected->message || actual->message)
883 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
884 context, expected->message, actual->message);
889 if (expected->message || actual->message)
890 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
891 context, expected->message, actual->message);
897 /******************************** MDI test **********************************/
899 /* CreateWindow for MDI frame window, initially visible */
900 static const struct message WmCreateMDIframeSeq[] = {
901 { HCBT_CREATEWND, hook },
902 { WM_GETMINMAXINFO, sent },
903 { WM_NCCREATE, sent },
904 { WM_NCCALCSIZE, sent|wparam, 0 },
906 { WM_SHOWWINDOW, sent|wparam, 1 },
907 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
908 { HCBT_ACTIVATE, hook },
909 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
910 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
911 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* Win9x */
912 { WM_ACTIVATEAPP, sent|wparam, 1 },
913 { WM_NCACTIVATE, sent|wparam, 1 },
914 { WM_ACTIVATE, sent|wparam, 1 },
915 { HCBT_SETFOCUS, hook },
916 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
917 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
918 /* Win9x adds SWP_NOZORDER below */
919 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
924 /* DestroyWindow for MDI frame window, initially visible */
925 static const struct message WmDestroyMDIframeSeq[] = {
926 { HCBT_DESTROYWND, hook },
927 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
928 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
929 { WM_NCACTIVATE, sent|wparam, 0 },
930 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
931 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
932 { WM_DESTROY, sent },
933 { WM_NCDESTROY, sent },
936 /* CreateWindow for MDI client window, initially visible */
937 static const struct message WmCreateMDIclientSeq[] = {
938 { HCBT_CREATEWND, hook },
939 { WM_NCCREATE, sent },
940 { WM_NCCALCSIZE, sent|wparam, 0 },
944 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
945 { WM_SHOWWINDOW, sent|wparam, 1 },
946 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE },
947 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
950 /* DestroyWindow for MDI client window, initially visible */
951 static const struct message WmDestroyMDIclientSeq[] = {
952 { HCBT_DESTROYWND, hook },
953 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
954 { WM_SHOWWINDOW, sent|wparam, 0 },
955 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
956 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
957 { WM_DESTROY, sent },
958 { WM_NCDESTROY, sent },
961 /* CreateWindow for MDI child window, initially visible */
962 static const struct message WmCreateMDIchildVisibleSeq[] = {
963 { HCBT_CREATEWND, hook },
964 { WM_NCCREATE, sent },
965 { WM_NCCALCSIZE, sent|wparam, 0 },
969 /* Win2k sends wparam set to
970 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
971 * while Win9x doesn't bother to set child window id according to
972 * CLIENTCREATESTRUCT.idFirstChild
974 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
975 { WM_SHOWWINDOW, sent|wparam, 1 },
976 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
977 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
978 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
979 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
980 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
981 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
983 /* Win9x: message sequence terminates here. */
985 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
986 { HCBT_SETFOCUS, hook }, /* in MDI client */
987 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
988 { WM_SETFOCUS, sent }, /* in MDI client */
989 { HCBT_SETFOCUS, hook },
990 { WM_KILLFOCUS, sent }, /* in MDI client */
991 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
992 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
993 { WM_SETFOCUS, sent|defwinproc },
994 { WM_MDIACTIVATE, sent|defwinproc },
997 /* DestroyWindow for MDI child window, initially visible */
998 static const struct message WmDestroyMDIchildVisibleSeq[] = {
999 { HCBT_DESTROYWND, hook },
1000 /* Win2k sends wparam set to
1001 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1002 * while Win9x doesn't bother to set child window id according to
1003 * CLIENTCREATESTRUCT.idFirstChild
1005 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1006 { WM_SHOWWINDOW, sent|wparam, 0 },
1007 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1008 { WM_ERASEBKGND, sent|parent|optional },
1009 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1011 /* { WM_DESTROY, sent }
1012 * Win9x: message sequence terminates here.
1015 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1016 { WM_KILLFOCUS, sent },
1017 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1018 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1019 { WM_SETFOCUS, sent }, /* in MDI client */
1021 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1022 { WM_KILLFOCUS, sent }, /* in MDI client */
1023 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1024 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1025 { WM_SETFOCUS, sent }, /* in MDI client */
1027 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1028 { WM_KILLFOCUS, sent },
1029 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1030 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1031 { WM_SETFOCUS, sent }, /* in MDI client */
1033 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1034 { WM_KILLFOCUS, sent }, /* in MDI client */
1035 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1036 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1037 { WM_SETFOCUS, sent }, /* in MDI client */
1039 { WM_DESTROY, sent },
1041 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1042 { WM_KILLFOCUS, sent },
1043 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1044 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1045 { WM_SETFOCUS, sent }, /* in MDI client */
1047 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1048 { WM_KILLFOCUS, sent }, /* in MDI client */
1049 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1050 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1051 { WM_SETFOCUS, sent }, /* in MDI client */
1053 { WM_NCDESTROY, sent },
1056 /* CreateWindow for MDI child window, initially invisible */
1057 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1058 { HCBT_CREATEWND, hook },
1059 { WM_NCCREATE, sent },
1060 { WM_NCCALCSIZE, sent|wparam, 0 },
1061 { WM_CREATE, sent },
1064 /* Win2k sends wparam set to
1065 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1066 * while Win9x doesn't bother to set child window id according to
1067 * CLIENTCREATESTRUCT.idFirstChild
1069 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1072 /* DestroyWindow for MDI child window, initially invisible */
1073 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1074 { HCBT_DESTROYWND, hook },
1075 /* Win2k sends wparam set to
1076 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1077 * while Win9x doesn't bother to set child window id according to
1078 * CLIENTCREATESTRUCT.idFirstChild
1080 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1081 { WM_DESTROY, sent },
1082 { WM_NCDESTROY, sent },
1085 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1086 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1087 { HCBT_CREATEWND, hook },
1088 { WM_NCCREATE, sent },
1089 { WM_NCCALCSIZE, sent|wparam, 0 },
1090 { WM_CREATE, sent },
1093 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1094 { WM_GETMINMAXINFO, sent },
1095 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1096 { WM_NCCALCSIZE, sent|wparam, 1 },
1097 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1098 { WM_SIZE, sent|defwinproc },
1100 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1101 { WM_NCCALCSIZE, sent|wparam, 1 },
1102 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1103 /* Win2k sends wparam set to
1104 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1105 * while Win9x doesn't bother to set child window id according to
1106 * CLIENTCREATESTRUCT.idFirstChild
1108 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1109 { WM_SHOWWINDOW, sent|wparam, 1 },
1110 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1111 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1112 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1113 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1114 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1115 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1117 /* Win9x: message sequence terminates here. */
1119 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1120 { HCBT_SETFOCUS, hook }, /* in MDI client */
1121 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1122 { WM_SETFOCUS, sent }, /* in MDI client */
1123 { HCBT_SETFOCUS, hook },
1124 { WM_KILLFOCUS, sent }, /* in MDI client */
1125 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1126 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1127 { WM_SETFOCUS, sent|defwinproc },
1128 { WM_MDIACTIVATE, sent|defwinproc },
1130 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1131 { WM_NCCALCSIZE, sent|wparam, 1 },
1132 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1135 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1136 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
1137 /* restore the 1st MDI child */
1138 { WM_SETREDRAW, sent|wparam, 0 },
1139 { HCBT_MINMAX, hook },
1140 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1141 { WM_NCCALCSIZE, sent|wparam, 1 },
1142 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1143 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1144 { WM_SIZE, sent|defwinproc },
1146 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1147 { WM_NCCALCSIZE, sent|wparam, 1 },
1148 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1149 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
1150 /* create the 2nd MDI child */
1151 { HCBT_CREATEWND, hook },
1152 { WM_NCCREATE, sent },
1153 { WM_NCCALCSIZE, sent|wparam, 0 },
1154 { WM_CREATE, sent },
1157 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1158 { WM_GETMINMAXINFO, sent },
1159 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1160 { WM_NCCALCSIZE, sent|wparam, 1 },
1161 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1162 { WM_SIZE, sent|defwinproc },
1164 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1165 { WM_NCCALCSIZE, sent|wparam, 1 },
1166 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1167 /* Win2k sends wparam set to
1168 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1169 * while Win9x doesn't bother to set child window id according to
1170 * CLIENTCREATESTRUCT.idFirstChild
1172 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1173 { WM_SHOWWINDOW, sent|wparam, 1 },
1174 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1175 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1176 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1177 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1178 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1180 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1181 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1183 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1185 /* Win9x: message sequence terminates here. */
1187 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1188 { HCBT_SETFOCUS, hook },
1189 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
1190 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
1191 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1192 { WM_SETFOCUS, sent }, /* in MDI client */
1193 { HCBT_SETFOCUS, hook },
1194 { WM_KILLFOCUS, sent }, /* in MDI client */
1195 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1196 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1197 { WM_SETFOCUS, sent|defwinproc },
1199 { WM_MDIACTIVATE, sent|defwinproc },
1201 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1202 { WM_NCCALCSIZE, sent|wparam, 1 },
1203 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1206 /* WM_MDICREATE MDI child window, initially visible and maximized */
1207 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
1208 { WM_MDICREATE, sent },
1209 { HCBT_CREATEWND, hook },
1210 { WM_NCCREATE, sent },
1211 { WM_NCCALCSIZE, sent|wparam, 0 },
1212 { WM_CREATE, sent },
1215 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1216 { WM_GETMINMAXINFO, sent },
1217 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1218 { WM_NCCALCSIZE, sent|wparam, 1 },
1219 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1220 { WM_SIZE, sent|defwinproc },
1222 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1223 { WM_NCCALCSIZE, sent|wparam, 1 },
1224 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1225 /* Win2k sends wparam set to
1226 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1227 * while Win9x doesn't bother to set child window id according to
1228 * CLIENTCREATESTRUCT.idFirstChild
1230 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1231 { WM_SHOWWINDOW, sent|wparam, 1 },
1232 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1233 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1234 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1235 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1236 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1237 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1239 /* Win9x: message sequence terminates here. */
1241 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1242 { HCBT_SETFOCUS, hook }, /* in MDI client */
1243 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1244 { WM_SETFOCUS, sent }, /* in MDI client */
1245 { HCBT_SETFOCUS, hook },
1246 { WM_KILLFOCUS, sent }, /* in MDI client */
1247 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1248 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1249 { WM_SETFOCUS, sent|defwinproc },
1251 { WM_MDIACTIVATE, sent|defwinproc },
1254 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1255 { WM_NCCALCSIZE, sent|wparam, 1 },
1256 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1259 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1260 { WM_NCCALCSIZE, sent|wparam, 1 },
1261 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1262 { WM_MOVE, sent|defwinproc },
1263 { WM_SIZE, sent|defwinproc },
1266 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1267 { WM_NCCALCSIZE, sent|wparam, 1 },
1268 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1272 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1273 { WM_NCCALCSIZE, sent|wparam, 1 },
1274 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1275 { WM_SIZE, sent|defwinproc },
1279 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1280 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
1281 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
1282 { HCBT_SYSCOMMAND, hook },
1283 { WM_CLOSE, sent|defwinproc },
1284 { WM_MDIDESTROY, sent }, /* in MDI client */
1286 /* bring the 1st MDI child to top */
1287 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
1288 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
1289 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
1290 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1291 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1293 /* maximize the 1st MDI child */
1294 { HCBT_MINMAX, hook },
1295 { WM_GETMINMAXINFO, sent|defwinproc },
1296 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
1297 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1298 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
1299 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1300 { WM_SIZE, sent|defwinproc },
1302 /* restore the 2nd MDI child */
1303 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
1304 { HCBT_MINMAX, hook },
1305 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOZORDER|0x8000 },
1306 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1307 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1308 { WM_SIZE, sent|defwinproc },
1309 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
1311 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1312 { WM_NCCALCSIZE, sent|wparam, 1 },
1313 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1315 /* bring the 1st MDI child to top */
1316 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1317 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1318 { HCBT_SETFOCUS, hook },
1319 { WM_KILLFOCUS, sent|defwinproc },
1320 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
1321 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1322 { WM_SETFOCUS, sent }, /* in MDI client */
1323 { HCBT_SETFOCUS, hook },
1324 { WM_KILLFOCUS, sent }, /* in MDI client */
1325 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1326 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1327 { WM_SETFOCUS, sent|defwinproc },
1328 { WM_MDIACTIVATE, sent|defwinproc },
1329 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1331 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1332 { WM_SHOWWINDOW, sent|wparam, 1 },
1333 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1334 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1335 { WM_MDIREFRESHMENU, sent },
1337 { HCBT_DESTROYWND, hook },
1338 /* Win2k sends wparam set to
1339 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1340 * while Win9x doesn't bother to set child window id according to
1341 * CLIENTCREATESTRUCT.idFirstChild
1343 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1344 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
1345 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1346 { WM_ERASEBKGND, sent|parent|optional },
1347 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1349 { WM_DESTROY, sent|defwinproc },
1350 { WM_NCDESTROY, sent|defwinproc },
1353 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1354 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
1355 { WM_MDIDESTROY, sent }, /* in MDI client */
1356 { WM_SHOWWINDOW, sent|wparam, 0 },
1357 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1358 { WM_ERASEBKGND, sent|parent|optional },
1359 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1361 { HCBT_SETFOCUS, hook },
1362 { WM_KILLFOCUS, sent },
1363 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1364 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1365 { WM_SETFOCUS, sent }, /* in MDI client */
1366 { HCBT_SETFOCUS, hook },
1367 { WM_KILLFOCUS, sent }, /* in MDI client */
1368 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1369 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1370 { WM_SETFOCUS, sent },
1373 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1374 { WM_NCCALCSIZE, sent|wparam, 1 },
1375 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1378 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1379 { WM_NCCALCSIZE, sent|wparam, 1 },
1380 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1381 { WM_MOVE, sent|defwinproc },
1382 { WM_SIZE, sent|defwinproc },
1385 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1386 { WM_NCCALCSIZE, sent|wparam, 1 },
1387 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1391 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1392 { WM_NCCALCSIZE, sent|wparam, 1 },
1393 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1394 { WM_SIZE, sent|defwinproc },
1397 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1398 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1399 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1402 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1403 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1404 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1405 { WM_MOVE, sent|defwinproc },
1406 { WM_SIZE, sent|defwinproc },
1409 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1410 { WM_NCCALCSIZE, sent|wparam, 1 },
1411 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1415 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOZORDER },
1416 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1417 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1418 { WM_SIZE, sent|defwinproc },
1421 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1422 { WM_NCCALCSIZE, sent|wparam, 1 },
1423 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1425 { WM_NCACTIVATE, sent|wparam, 0 },
1426 { WM_MDIACTIVATE, sent },
1428 { HCBT_MINMAX, hook },
1429 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
1430 { WM_NCCALCSIZE, sent|wparam, 1 },
1431 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1432 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE|0x8000 },
1433 { WM_SIZE, sent|defwinproc },
1436 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1437 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1438 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1441 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1442 { WM_NCCALCSIZE, sent|wparam, 1 },
1443 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1444 { WM_MOVE, sent|defwinproc },
1445 { WM_SIZE, sent|defwinproc },
1448 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1449 { WM_NCCALCSIZE, sent|wparam, 1 },
1450 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1453 { HCBT_SETFOCUS, hook },
1454 { WM_KILLFOCUS, sent },
1455 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1456 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1457 { WM_SETFOCUS, sent }, /* in MDI client */
1459 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
1461 { HCBT_DESTROYWND, hook },
1462 /* Win2k sends wparam set to
1463 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1464 * while Win9x doesn't bother to set child window id according to
1465 * CLIENTCREATESTRUCT.idFirstChild
1467 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1469 { WM_SHOWWINDOW, sent|wparam, 0 },
1470 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1471 { WM_ERASEBKGND, sent|parent|optional },
1472 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1474 { WM_DESTROY, sent },
1475 { WM_NCDESTROY, sent },
1478 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1479 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
1480 { HCBT_MINMAX, hook },
1481 { WM_GETMINMAXINFO, sent },
1482 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1483 { WM_NCCALCSIZE, sent|wparam, 1 },
1484 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1486 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1487 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1488 { HCBT_SETFOCUS, hook },
1489 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1490 { WM_SETFOCUS, sent }, /* in MDI client */
1491 { HCBT_SETFOCUS, hook },
1492 { WM_KILLFOCUS, sent }, /* in MDI client */
1493 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1494 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1495 { WM_SETFOCUS, sent|defwinproc },
1496 { WM_MDIACTIVATE, sent|defwinproc },
1497 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1498 { WM_SIZE, sent|defwinproc },
1500 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1501 { WM_NCCALCSIZE, sent|wparam, 1 },
1502 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1505 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1506 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
1507 { HCBT_MINMAX, hook },
1508 { WM_GETMINMAXINFO, sent },
1509 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1510 { WM_NCCALCSIZE, sent|wparam, 1 },
1511 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1512 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1513 { WM_SIZE, sent|defwinproc },
1515 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1516 { WM_NCCALCSIZE, sent|wparam, 1 },
1517 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1520 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
1521 static const struct message WmRestoreMDIchildVisibleSeq[] = {
1522 { HCBT_MINMAX, hook },
1523 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1524 { WM_NCCALCSIZE, sent|wparam, 1 },
1525 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1526 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1527 { WM_SIZE, sent|defwinproc },
1529 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1530 { WM_NCCALCSIZE, sent|wparam, 1 },
1531 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1534 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1535 static const struct message WmRestoreMDIchildInisibleSeq[] = {
1536 { HCBT_MINMAX, hook },
1537 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1538 { WM_NCCALCSIZE, sent|wparam, 1 },
1539 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1540 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1541 { WM_SIZE, sent|defwinproc },
1543 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1544 { WM_NCCALCSIZE, sent|wparam, 1 },
1545 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1549 static HWND mdi_client;
1550 static WNDPROC old_mdi_client_proc;
1552 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1556 /* do not log painting messages */
1557 if (message != WM_PAINT &&
1558 message != WM_ERASEBKGND &&
1559 message != WM_NCPAINT &&
1560 message != WM_GETTEXT &&
1561 message != WM_MDIGETACTIVE)
1563 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1567 case WM_WINDOWPOSCHANGING:
1568 case WM_WINDOWPOSCHANGED:
1570 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1572 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1573 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1574 winpos->hwnd, winpos->hwndInsertAfter,
1575 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1577 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1578 * in the high word for internal purposes
1580 wParam = winpos->flags & 0xffff;
1585 msg.message = message;
1586 msg.flags = sent|wparam|lparam;
1587 msg.wParam = wParam;
1588 msg.lParam = lParam;
1592 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1595 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1597 static long defwndproc_counter = 0;
1601 /* do not log painting messages */
1602 if (message != WM_PAINT &&
1603 message != WM_ERASEBKGND &&
1604 message != WM_NCPAINT &&
1605 message != WM_GETTEXT)
1607 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1611 case WM_WINDOWPOSCHANGING:
1612 case WM_WINDOWPOSCHANGED:
1614 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1616 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1617 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1618 winpos->hwnd, winpos->hwndInsertAfter,
1619 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1621 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1622 * in the high word for internal purposes
1624 wParam = winpos->flags & 0xffff;
1628 case WM_MDIACTIVATE:
1630 HWND active, client = GetParent(hwnd);
1632 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1634 if (hwnd == (HWND)lParam) /* if we are being activated */
1635 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
1637 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
1642 msg.message = message;
1643 msg.flags = sent|wparam|lparam;
1644 if (defwndproc_counter) msg.flags |= defwinproc;
1645 msg.wParam = wParam;
1646 msg.lParam = lParam;
1650 defwndproc_counter++;
1651 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1652 defwndproc_counter--;
1657 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1659 static long defwndproc_counter = 0;
1663 /* do not log painting messages */
1664 if (message != WM_PAINT &&
1665 message != WM_ERASEBKGND &&
1666 message != WM_NCPAINT &&
1667 message != WM_GETTEXT)
1669 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1673 case WM_WINDOWPOSCHANGING:
1674 case WM_WINDOWPOSCHANGED:
1676 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1678 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1679 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1680 winpos->hwnd, winpos->hwndInsertAfter,
1681 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1683 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1684 * in the high word for internal purposes
1686 wParam = winpos->flags & 0xffff;
1691 msg.message = message;
1692 msg.flags = sent|wparam|lparam;
1693 if (defwndproc_counter) msg.flags |= defwinproc;
1694 msg.wParam = wParam;
1695 msg.lParam = lParam;
1699 defwndproc_counter++;
1700 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
1701 defwndproc_counter--;
1706 static BOOL mdi_RegisterWindowClasses(void)
1711 cls.lpfnWndProc = mdi_frame_wnd_proc;
1714 cls.hInstance = GetModuleHandleA(0);
1716 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1717 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1718 cls.lpszMenuName = NULL;
1719 cls.lpszClassName = "MDI_frame_class";
1720 if (!RegisterClassA(&cls)) return FALSE;
1722 cls.lpfnWndProc = mdi_child_wnd_proc;
1723 cls.lpszClassName = "MDI_child_class";
1724 if (!RegisterClassA(&cls)) return FALSE;
1726 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
1727 old_mdi_client_proc = cls.lpfnWndProc;
1728 cls.hInstance = GetModuleHandleA(0);
1729 cls.lpfnWndProc = mdi_client_hook_proc;
1730 cls.lpszClassName = "MDI_client_class";
1731 if (!RegisterClassA(&cls)) assert(0);
1736 static void test_mdi_messages(void)
1738 MDICREATESTRUCTA mdi_cs;
1739 CLIENTCREATESTRUCT client_cs;
1740 HWND mdi_frame, mdi_child, mdi_child2, active_child;
1742 HMENU hMenu = CreateMenu();
1744 assert(mdi_RegisterWindowClasses());
1748 trace("creating MDI frame window\n");
1749 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1750 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1751 WS_MAXIMIZEBOX | WS_VISIBLE,
1752 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1753 GetDesktopWindow(), hMenu,
1754 GetModuleHandleA(0), NULL);
1756 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
1758 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1759 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
1761 trace("creating MDI client window\n");
1762 client_cs.hWindowMenu = 0;
1763 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
1764 mdi_client = CreateWindowExA(0, "MDI_client_class",
1766 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
1768 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
1770 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
1772 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1773 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
1775 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1776 ok(!active_child, "wrong active MDI child %p\n", active_child);
1777 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1782 trace("creating invisible MDI child window\n");
1783 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1785 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1786 mdi_client, 0, GetModuleHandleA(0), NULL);
1790 ShowWindow(mdi_child, SW_SHOWNORMAL);
1791 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
1793 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1794 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1796 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1797 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1799 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1800 ok(!active_child, "wrong active MDI child %p\n", active_child);
1801 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1803 ShowWindow(mdi_child, SW_HIDE);
1804 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
1807 ShowWindow(mdi_child, SW_SHOW);
1808 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
1810 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1811 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1813 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1814 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1816 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1817 ok(!active_child, "wrong active MDI child %p\n", active_child);
1818 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1820 DestroyWindow(mdi_child);
1823 trace("creating visible MDI child window\n");
1824 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1825 WS_CHILD | WS_VISIBLE,
1826 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1827 mdi_client, 0, GetModuleHandleA(0), NULL);
1829 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", TRUE);
1831 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1832 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1834 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1835 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
1837 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1838 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
1839 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1842 DestroyWindow(mdi_child);
1843 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
1845 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1846 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1848 /* Win2k: MDI client still returns a just destroyed child as active
1849 * Win9x: MDI client returns 0
1851 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1852 ok(active_child == mdi_child || /* win2k */
1853 !active_child, /* win9x */
1854 "wrong active MDI child %p\n", active_child);
1855 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1859 trace("creating invisible MDI child window\n");
1860 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1862 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1863 mdi_client, 0, GetModuleHandleA(0), NULL);
1865 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
1867 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
1868 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
1870 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1871 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1873 /* Win2k: MDI client still returns a just destroyed child as active
1874 * Win9x: MDI client returns mdi_child2
1876 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1877 ok(active_child == mdi_child || /* win2k */
1878 active_child == mdi_child2, /* win9x */
1879 "wrong active MDI child %p\n", active_child);
1880 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1883 ShowWindow(mdi_child2, SW_MAXIMIZE);
1884 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
1886 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1887 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
1889 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1890 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1891 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1894 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1895 ok(GetFocus() == mdi_child2 || /* win2k */
1896 GetFocus() == 0, /* win9x */
1897 "wrong focus window %p\n", GetFocus());
1902 ShowWindow(mdi_child2, SW_HIDE);
1903 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1905 ShowWindow(mdi_child2, SW_RESTORE);
1906 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
1909 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1910 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
1912 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1913 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1914 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1920 ShowWindow(mdi_child2, SW_HIDE);
1921 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1923 ShowWindow(mdi_child2, SW_SHOW);
1924 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", TRUE);
1926 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1927 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1929 ShowWindow(mdi_child2, SW_MAXIMIZE);
1930 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
1932 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1933 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1935 ShowWindow(mdi_child2, SW_RESTORE);
1936 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
1938 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1939 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1944 ShowWindow(mdi_child2, SW_HIDE);
1945 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1947 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1948 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1950 DestroyWindow(mdi_child2);
1951 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", TRUE);
1953 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1954 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1956 /* test for maximized MDI children */
1957 trace("creating maximized visible MDI child window 1\n");
1958 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1959 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
1960 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1961 mdi_client, 0, GetModuleHandleA(0), NULL);
1963 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
1964 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
1966 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1967 ok(GetFocus() == mdi_child || /* win2k */
1968 GetFocus() == 0, /* win9x */
1969 "wrong focus window %p\n", GetFocus());
1971 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1972 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
1973 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1976 trace("creating maximized visible MDI child window 2\n");
1977 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1978 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
1979 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1980 mdi_client, 0, GetModuleHandleA(0), NULL);
1982 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
1983 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
1984 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
1986 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1987 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
1989 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1990 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1991 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1994 trace("destroying maximized visible MDI child window 2\n");
1995 DestroyWindow(mdi_child2);
1996 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
1998 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2000 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2001 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2003 /* Win2k: MDI client still returns a just destroyed child as active
2004 * Win9x: MDI client returns 0
2006 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2007 ok(active_child == mdi_child2 || /* win2k */
2008 !active_child, /* win9x */
2009 "wrong active MDI child %p\n", active_child);
2012 ShowWindow(mdi_child, SW_MAXIMIZE);
2013 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2016 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2017 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2019 trace("re-creating maximized visible MDI child window 2\n");
2020 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2021 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2022 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2023 mdi_client, 0, GetModuleHandleA(0), NULL);
2025 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2026 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2027 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2029 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2030 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2032 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2033 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2034 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2037 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
2038 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
2039 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
2041 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2042 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2043 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2045 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2046 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2047 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2050 DestroyWindow(mdi_child);
2051 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2053 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2054 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2056 /* Win2k: MDI client still returns a just destroyed child as active
2057 * Win9x: MDI client returns 0
2059 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2060 ok(active_child == mdi_child || /* win2k */
2061 !active_child, /* win9x */
2062 "wrong active MDI child %p\n", active_child);
2064 /* end of test for maximized MDI children */
2066 mdi_cs.szClass = "MDI_child_Class";
2067 mdi_cs.szTitle = "MDI child";
2068 mdi_cs.hOwner = GetModuleHandleA(0);
2071 mdi_cs.cx = CW_USEDEFAULT;
2072 mdi_cs.cy = CW_USEDEFAULT;
2073 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
2075 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
2076 ok(mdi_child != 0, "MDI child creation failed\n");
2077 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
2079 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
2081 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2082 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2084 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
2085 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2086 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2088 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2089 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2090 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2093 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
2094 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
2096 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
2097 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2098 ok(!active_child, "wrong active MDI child %p\n", active_child);
2103 DestroyWindow(mdi_client);
2104 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
2106 DestroyWindow(mdi_frame);
2107 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
2109 /************************* End of MDI test **********************************/
2111 static void test_WM_SETREDRAW(HWND hwnd)
2113 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
2117 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
2118 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
2120 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
2121 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
2124 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
2125 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
2127 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2128 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
2130 /* restore original WS_VISIBLE state */
2131 SetWindowLongA(hwnd, GWL_STYLE, style);
2136 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2140 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2142 msg.message = message;
2143 msg.flags = sent|wparam|lparam;
2144 msg.wParam = wParam;
2145 msg.lParam = lParam;
2148 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2149 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2153 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2155 DWORD style, exstyle;
2158 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2159 style = GetWindowLongA(hwnd, GWL_STYLE);
2160 /* do not be confused by WS_DLGFRAME set */
2161 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2163 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2164 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2166 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2167 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2168 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
2170 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", TRUE);
2172 style = GetWindowLongA(hwnd, GWL_STYLE);
2173 if (set) ok(style & set, "style %08lx should be set\n", set);
2174 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2176 /* a subsequent call should do nothing */
2177 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2178 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2182 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2183 ok(GetScrollRange(hwnd, ctl, &xmin, &xmax), "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
2184 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2185 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
2186 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
2189 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2191 DWORD style, exstyle;
2194 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2195 style = GetWindowLongA(hwnd, GWL_STYLE);
2196 /* do not be confused by WS_DLGFRAME set */
2197 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2199 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2200 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2202 si.cbSize = sizeof(si);
2203 si.fMask = SIF_RANGE;
2206 SetScrollInfo(hwnd, ctl, &si, TRUE);
2207 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2208 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
2210 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", TRUE);
2212 style = GetWindowLongA(hwnd, GWL_STYLE);
2213 if (set) ok(style & set, "style %08lx should be set\n", set);
2214 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2216 /* a subsequent call should do nothing */
2217 SetScrollInfo(hwnd, ctl, &si, TRUE);
2218 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2220 si.fMask = SIF_PAGE;
2222 SetScrollInfo(hwnd, ctl, &si, FALSE);
2223 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2227 SetScrollInfo(hwnd, ctl, &si, FALSE);
2228 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2230 si.fMask = SIF_RANGE;
2231 si.nMin = 0xdeadbeef;
2232 si.nMax = 0xdeadbeef;
2233 ok(GetScrollInfo(hwnd, ctl, &si), "GetScrollInfo error %ld\n", GetLastError());
2234 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2235 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
2236 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
2239 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2240 static void test_scroll_messages(HWND hwnd)
2247 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
2248 if (sequence->message != WmGetScrollRangeSeq[0].message)
2249 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2250 /* values of min and max are undefined */
2253 ok(SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE), "SetScrollRange error %ld\n", GetLastError());
2254 if (sequence->message != WmSetScrollRangeSeq[0].message)
2255 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2260 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
2261 if (sequence->message != WmGetScrollRangeSeq[0].message)
2262 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2263 /* values of min and max are undefined */
2266 si.cbSize = sizeof(si);
2267 si.fMask = SIF_RANGE;
2270 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2271 if (sequence->message != WmSetScrollRangeSeq[0].message)
2272 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2275 si.fMask = SIF_PAGE;
2277 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2278 if (sequence->message != WmSetScrollRangeSeq[0].message)
2279 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2284 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2285 if (sequence->message != WmSetScrollRangeSeq[0].message)
2286 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2289 si.fMask = SIF_RANGE;
2290 si.nMin = 0xdeadbeef;
2291 si.nMax = 0xdeadbeef;
2292 ok(GetScrollInfo(hwnd, SB_CTL, &si), "GetScrollInfo error %ld\n", GetLastError());
2293 if (sequence->message != WmGetScrollInfoSeq[0].message)
2294 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2295 /* values of min and max are undefined */
2298 /* set WS_HSCROLL */
2299 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2300 /* clear WS_HSCROLL */
2301 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2303 /* set WS_HSCROLL */
2304 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2305 /* clear WS_HSCROLL */
2306 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2308 /* set WS_VSCROLL */
2309 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2310 /* clear WS_VSCROLL */
2311 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2313 /* set WS_VSCROLL */
2314 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2315 /* clear WS_VSCROLL */
2316 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2319 /* test if we receive the right sequence of messages */
2320 static void test_messages(void)
2322 HWND hwnd, hparent, hchild;
2323 HWND hchild2, hbutton;
2327 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2328 100, 100, 200, 200, 0, 0, 0, NULL);
2329 ok (hwnd != 0, "Failed to create overlapped window\n");
2330 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2332 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2333 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
2334 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
2336 /* test WM_SETREDRAW on a not visible top level window */
2337 test_WM_SETREDRAW(hwnd);
2339 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2340 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
2341 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
2343 ok(GetActiveWindow() == hwnd, "window should be active\n");
2344 ok(GetFocus() == hwnd, "window should have input focus\n");
2345 ShowWindow(hwnd, SW_HIDE);
2346 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
2348 ShowWindow(hwnd, SW_SHOW);
2349 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
2351 ok(GetActiveWindow() == hwnd, "window should be active\n");
2352 ok(GetFocus() == hwnd, "window should have input focus\n");
2353 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2354 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", TRUE);
2355 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
2357 /* test WM_SETREDRAW on a visible top level window */
2358 ShowWindow(hwnd, SW_SHOW);
2359 test_WM_SETREDRAW(hwnd);
2361 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
2362 test_scroll_messages(hwnd);
2364 DestroyWindow(hwnd);
2365 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
2367 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2368 100, 100, 200, 200, 0, 0, 0, NULL);
2369 ok (hparent != 0, "Failed to create parent window\n");
2372 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
2373 0, 0, 10, 10, hparent, 0, 0, NULL);
2374 ok (hchild != 0, "Failed to create child window\n");
2375 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
2376 DestroyWindow(hchild);
2379 /* visible child window with a caption */
2380 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
2381 WS_CHILD | WS_VISIBLE | WS_CAPTION,
2382 0, 0, 10, 10, hparent, 0, 0, NULL);
2383 ok (hchild != 0, "Failed to create child window\n");
2384 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
2386 trace("testing scroll APIs on a visible child window %p\n", hchild);
2387 test_scroll_messages(hchild);
2389 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2390 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
2392 DestroyWindow(hchild);
2395 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2396 0, 0, 10, 10, hparent, 0, 0, NULL);
2397 ok (hchild != 0, "Failed to create child window\n");
2398 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2400 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
2401 100, 100, 50, 50, hparent, 0, 0, NULL);
2402 ok (hchild2 != 0, "Failed to create child2 window\n");
2405 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
2406 0, 100, 50, 50, hchild, 0, 0, NULL);
2407 ok (hbutton != 0, "Failed to create button window\n");
2409 /* test WM_SETREDRAW on a not visible child window */
2410 test_WM_SETREDRAW(hchild);
2412 ShowWindow(hchild, SW_SHOW);
2413 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2415 ShowWindow(hchild, SW_HIDE);
2416 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
2418 ShowWindow(hchild, SW_SHOW);
2419 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2421 /* test WM_SETREDRAW on a visible child window */
2422 test_WM_SETREDRAW(hchild);
2424 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
2425 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
2427 ShowWindow(hchild, SW_HIDE);
2429 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2430 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
2432 ShowWindow(hchild, SW_HIDE);
2434 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2435 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
2437 /* DestroyWindow sequence below expects that a child has focus */
2441 DestroyWindow(hchild);
2442 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
2443 DestroyWindow(hchild2);
2444 DestroyWindow(hbutton);
2447 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
2448 0, 0, 100, 100, hparent, 0, 0, NULL);
2449 ok (hchild != 0, "Failed to create child popup window\n");
2450 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
2451 DestroyWindow(hchild);
2453 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
2455 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
2456 0, 0, 100, 100, hparent, 0, 0, NULL);
2457 ok (hchild != 0, "Failed to create popup window\n");
2458 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2459 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2460 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2462 ShowWindow(hchild, SW_SHOW);
2463 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2465 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2466 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2468 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2469 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
2470 DestroyWindow(hchild);
2472 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2473 * changes nothing in message sequences.
2476 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
2477 0, 0, 100, 100, hparent, 0, 0, NULL);
2478 ok (hchild != 0, "Failed to create popup window\n");
2479 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2480 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2481 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2483 ShowWindow(hchild, SW_SHOW);
2484 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2486 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2487 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2488 DestroyWindow(hchild);
2491 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
2492 0, 0, 100, 100, hparent, 0, 0, NULL);
2493 ok(hwnd != 0, "Failed to create custom dialog window\n");
2494 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
2496 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
2497 test_scroll_messages(hwnd);
2500 after_end_dialog = 1;
2501 EndDialog( hwnd, 0 );
2502 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
2504 DestroyWindow(hwnd);
2505 after_end_dialog = 0;
2508 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
2509 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
2511 /* test showing child with hidden parent */
2512 ShowWindow( hparent, SW_HIDE );
2515 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2516 0, 0, 10, 10, hparent, 0, 0, NULL);
2517 ok (hchild != 0, "Failed to create child window\n");
2518 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2520 ShowWindow( hchild, SW_SHOW );
2521 ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", TRUE);
2522 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2523 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2525 ShowWindow( hchild, SW_HIDE );
2526 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", TRUE);
2527 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
2528 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2530 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2531 ok_sequence(WmShowChildInvisibleParentSeq_2, "SetWindowPos:show child with invisible parent", TRUE);
2532 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2533 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2535 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2536 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", TRUE);
2537 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
2538 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2540 DestroyWindow(hchild);
2541 DestroyWindow(hparent);
2544 /* Message sequence for SetMenu */
2545 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
2546 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
2548 hmenu = CreateMenu();
2549 ok (hmenu != 0, "Failed to create menu\n");
2550 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
2551 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2552 100, 100, 200, 200, 0, hmenu, 0, NULL);
2553 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2554 ok (SetMenu(hwnd, 0), "SetMenu\n");
2555 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
2556 ok (SetMenu(hwnd, 0), "SetMenu\n");
2557 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
2558 ShowWindow(hwnd, SW_SHOW);
2560 ok (SetMenu(hwnd, 0), "SetMenu\n");
2561 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
2562 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
2563 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
2565 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
2566 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
2568 DestroyWindow(hwnd);
2571 /* Message sequence for EnableWindow */
2572 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2573 100, 100, 200, 200, 0, 0, 0, NULL);
2574 ok (hparent != 0, "Failed to create parent window\n");
2575 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
2576 0, 0, 10, 10, hparent, 0, 0, NULL);
2577 ok (hchild != 0, "Failed to create child window\n");
2582 EnableWindow(hparent, FALSE);
2583 ok_sequence(WmEnableWindowSeq, "EnableWindow", FALSE);
2585 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
2587 PostMessage( hparent, WM_USER, 0, 0 );
2588 PostMessage( hparent, WM_USER+1, 0, 0 );
2589 /* PeekMessage(NULL) fails, but still removes the message */
2590 SetLastError(0xdeadbeef);
2591 ok( !PeekMessage( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
2592 ok( GetLastError() == ERROR_NOACCESS, "last error is %ld\n", GetLastError() );
2593 ok( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
2594 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
2596 DestroyWindow(hchild);
2597 DestroyWindow(hparent);
2601 /****************** button message test *************************/
2602 static const struct message WmSetFocusButtonSeq[] =
2604 { HCBT_SETFOCUS, hook },
2605 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2606 { WM_SETFOCUS, sent|wparam, 0 },
2607 { WM_CTLCOLORBTN, sent|defwinproc },
2610 static const struct message WmKillFocusButtonSeq[] =
2612 { HCBT_SETFOCUS, hook },
2613 { WM_KILLFOCUS, sent|wparam, 0 },
2614 { WM_CTLCOLORBTN, sent|defwinproc },
2615 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2618 static const struct message WmSetFocusStaticSeq[] =
2620 { HCBT_SETFOCUS, hook },
2621 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2622 { WM_SETFOCUS, sent|wparam, 0 },
2623 { WM_CTLCOLORSTATIC, sent|defwinproc },
2626 static const struct message WmKillFocusStaticSeq[] =
2628 { HCBT_SETFOCUS, hook },
2629 { WM_KILLFOCUS, sent|wparam, 0 },
2630 { WM_CTLCOLORSTATIC, sent|defwinproc },
2631 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2634 static const struct message WmLButtonDownSeq[] =
2636 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
2637 { HCBT_SETFOCUS, hook },
2638 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2639 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
2640 { WM_CTLCOLORBTN, sent|defwinproc },
2641 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
2642 { WM_CTLCOLORBTN, sent|defwinproc },
2645 static const struct message WmLButtonUpSeq[] =
2647 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
2648 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
2649 { WM_CTLCOLORBTN, sent|defwinproc },
2650 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
2654 static WNDPROC old_button_proc;
2656 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2658 static long defwndproc_counter = 0;
2662 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2664 msg.message = message;
2665 msg.flags = sent|wparam|lparam;
2666 if (defwndproc_counter) msg.flags |= defwinproc;
2667 msg.wParam = wParam;
2668 msg.lParam = lParam;
2671 if (message == BM_SETSTATE)
2672 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
2674 defwndproc_counter++;
2675 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
2676 defwndproc_counter--;
2681 static void subclass_button(void)
2685 if (!GetClassInfoA(0, "button", &cls)) assert(0);
2687 old_button_proc = cls.lpfnWndProc;
2689 cls.hInstance = GetModuleHandle(0);
2690 cls.lpfnWndProc = button_hook_proc;
2691 cls.lpszClassName = "my_button_class";
2692 if (!RegisterClassA(&cls)) assert(0);
2695 static void test_button_messages(void)
2701 const struct message *setfocus;
2702 const struct message *killfocus;
2704 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
2705 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2706 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
2707 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2708 { BS_CHECKBOX, DLGC_BUTTON,
2709 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2710 { BS_AUTOCHECKBOX, DLGC_BUTTON,
2711 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2712 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
2713 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2714 { BS_3STATE, DLGC_BUTTON,
2715 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2716 { BS_AUTO3STATE, DLGC_BUTTON,
2717 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2718 { BS_GROUPBOX, DLGC_STATIC,
2719 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2720 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
2721 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2722 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
2723 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2724 { BS_OWNERDRAW, DLGC_BUTTON,
2725 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
2733 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
2735 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
2736 0, 0, 50, 14, 0, 0, 0, NULL);
2737 ok(hwnd != 0, "Failed to create button window\n");
2739 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
2740 ok(dlg_code == button[i].dlg_code, "%d: wrong dlg_code %08lx\n", i, dlg_code);
2742 ShowWindow(hwnd, SW_SHOW);
2747 trace("button style %08lx\n", button[i].style);
2749 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
2752 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
2754 DestroyWindow(hwnd);
2757 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
2758 0, 0, 50, 14, 0, 0, 0, NULL);
2759 ok(hwnd != 0, "Failed to create button window\n");
2764 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
2765 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
2767 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
2768 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONDOWN on a button", FALSE);
2769 DestroyWindow(hwnd);
2772 /************* painting message test ********************/
2774 static void dump_region(HRGN hrgn)
2777 RGNDATA *data = NULL;
2782 printf( "null region\n" );
2785 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
2786 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
2787 GetRegionData( hrgn, size, data );
2788 printf("%ld rects:", data->rdh.nCount );
2789 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
2790 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
2792 HeapFree( GetProcessHeap(), 0, data );
2795 static void check_update_rgn( HWND hwnd, HRGN hrgn )
2799 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
2800 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
2802 ret = GetUpdateRgn( hwnd, update, FALSE );
2803 ok( ret != ERROR, "GetUpdateRgn failed\n" );
2804 if (ret == NULLREGION)
2806 ok( !hrgn, "Update region shouldn't be empty\n" );
2810 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
2812 ok( 0, "Regions are different\n" );
2813 if (winetest_debug > 0)
2815 printf( "Update region: " );
2816 dump_region( update );
2817 printf( "Wanted region: " );
2818 dump_region( hrgn );
2822 GetRgnBox( update, &r1 );
2823 GetUpdateRect( hwnd, &r2, FALSE );
2824 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
2825 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
2826 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
2828 DeleteObject( tmp );
2829 DeleteObject( update );
2832 static const struct message WmInvalidateRgn[] = {
2833 { WM_NCPAINT, sent },
2834 { WM_GETTEXT, sent|defwinproc|optional },
2838 static const struct message WmGetUpdateRect[] = {
2839 { WM_NCPAINT, sent },
2840 { WM_GETTEXT, sent|defwinproc|optional },
2845 static const struct message WmInvalidateFull[] = {
2846 { WM_NCPAINT, sent|wparam, 1 },
2847 { WM_GETTEXT, sent|defwinproc|optional },
2851 static const struct message WmInvalidateErase[] = {
2852 { WM_NCPAINT, sent|wparam, 1 },
2853 { WM_GETTEXT, sent|defwinproc|optional },
2854 { WM_ERASEBKGND, sent },
2858 static const struct message WmInvalidatePaint[] = {
2860 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
2861 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2865 static const struct message WmInvalidateErasePaint[] = {
2867 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
2868 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2869 { WM_ERASEBKGND, sent|beginpaint },
2873 static const struct message WmInvalidateErasePaint2[] = {
2875 { WM_NCPAINT, sent|beginpaint },
2876 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2877 { WM_ERASEBKGND, sent|beginpaint },
2881 static const struct message WmErase[] = {
2882 { WM_ERASEBKGND, sent },
2886 static const struct message WmPaint[] = {
2891 static const struct message WmParentOnlyPaint[] = {
2892 { WM_PAINT, sent|parent },
2896 static const struct message WmInvalidateParent[] = {
2897 { WM_NCPAINT, sent|parent },
2898 { WM_GETTEXT, sent|defwinproc|parent|optional },
2899 { WM_ERASEBKGND, sent|parent },
2903 static const struct message WmInvalidateParentChild[] = {
2904 { WM_NCPAINT, sent|parent },
2905 { WM_GETTEXT, sent|defwinproc|parent|optional },
2906 { WM_ERASEBKGND, sent|parent },
2907 { WM_NCPAINT, sent },
2908 { WM_GETTEXT, sent|defwinproc|optional },
2909 { WM_ERASEBKGND, sent },
2913 static const struct message WmInvalidateParentChild2[] = {
2914 { WM_ERASEBKGND, sent|parent },
2915 { WM_NCPAINT, sent },
2916 { WM_GETTEXT, sent|defwinproc|optional },
2917 { WM_ERASEBKGND, sent },
2921 static const struct message WmParentPaint[] = {
2922 { WM_PAINT, sent|parent },
2927 static const struct message WmParentPaintNc[] = {
2928 { WM_PAINT, sent|parent },
2930 { WM_NCPAINT, sent|beginpaint },
2931 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2932 { WM_ERASEBKGND, sent|beginpaint },
2936 static const struct message WmChildPaintNc[] = {
2938 { WM_NCPAINT, sent|beginpaint },
2939 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2940 { WM_ERASEBKGND, sent|beginpaint },
2944 static const struct message WmParentErasePaint[] = {
2945 { WM_PAINT, sent|parent },
2946 { WM_NCPAINT, sent|parent|beginpaint },
2947 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
2948 { WM_ERASEBKGND, sent|parent|beginpaint },
2950 { WM_NCPAINT, sent|beginpaint },
2951 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2952 { WM_ERASEBKGND, sent|beginpaint },
2956 static const struct message WmParentOnlyNcPaint[] = {
2957 { WM_PAINT, sent|parent },
2958 { WM_NCPAINT, sent|parent|beginpaint },
2959 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
2963 static const struct message WmSetParentStyle[] = {
2964 { WM_STYLECHANGING, sent|parent },
2965 { WM_STYLECHANGED, sent|parent },
2969 static void test_paint_messages(void)
2974 HWND hparent, hchild;
2975 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2976 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
2977 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2978 100, 100, 200, 200, 0, 0, 0, NULL);
2979 ok (hwnd != 0, "Failed to create overlapped window\n");
2981 ShowWindow( hwnd, SW_SHOW );
2982 UpdateWindow( hwnd );
2984 /* try to flush pending X expose events */
2985 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
2986 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
2988 check_update_rgn( hwnd, 0 );
2989 SetRectRgn( hrgn, 10, 10, 20, 20 );
2990 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
2991 check_update_rgn( hwnd, hrgn );
2992 SetRectRgn( hrgn2, 20, 20, 30, 30 );
2993 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
2994 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
2995 check_update_rgn( hwnd, hrgn );
2996 /* validate everything */
2997 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
2998 check_update_rgn( hwnd, 0 );
2999 /* now with frame */
3000 SetRectRgn( hrgn, -5, -5, 20, 20 );
3002 /* flush pending messages */
3003 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3006 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3007 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3009 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
3010 check_update_rgn( hwnd, hrgn );
3013 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3014 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3017 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3018 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
3020 GetClientRect( hwnd, &rect );
3021 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
3022 check_update_rgn( hwnd, hrgn );
3025 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
3026 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3029 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
3030 ok_sequence( WmInvalidatePaint, "InvalidatePaint", TRUE );
3031 check_update_rgn( hwnd, 0 );
3034 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
3035 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
3036 check_update_rgn( hwnd, 0 );
3039 SetRectRgn( hrgn, 0, 0, 100, 100 );
3040 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3041 SetRectRgn( hrgn, 0, 0, 50, 100 );
3042 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
3043 SetRectRgn( hrgn, 50, 0, 100, 100 );
3044 check_update_rgn( hwnd, hrgn );
3045 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3046 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
3047 check_update_rgn( hwnd, 0 );
3050 SetRectRgn( hrgn, 0, 0, 100, 100 );
3051 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3052 SetRectRgn( hrgn, 0, 0, 100, 50 );
3053 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3054 ok_sequence( WmErase, "Erase", FALSE );
3055 SetRectRgn( hrgn, 0, 50, 100, 100 );
3056 check_update_rgn( hwnd, hrgn );
3059 SetRectRgn( hrgn, 0, 0, 100, 100 );
3060 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3061 SetRectRgn( hrgn, 0, 0, 50, 50 );
3062 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
3063 ok_sequence( WmPaint, "Paint", TRUE );
3066 SetRectRgn( hrgn, -4, -4, -2, -2 );
3067 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3068 SetRectRgn( hrgn, -200, -200, -198, -198 );
3069 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
3070 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3073 SetRectRgn( hrgn, -4, -4, -2, -2 );
3074 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3075 SetRectRgn( hrgn, -4, -4, -3, -3 );
3076 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
3077 SetRectRgn( hrgn, 0, 0, 1, 1 );
3078 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
3079 ok_sequence( WmPaint, "Paint", TRUE );
3082 SetRectRgn( hrgn, -4, -4, -1, -1 );
3083 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3084 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
3085 /* make sure no WM_PAINT was generated */
3086 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3087 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3090 SetRectRgn( hrgn, -4, -4, -1, -1 );
3091 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3092 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
3094 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
3096 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
3097 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
3098 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
3099 ret = GetUpdateRect( hwnd, &rect, FALSE );
3100 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
3101 /* this will send WM_NCPAINT and validate the non client area */
3102 ret = GetUpdateRect( hwnd, &rect, TRUE );
3103 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
3105 DispatchMessage( &msg );
3107 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
3109 DestroyWindow( hwnd );
3111 /* now test with a child window */
3113 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
3114 100, 100, 200, 200, 0, 0, 0, NULL);
3115 ok (hparent != 0, "Failed to create parent window\n");
3117 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
3118 10, 10, 100, 100, hparent, 0, 0, NULL);
3119 ok (hchild != 0, "Failed to create child window\n");
3121 ShowWindow( hparent, SW_SHOW );
3122 UpdateWindow( hparent );
3123 UpdateWindow( hchild );
3124 /* try to flush pending X expose events */
3125 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3126 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3129 log_all_parent_messages++;
3131 SetRect( &rect, 0, 0, 50, 50 );
3132 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3133 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3134 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
3136 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3138 MapWindowPoints( hchild, hparent, &pt, 1 );
3139 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
3140 check_update_rgn( hchild, hrgn );
3141 SetRectRgn( hrgn, 0, 0, 50, 50 );
3142 check_update_rgn( hparent, hrgn );
3143 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3144 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
3145 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3146 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3148 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3149 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
3151 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3152 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3153 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
3154 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3155 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3157 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
3158 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3159 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
3161 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3163 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3164 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3165 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
3167 /* flush all paint messages */
3168 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3171 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
3172 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3173 SetRectRgn( hrgn, 0, 0, 50, 50 );
3174 check_update_rgn( hparent, hrgn );
3175 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3176 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3177 SetRectRgn( hrgn, 0, 0, 50, 50 );
3178 check_update_rgn( hparent, hrgn );
3180 /* flush all paint messages */
3181 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3182 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3185 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
3186 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3187 SetRectRgn( hrgn, 0, 0, 50, 50 );
3188 check_update_rgn( hparent, hrgn );
3189 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3190 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3191 SetRectRgn( hrgn2, 10, 10, 50, 50 );
3192 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
3193 check_update_rgn( hparent, hrgn );
3194 /* flush all paint messages */
3195 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3198 /* same as above but parent gets completely validated */
3199 SetRect( &rect, 20, 20, 30, 30 );
3200 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3201 SetRectRgn( hrgn, 20, 20, 30, 30 );
3202 check_update_rgn( hparent, hrgn );
3203 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3204 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3205 check_update_rgn( hparent, 0 ); /* no update region */
3206 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3207 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
3209 /* make sure RDW_VALIDATE on child doesn't have the same effect */
3211 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3212 SetRectRgn( hrgn, 20, 20, 30, 30 );
3213 check_update_rgn( hparent, hrgn );
3214 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
3215 SetRectRgn( hrgn, 20, 20, 30, 30 );
3216 check_update_rgn( hparent, hrgn );
3218 /* same as above but normal WM_PAINT doesn't validate parent */
3220 SetRect( &rect, 20, 20, 30, 30 );
3221 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3222 SetRectRgn( hrgn, 20, 20, 30, 30 );
3223 check_update_rgn( hparent, hrgn );
3224 /* no WM_PAINT in child while parent still pending */
3225 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3226 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3227 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3228 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
3231 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3232 /* no WM_PAINT in child while parent still pending */
3233 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3234 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3235 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
3236 /* now that parent is valid child should get WM_PAINT */
3237 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3238 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3239 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3240 ok_sequence( WmEmptySeq, "No other message", FALSE );
3242 /* same thing with WS_CLIPCHILDREN in parent */
3244 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3245 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3246 /* changing style invalidates non client area, but we need to invalidate something else to see it */
3247 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
3248 ok_sequence( WmEmptySeq, "No message", FALSE );
3249 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
3250 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
3253 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
3254 SetRectRgn( hrgn, 20, 20, 30, 30 );
3255 check_update_rgn( hparent, hrgn );
3256 /* no WM_PAINT in child while parent still pending */
3257 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3258 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3259 /* WM_PAINT in parent first */
3260 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3261 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
3263 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
3265 SetRect( &rect, 0, 0, 30, 30 );
3266 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
3267 SetRectRgn( hrgn, 0, 0, 30, 30 );
3268 check_update_rgn( hparent, hrgn );
3269 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3270 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
3272 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3274 SetRect( &rect, -10, 0, 30, 30 );
3275 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3276 SetRect( &rect, 0, 0, 20, 20 );
3277 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3278 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3279 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
3281 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3283 SetRect( &rect, -10, 0, 30, 30 );
3284 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3285 SetRect( &rect, 0, 0, 100, 100 );
3286 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3287 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3288 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
3289 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3290 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
3292 /* test RDW_INTERNALPAINT behavior */
3295 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
3296 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3297 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3299 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
3300 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3301 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3303 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3304 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3305 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3307 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3308 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3309 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3310 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3311 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3313 log_all_parent_messages--;
3314 DestroyWindow( hparent );
3316 DeleteObject( hrgn );
3317 DeleteObject( hrgn2 );
3326 static DWORD WINAPI thread_proc(void *param)
3329 struct wnd_event *wnd_event = (struct wnd_event *)param;
3331 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
3332 100, 100, 200, 200, 0, 0, 0, NULL);
3333 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
3335 SetEvent(wnd_event->event);
3337 while (GetMessage(&msg, 0, 0, 0))
3339 TranslateMessage(&msg);
3340 DispatchMessage(&msg);
3346 static void test_interthread_messages(void)
3353 int len, expected_len;
3354 struct wnd_event wnd_event;
3356 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
3357 if (!wnd_event.event)
3359 trace("skipping interthread message test under win9x\n");
3363 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
3364 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
3366 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3368 CloseHandle(wnd_event.event);
3370 SetLastError(0xdeadbeef);
3371 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
3372 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
3374 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3375 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
3377 expected_len = lstrlenA("window caption text");
3378 memset(buf, 0, sizeof(buf));
3379 SetLastError(0xdeadbeef);
3380 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
3381 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
3382 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
3384 msg.hwnd = wnd_event.hwnd;
3385 msg.message = WM_GETTEXT;
3386 msg.wParam = sizeof(buf);
3387 msg.lParam = (LPARAM)buf;
3388 memset(buf, 0, sizeof(buf));
3389 SetLastError(0xdeadbeef);
3390 len = DispatchMessageA(&msg);
3391 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3392 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
3394 /* the following test causes an exception in user.exe under win9x */
3395 msg.hwnd = wnd_event.hwnd;
3396 msg.message = WM_TIMER;
3398 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3399 SetLastError(0xdeadbeef);
3400 len = DispatchMessageA(&msg);
3401 ok(!len && GetLastError() == 0xdeadbeef,
3402 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
3404 ok(PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0), "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
3406 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3407 CloseHandle(hThread);
3411 static const struct message WmVkN[] = {
3412 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3413 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3414 { WM_CHAR, wparam|lparam, 'n', 1 },
3415 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
3416 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3417 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3420 static const struct message WmShiftVkN[] = {
3421 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
3422 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
3423 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3424 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3425 { WM_CHAR, wparam|lparam, 'N', 1 },
3426 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
3427 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3428 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3429 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
3430 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
3433 static const struct message WmCtrlVkN[] = {
3434 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3435 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3436 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3437 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3438 { WM_CHAR, wparam|lparam, 0x000e, 1 },
3439 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3440 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3441 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3442 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3443 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3446 static const struct message WmCtrlVkN_2[] = {
3447 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3448 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3449 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3450 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3451 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3452 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3453 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3454 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3457 static const struct message WmAltVkN[] = {
3458 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3459 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3460 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3461 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3462 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
3463 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
3464 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
3465 { HCBT_SYSCOMMAND, hook },
3466 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
3467 { WM_SETCURSOR, sent|defwinproc },
3468 { WM_INITMENU, sent|defwinproc },
3469 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
3470 { WM_CAPTURECHANGED, sent|defwinproc },
3471 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
3472 { WM_EXITMENULOOP, sent|defwinproc },
3473 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
3474 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
3475 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3476 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3477 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3478 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3481 static const struct message WmAltVkN_2[] = {
3482 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3483 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3484 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3485 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
3486 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3487 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3488 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3489 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3492 static const struct message WmCtrlAltVkN[] = {
3493 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3494 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3495 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3496 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3497 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
3498 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3499 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
3500 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3501 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3502 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3503 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3504 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3508 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
3512 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
3514 struct message log_msg;
3516 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
3518 log_msg.message = msg.message;
3519 log_msg.flags = wparam|lparam;
3520 log_msg.wParam = msg.wParam;
3521 log_msg.lParam = msg.lParam;
3522 add_message(&log_msg);
3524 if (!TranslateAccelerator(hwnd, hAccel, &msg))
3526 TranslateMessage(&msg);
3527 DispatchMessage(&msg);
3532 static void test_accelerators(void)
3536 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
3537 100, 100, 200, 200, 0, 0, 0, NULL);
3541 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3543 state = GetKeyState(VK_SHIFT);
3544 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
3545 state = GetKeyState(VK_CAPITAL);
3546 ok(state == 0, "wrong CapsLock state %04x\n", state);
3548 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
3549 assert(hAccel != 0);
3551 trace("testing VK_N press/release\n");
3553 keybd_event('N', 0, 0, 0);
3554 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3555 pump_msg_loop(hwnd, hAccel);
3556 ok_sequence(WmVkN, "VK_N press/release", FALSE);
3558 trace("testing Shift+VK_N press/release\n");
3560 keybd_event(VK_SHIFT, 0, 0, 0);
3561 keybd_event('N', 0, 0, 0);
3562 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3563 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
3564 pump_msg_loop(hwnd, hAccel);
3565 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
3567 trace("testing Ctrl+VK_N press/release\n");
3569 keybd_event(VK_CONTROL, 0, 0, 0);
3570 keybd_event('N', 0, 0, 0);
3571 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3572 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3573 pump_msg_loop(hwnd, hAccel);
3574 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
3576 trace("testing Alt+VK_N press/release\n");
3578 keybd_event(VK_MENU, 0, 0, 0);
3579 keybd_event('N', 0, 0, 0);
3580 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3581 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3582 pump_msg_loop(hwnd, hAccel);
3583 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
3585 trace("testing Ctrl+Alt+VK_N press/release\n");
3587 keybd_event(VK_CONTROL, 0, 0, 0);
3588 keybd_event(VK_MENU, 0, 0, 0);
3589 keybd_event('N', 0, 0, 0);
3590 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3591 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3592 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3593 pump_msg_loop(hwnd, hAccel);
3594 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
3596 ok(DestroyAcceleratorTable(hAccel), "DestroyAcceleratorTable error %ld\n", GetLastError());
3598 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
3599 assert(hAccel != 0);
3601 trace("testing VK_N press/release\n");
3603 keybd_event('N', 0, 0, 0);
3604 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3605 pump_msg_loop(hwnd, hAccel);
3606 ok_sequence(WmVkN, "VK_N press/release", FALSE);
3608 trace("testing Shift+VK_N press/release\n");
3610 keybd_event(VK_SHIFT, 0, 0, 0);
3611 keybd_event('N', 0, 0, 0);
3612 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3613 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
3614 pump_msg_loop(hwnd, hAccel);
3615 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
3617 trace("testing Ctrl+VK_N press/release 2\n");
3619 keybd_event(VK_CONTROL, 0, 0, 0);
3620 keybd_event('N', 0, 0, 0);
3621 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3622 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3623 pump_msg_loop(hwnd, hAccel);
3624 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
3626 trace("testing Alt+VK_N press/release 2\n");
3628 keybd_event(VK_MENU, 0, 0, 0);
3629 keybd_event('N', 0, 0, 0);
3630 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3631 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3632 pump_msg_loop(hwnd, hAccel);
3633 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
3635 trace("testing Ctrl+Alt+VK_N press/release\n");
3637 keybd_event(VK_CONTROL, 0, 0, 0);
3638 keybd_event(VK_MENU, 0, 0, 0);
3639 keybd_event('N', 0, 0, 0);
3640 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3641 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3642 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3643 pump_msg_loop(hwnd, hAccel);
3644 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
3646 ok(DestroyAcceleratorTable(hAccel), "DestroyAcceleratorTable error %ld\n", GetLastError());
3648 DestroyWindow(hwnd);
3651 /************* window procedures ********************/
3653 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3655 static long defwndproc_counter = 0;
3656 static long beginpaint_counter = 0;
3660 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3664 case WM_WINDOWPOSCHANGING:
3665 case WM_WINDOWPOSCHANGED:
3667 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
3669 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
3670 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
3671 winpos->hwnd, winpos->hwndInsertAfter,
3672 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
3674 /* Log only documented flags, win2k uses 0x1000 and 0x2000
3675 * in the high word for internal purposes
3677 wParam = winpos->flags & 0xffff;
3682 msg.message = message;
3683 msg.flags = sent|wparam|lparam;
3684 if (defwndproc_counter) msg.flags |= defwinproc;
3685 if (beginpaint_counter) msg.flags |= beginpaint;
3686 msg.wParam = wParam;
3687 msg.lParam = lParam;
3690 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
3692 HWND parent = GetParent(hwnd);
3694 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
3696 GetClientRect(parent, &rc);
3697 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
3699 trace("ptReserved = (%ld,%ld)\n"
3700 "ptMaxSize = (%ld,%ld)\n"
3701 "ptMaxPosition = (%ld,%ld)\n"
3702 "ptMinTrackSize = (%ld,%ld)\n"
3703 "ptMaxTrackSize = (%ld,%ld)\n",
3704 minmax->ptReserved.x, minmax->ptReserved.y,
3705 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
3706 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
3707 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
3708 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
3710 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
3711 minmax->ptMaxSize.x, rc.right);
3712 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
3713 minmax->ptMaxSize.y, rc.bottom);
3716 if (message == WM_PAINT)
3719 beginpaint_counter++;
3720 BeginPaint( hwnd, &ps );
3721 beginpaint_counter--;
3722 EndPaint( hwnd, &ps );
3726 defwndproc_counter++;
3727 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3728 defwndproc_counter--;
3733 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3735 static long defwndproc_counter = 0;
3739 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3741 msg.message = message;
3742 msg.flags = sent|wparam|lparam;
3743 if (defwndproc_counter) msg.flags |= defwinproc;
3744 msg.wParam = wParam;
3745 msg.lParam = lParam;
3748 if (message == WM_CREATE)
3750 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
3751 SetWindowLongA(hwnd, GWL_STYLE, style);
3754 defwndproc_counter++;
3755 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3756 defwndproc_counter--;
3761 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3763 static long defwndproc_counter = 0;
3764 static long beginpaint_counter = 0;
3768 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3770 if (log_all_parent_messages ||
3771 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
3772 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
3773 message == WM_ENABLE || message == WM_ENTERIDLE ||
3774 message == WM_IME_SETCONTEXT)
3776 msg.message = message;
3777 msg.flags = sent|parent|wparam|lparam;
3778 if (defwndproc_counter) msg.flags |= defwinproc;
3779 if (beginpaint_counter) msg.flags |= beginpaint;
3780 msg.wParam = wParam;
3781 msg.lParam = lParam;
3785 if (message == WM_PAINT)
3788 beginpaint_counter++;
3789 BeginPaint( hwnd, &ps );
3790 beginpaint_counter--;
3791 EndPaint( hwnd, &ps );
3795 defwndproc_counter++;
3796 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3797 defwndproc_counter--;
3802 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3804 static long defwndproc_counter = 0;
3808 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3810 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
3811 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
3812 if (after_end_dialog)
3813 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
3815 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
3817 msg.message = message;
3818 msg.flags = sent|wparam|lparam;
3819 if (defwndproc_counter) msg.flags |= defwinproc;
3820 msg.wParam = wParam;
3821 msg.lParam = lParam;
3824 defwndproc_counter++;
3825 ret = DefDlgProcA(hwnd, message, wParam, lParam);
3826 defwndproc_counter--;
3831 static BOOL RegisterWindowClasses(void)
3836 cls.lpfnWndProc = MsgCheckProcA;
3839 cls.hInstance = GetModuleHandleA(0);
3841 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
3842 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
3843 cls.lpszMenuName = NULL;
3844 cls.lpszClassName = "TestWindowClass";
3845 if(!RegisterClassA(&cls)) return FALSE;
3847 cls.lpfnWndProc = PopupMsgCheckProcA;
3848 cls.lpszClassName = "TestPopupClass";
3849 if(!RegisterClassA(&cls)) return FALSE;
3851 cls.lpfnWndProc = ParentMsgCheckProcA;
3852 cls.lpszClassName = "TestParentClass";
3853 if(!RegisterClassA(&cls)) return FALSE;
3855 cls.lpfnWndProc = DefWindowProcA;
3856 cls.lpszClassName = "SimpleWindowClass";
3857 if(!RegisterClassA(&cls)) return FALSE;
3859 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
3860 cls.lpfnWndProc = TestDlgProcA;
3861 cls.lpszClassName = "TestDialogClass";
3862 if(!RegisterClassA(&cls)) return FALSE;
3867 static HHOOK hCBT_hook;
3869 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
3873 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
3875 if (nCode == HCBT_SYSCOMMAND)
3879 msg.message = nCode;
3881 msg.wParam = wParam;
3882 msg.lParam = lParam;
3885 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
3888 /* Log also SetFocus(0) calls */
3889 if (!wParam) wParam = lParam;
3891 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
3893 if (!strcmp(buf, "TestWindowClass") ||
3894 !strcmp(buf, "TestParentClass") ||
3895 !strcmp(buf, "TestPopupClass") ||
3896 !strcmp(buf, "SimpleWindowClass") ||
3897 !strcmp(buf, "TestDialogClass") ||
3898 !strcmp(buf, "MDI_frame_class") ||
3899 !strcmp(buf, "MDI_client_class") ||
3900 !strcmp(buf, "MDI_child_class") ||
3901 !strcmp(buf, "my_button_class") ||
3902 !strcmp(buf, "#32770"))
3906 msg.message = nCode;
3908 msg.wParam = wParam;
3909 msg.lParam = lParam;
3913 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
3916 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
3917 static const WCHAR wszAnsi[] = {'U',0};
3919 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3923 case CB_FINDSTRINGEXACT:
3924 trace("String: %p\n", (LPCWSTR)lParam);
3925 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
3927 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
3931 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
3934 static void test_message_conversion(void)
3936 static const WCHAR wszMsgConversionClass[] =
3937 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
3944 cls.lpfnWndProc = MsgConversionProcW;
3947 cls.hInstance = GetModuleHandleW(NULL);
3949 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
3950 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
3951 cls.lpszMenuName = NULL;
3952 cls.lpszClassName = wszMsgConversionClass;
3953 /* this call will fail on Win9x, but that doesn't matter as this test is
3954 * meaningless on those platforms */
3955 if(!RegisterClassW(&cls)) return;
3957 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
3958 100, 100, 200, 200, 0, 0, 0, NULL);
3959 ok(hwnd != NULL, "Window creation failed\n");
3963 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
3964 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3965 ok(lRes == 0, "String should have been converted\n");
3966 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3967 ok(lRes == 1, "String shouldn't have been converted\n");
3971 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
3972 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3973 ok(lRes == 1, "String shouldn't have been converted\n");
3974 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3975 ok(lRes == 1, "String shouldn't have been converted\n");
3977 /* Synchronous messages */
3979 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3980 ok(lRes == 0, "String should have been converted\n");
3981 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3982 ok(lRes == 1, "String shouldn't have been converted\n");
3984 /* Asynchronous messages */
3987 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3988 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3989 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3991 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3992 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3993 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3995 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3996 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3997 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3999 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4000 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4001 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4003 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4004 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4005 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4007 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4008 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4009 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4011 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4012 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4013 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4015 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4016 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4017 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4020 typedef struct _thread_info
4027 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
4031 #define TIMER_ID 0x19
4033 static DWORD WINAPI timer_thread_proc(LPVOID x)
4035 thread_info *info = x;
4038 r = KillTimer(info->hWnd, 0x19);
4039 ok(r,"KillTimer failed in thread\n");
4040 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
4041 ok(r,"SetTimer failed in thread\n");
4042 ok(r==TIMER_ID,"SetTimer id different\n");
4043 r = SetEvent(info->handles[0]);
4044 ok(r,"SetEvent failed in thread\n");
4048 static void test_timers(void)
4053 info.hWnd = CreateWindow ("TestWindowClass", NULL,
4054 WS_OVERLAPPEDWINDOW ,
4055 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4058 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
4059 ok(info.id, "SetTimer failed");
4060 ok(info.id==TIMER_ID, "SetTimer timer ID different");
4061 info.handles[0] = CreateEvent(NULL,0,0,NULL);
4062 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
4064 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
4066 WaitForSingleObject(info.handles[1], INFINITE);
4068 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
4070 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
4075 if (!RegisterWindowClasses()) assert(0);
4077 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
4081 test_mdi_messages();
4082 test_button_messages();
4083 test_paint_messages();
4084 test_interthread_messages();
4085 test_message_conversion();
4086 test_accelerators();
4089 UnhookWindowsHookEx(hCBT_hook);