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 #define ok_sequence( exp, contx, todo) \
804 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
807 static void ok_sequence_(const struct message *expected, const char *context, int todo,
808 const char *file, int line)
810 static const struct message end_of_sequence = { 0, 0, 0, 0 };
811 const struct message *actual;
814 add_message(&end_of_sequence);
818 while (expected->message && actual->message)
820 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
822 if (expected->message == actual->message)
824 if (expected->flags & wparam)
826 if (expected->wParam != actual->wParam && todo)
830 ok_( file, line) (FALSE,
831 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
832 context, expected->message, expected->wParam, actual->wParam);
836 ok_( file, line) (expected->wParam == actual->wParam,
837 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
838 context, expected->message, expected->wParam, actual->wParam);
840 if (expected->flags & lparam)
841 ok_( file, line) (expected->lParam == actual->lParam,
842 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
843 context, expected->message, expected->lParam, actual->lParam);
844 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
845 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
846 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
847 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
848 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
849 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
850 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
851 "%s: the msg 0x%04x should have been %s\n",
852 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
853 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
854 "%s: the msg 0x%04x was expected in %s\n",
855 context, expected->message, (expected->flags & parent) ? "parent" : "child");
856 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook),
857 "%s: the msg 0x%04x should have been sent by a hook\n",
858 context, expected->message);
862 else if (expected->flags & optional)
868 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
869 context, expected->message, actual->message);
876 ok_( file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
877 context, expected->message, actual->message);
883 /* skip all optional trailing messages */
884 while (expected->message && (expected->flags & optional))
890 if (expected->message || actual->message) {
892 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
893 context, expected->message, actual->message);
899 if (expected->message || actual->message)
900 ok_( file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
901 context, expected->message, actual->message);
903 if( todo && !failcount) /* succeeded yet marked todo */
905 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
911 /******************************** MDI test **********************************/
913 /* CreateWindow for MDI frame window, initially visible */
914 static const struct message WmCreateMDIframeSeq[] = {
915 { HCBT_CREATEWND, hook },
916 { WM_GETMINMAXINFO, sent },
917 { WM_NCCREATE, sent },
918 { WM_NCCALCSIZE, sent|wparam, 0 },
920 { WM_SHOWWINDOW, sent|wparam, 1 },
921 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
922 { HCBT_ACTIVATE, hook },
923 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
924 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
925 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* Win9x */
926 { WM_ACTIVATEAPP, sent|wparam, 1 },
927 { WM_NCACTIVATE, sent|wparam, 1 },
928 { WM_ACTIVATE, sent|wparam, 1 },
929 { HCBT_SETFOCUS, hook },
930 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
931 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
932 /* Win9x adds SWP_NOZORDER below */
933 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
938 /* DestroyWindow for MDI frame window, initially visible */
939 static const struct message WmDestroyMDIframeSeq[] = {
940 { HCBT_DESTROYWND, hook },
941 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
942 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
943 { WM_NCACTIVATE, sent|wparam, 0 },
944 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
945 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
946 { WM_DESTROY, sent },
947 { WM_NCDESTROY, sent },
950 /* CreateWindow for MDI client window, initially visible */
951 static const struct message WmCreateMDIclientSeq[] = {
952 { HCBT_CREATEWND, hook },
953 { WM_NCCREATE, sent },
954 { WM_NCCALCSIZE, sent|wparam, 0 },
958 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
959 { WM_SHOWWINDOW, sent|wparam, 1 },
960 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE },
961 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
964 /* DestroyWindow for MDI client window, initially visible */
965 static const struct message WmDestroyMDIclientSeq[] = {
966 { HCBT_DESTROYWND, hook },
967 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
968 { WM_SHOWWINDOW, sent|wparam, 0 },
969 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
970 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
971 { WM_DESTROY, sent },
972 { WM_NCDESTROY, sent },
975 /* CreateWindow for MDI child window, initially visible */
976 static const struct message WmCreateMDIchildVisibleSeq[] = {
977 { HCBT_CREATEWND, hook },
978 { WM_NCCREATE, sent },
979 { WM_NCCALCSIZE, sent|wparam, 0 },
983 /* Win2k sends wparam set to
984 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
985 * while Win9x doesn't bother to set child window id according to
986 * CLIENTCREATESTRUCT.idFirstChild
988 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
989 { WM_SHOWWINDOW, sent|wparam, 1 },
990 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
991 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
992 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
993 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
994 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
995 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
997 /* Win9x: message sequence terminates here. */
999 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1000 { HCBT_SETFOCUS, hook }, /* in MDI client */
1001 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1002 { WM_SETFOCUS, sent }, /* in MDI client */
1003 { HCBT_SETFOCUS, hook },
1004 { WM_KILLFOCUS, sent }, /* in MDI client */
1005 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1006 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1007 { WM_SETFOCUS, sent|defwinproc },
1008 { WM_MDIACTIVATE, sent|defwinproc },
1011 /* DestroyWindow for MDI child window, initially visible */
1012 static const struct message WmDestroyMDIchildVisibleSeq[] = {
1013 { HCBT_DESTROYWND, hook },
1014 /* Win2k sends wparam set to
1015 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1016 * while Win9x doesn't bother to set child window id according to
1017 * CLIENTCREATESTRUCT.idFirstChild
1019 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1020 { WM_SHOWWINDOW, sent|wparam, 0 },
1021 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1022 { WM_ERASEBKGND, sent|parent|optional },
1023 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1025 /* { WM_DESTROY, sent }
1026 * Win9x: message sequence terminates here.
1029 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1030 { WM_KILLFOCUS, sent },
1031 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1032 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1033 { WM_SETFOCUS, sent }, /* in MDI client */
1035 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1036 { WM_KILLFOCUS, sent }, /* in MDI client */
1037 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1038 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1039 { WM_SETFOCUS, sent }, /* in MDI client */
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_DESTROY, sent },
1055 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1056 { WM_KILLFOCUS, sent },
1057 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1058 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1059 { WM_SETFOCUS, sent }, /* in MDI client */
1061 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1062 { WM_KILLFOCUS, sent }, /* in MDI client */
1063 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1064 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1065 { WM_SETFOCUS, sent }, /* in MDI client */
1067 { WM_NCDESTROY, sent },
1070 /* CreateWindow for MDI child window, initially invisible */
1071 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1072 { HCBT_CREATEWND, hook },
1073 { WM_NCCREATE, sent },
1074 { WM_NCCALCSIZE, sent|wparam, 0 },
1075 { WM_CREATE, sent },
1078 /* Win2k sends wparam set to
1079 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1080 * while Win9x doesn't bother to set child window id according to
1081 * CLIENTCREATESTRUCT.idFirstChild
1083 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1086 /* DestroyWindow for MDI child window, initially invisible */
1087 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1088 { HCBT_DESTROYWND, hook },
1089 /* Win2k sends wparam set to
1090 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1091 * while Win9x doesn't bother to set child window id according to
1092 * CLIENTCREATESTRUCT.idFirstChild
1094 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1095 { WM_DESTROY, sent },
1096 { WM_NCDESTROY, sent },
1099 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1100 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1101 { HCBT_CREATEWND, hook },
1102 { WM_NCCREATE, sent },
1103 { WM_NCCALCSIZE, sent|wparam, 0 },
1104 { WM_CREATE, sent },
1107 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1108 { WM_GETMINMAXINFO, sent },
1109 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1110 { WM_NCCALCSIZE, sent|wparam, 1 },
1111 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1112 { WM_SIZE, sent|defwinproc },
1114 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1115 { WM_NCCALCSIZE, sent|wparam, 1 },
1116 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1117 /* Win2k sends wparam set to
1118 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1119 * while Win9x doesn't bother to set child window id according to
1120 * CLIENTCREATESTRUCT.idFirstChild
1122 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1123 { WM_SHOWWINDOW, sent|wparam, 1 },
1124 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1125 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1126 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1127 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1128 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1129 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1131 /* Win9x: message sequence terminates here. */
1133 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1134 { HCBT_SETFOCUS, hook }, /* in MDI client */
1135 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1136 { WM_SETFOCUS, sent }, /* in MDI client */
1137 { HCBT_SETFOCUS, hook },
1138 { WM_KILLFOCUS, sent }, /* in MDI client */
1139 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1140 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1141 { WM_SETFOCUS, sent|defwinproc },
1142 { WM_MDIACTIVATE, sent|defwinproc },
1144 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1145 { WM_NCCALCSIZE, sent|wparam, 1 },
1146 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1149 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1150 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
1151 /* restore the 1st MDI child */
1152 { WM_SETREDRAW, sent|wparam, 0 },
1153 { HCBT_MINMAX, hook },
1154 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1155 { WM_NCCALCSIZE, sent|wparam, 1 },
1156 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1157 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1158 { WM_SIZE, sent|defwinproc },
1160 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1161 { WM_NCCALCSIZE, sent|wparam, 1 },
1162 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1163 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
1164 /* create the 2nd MDI child */
1165 { HCBT_CREATEWND, hook },
1166 { WM_NCCREATE, sent },
1167 { WM_NCCALCSIZE, sent|wparam, 0 },
1168 { WM_CREATE, sent },
1171 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1172 { WM_GETMINMAXINFO, sent },
1173 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1174 { WM_NCCALCSIZE, sent|wparam, 1 },
1175 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1176 { WM_SIZE, sent|defwinproc },
1178 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1179 { WM_NCCALCSIZE, sent|wparam, 1 },
1180 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1181 /* Win2k sends wparam set to
1182 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1183 * while Win9x doesn't bother to set child window id according to
1184 * CLIENTCREATESTRUCT.idFirstChild
1186 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1187 { WM_SHOWWINDOW, sent|wparam, 1 },
1188 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1189 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1190 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1191 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1192 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1194 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1195 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1197 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1199 /* Win9x: message sequence terminates here. */
1201 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1202 { HCBT_SETFOCUS, hook },
1203 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
1204 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
1205 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1206 { WM_SETFOCUS, sent }, /* in MDI client */
1207 { HCBT_SETFOCUS, hook },
1208 { WM_KILLFOCUS, sent }, /* in MDI client */
1209 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1210 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1211 { WM_SETFOCUS, sent|defwinproc },
1213 { WM_MDIACTIVATE, sent|defwinproc },
1215 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1216 { WM_NCCALCSIZE, sent|wparam, 1 },
1217 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1220 /* WM_MDICREATE MDI child window, initially visible and maximized */
1221 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
1222 { WM_MDICREATE, sent },
1223 { HCBT_CREATEWND, hook },
1224 { WM_NCCREATE, sent },
1225 { WM_NCCALCSIZE, sent|wparam, 0 },
1226 { WM_CREATE, sent },
1229 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1230 { WM_GETMINMAXINFO, sent },
1231 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1232 { WM_NCCALCSIZE, sent|wparam, 1 },
1233 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1234 { WM_SIZE, sent|defwinproc },
1236 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1237 { WM_NCCALCSIZE, sent|wparam, 1 },
1238 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1239 /* Win2k sends wparam set to
1240 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1241 * while Win9x doesn't bother to set child window id according to
1242 * CLIENTCREATESTRUCT.idFirstChild
1244 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1245 { WM_SHOWWINDOW, sent|wparam, 1 },
1246 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1247 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1248 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1249 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1250 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1251 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1253 /* Win9x: message sequence terminates here. */
1255 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1256 { HCBT_SETFOCUS, hook }, /* in MDI client */
1257 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1258 { WM_SETFOCUS, sent }, /* in MDI client */
1259 { HCBT_SETFOCUS, hook },
1260 { WM_KILLFOCUS, sent }, /* in MDI client */
1261 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1262 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1263 { WM_SETFOCUS, sent|defwinproc },
1265 { WM_MDIACTIVATE, sent|defwinproc },
1268 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1269 { WM_NCCALCSIZE, sent|wparam, 1 },
1270 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1273 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1274 { WM_NCCALCSIZE, sent|wparam, 1 },
1275 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1276 { WM_MOVE, sent|defwinproc },
1277 { WM_SIZE, sent|defwinproc },
1280 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1281 { WM_NCCALCSIZE, sent|wparam, 1 },
1282 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1286 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1287 { WM_NCCALCSIZE, sent|wparam, 1 },
1288 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1289 { WM_SIZE, sent|defwinproc },
1293 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1294 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
1295 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
1296 { HCBT_SYSCOMMAND, hook },
1297 { WM_CLOSE, sent|defwinproc },
1298 { WM_MDIDESTROY, sent }, /* in MDI client */
1300 /* bring the 1st MDI child to top */
1301 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
1302 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
1303 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
1304 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1305 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1307 /* maximize the 1st MDI child */
1308 { HCBT_MINMAX, hook },
1309 { WM_GETMINMAXINFO, sent|defwinproc },
1310 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
1311 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1312 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
1313 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1314 { WM_SIZE, sent|defwinproc },
1316 /* restore the 2nd MDI child */
1317 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
1318 { HCBT_MINMAX, hook },
1319 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOZORDER|0x8000 },
1320 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1321 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1322 { WM_SIZE, sent|defwinproc },
1323 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
1325 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1326 { WM_NCCALCSIZE, sent|wparam, 1 },
1327 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1329 /* bring the 1st MDI child to top */
1330 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1331 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1332 { HCBT_SETFOCUS, hook },
1333 { WM_KILLFOCUS, sent|defwinproc },
1334 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
1335 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1336 { WM_SETFOCUS, sent }, /* in MDI client */
1337 { HCBT_SETFOCUS, hook },
1338 { WM_KILLFOCUS, sent }, /* in MDI client */
1339 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1340 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1341 { WM_SETFOCUS, sent|defwinproc },
1342 { WM_MDIACTIVATE, sent|defwinproc },
1343 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1345 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1346 { WM_SHOWWINDOW, sent|wparam, 1 },
1347 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1348 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1349 { WM_MDIREFRESHMENU, sent },
1351 { HCBT_DESTROYWND, hook },
1352 /* Win2k sends wparam set to
1353 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1354 * while Win9x doesn't bother to set child window id according to
1355 * CLIENTCREATESTRUCT.idFirstChild
1357 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1358 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
1359 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1360 { WM_ERASEBKGND, sent|parent|optional },
1361 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1363 { WM_DESTROY, sent|defwinproc },
1364 { WM_NCDESTROY, sent|defwinproc },
1367 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1368 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
1369 { WM_MDIDESTROY, sent }, /* in MDI client */
1370 { WM_SHOWWINDOW, sent|wparam, 0 },
1371 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1372 { WM_ERASEBKGND, sent|parent|optional },
1373 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1375 { HCBT_SETFOCUS, hook },
1376 { WM_KILLFOCUS, sent },
1377 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1378 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1379 { WM_SETFOCUS, sent }, /* in MDI client */
1380 { HCBT_SETFOCUS, hook },
1381 { WM_KILLFOCUS, sent }, /* in MDI client */
1382 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1383 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1384 { WM_SETFOCUS, sent },
1387 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1388 { WM_NCCALCSIZE, sent|wparam, 1 },
1389 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1392 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1393 { WM_NCCALCSIZE, sent|wparam, 1 },
1394 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1395 { WM_MOVE, sent|defwinproc },
1396 { WM_SIZE, sent|defwinproc },
1399 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1400 { WM_NCCALCSIZE, sent|wparam, 1 },
1401 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1405 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1406 { WM_NCCALCSIZE, sent|wparam, 1 },
1407 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1408 { WM_SIZE, sent|defwinproc },
1411 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1412 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1413 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1416 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1417 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1418 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1419 { WM_MOVE, sent|defwinproc },
1420 { WM_SIZE, sent|defwinproc },
1423 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1424 { WM_NCCALCSIZE, sent|wparam, 1 },
1425 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1429 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOZORDER },
1430 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1431 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1432 { WM_SIZE, sent|defwinproc },
1435 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1436 { WM_NCCALCSIZE, sent|wparam, 1 },
1437 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1439 { WM_NCACTIVATE, sent|wparam, 0 },
1440 { WM_MDIACTIVATE, sent },
1442 { HCBT_MINMAX, hook },
1443 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
1444 { WM_NCCALCSIZE, sent|wparam, 1 },
1445 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1446 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE|0x8000 },
1447 { WM_SIZE, sent|defwinproc },
1450 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1451 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1452 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1455 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1456 { WM_NCCALCSIZE, sent|wparam, 1 },
1457 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1458 { WM_MOVE, sent|defwinproc },
1459 { WM_SIZE, sent|defwinproc },
1462 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1463 { WM_NCCALCSIZE, sent|wparam, 1 },
1464 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1467 { HCBT_SETFOCUS, hook },
1468 { WM_KILLFOCUS, sent },
1469 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1470 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1471 { WM_SETFOCUS, sent }, /* in MDI client */
1473 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
1475 { HCBT_DESTROYWND, hook },
1476 /* Win2k sends wparam set to
1477 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1478 * while Win9x doesn't bother to set child window id according to
1479 * CLIENTCREATESTRUCT.idFirstChild
1481 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1483 { WM_SHOWWINDOW, sent|wparam, 0 },
1484 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1485 { WM_ERASEBKGND, sent|parent|optional },
1486 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1488 { WM_DESTROY, sent },
1489 { WM_NCDESTROY, sent },
1492 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1493 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
1494 { HCBT_MINMAX, hook },
1495 { WM_GETMINMAXINFO, sent },
1496 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1497 { WM_NCCALCSIZE, sent|wparam, 1 },
1498 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1500 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1501 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1502 { HCBT_SETFOCUS, hook },
1503 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1504 { WM_SETFOCUS, sent }, /* in MDI client */
1505 { HCBT_SETFOCUS, hook },
1506 { WM_KILLFOCUS, sent }, /* in MDI client */
1507 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1508 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1509 { WM_SETFOCUS, sent|defwinproc },
1510 { WM_MDIACTIVATE, sent|defwinproc },
1511 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1512 { WM_SIZE, sent|defwinproc },
1514 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1515 { WM_NCCALCSIZE, sent|wparam, 1 },
1516 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1519 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1520 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
1521 { HCBT_MINMAX, hook },
1522 { WM_GETMINMAXINFO, sent },
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 visible MDI child window */
1535 static const struct message WmRestoreMDIchildVisibleSeq[] = {
1536 { HCBT_MINMAX, hook },
1537 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1538 { WM_NCCALCSIZE, sent|wparam, 1 },
1539 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1540 { WM_WINDOWPOSCHANGED, sent|wparam, 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 },
1548 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1549 static const struct message WmRestoreMDIchildInisibleSeq[] = {
1550 { HCBT_MINMAX, hook },
1551 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1552 { WM_NCCALCSIZE, sent|wparam, 1 },
1553 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1554 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1555 { WM_SIZE, sent|defwinproc },
1557 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1558 { WM_NCCALCSIZE, sent|wparam, 1 },
1559 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1563 static HWND mdi_client;
1564 static WNDPROC old_mdi_client_proc;
1566 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1570 /* do not log painting messages */
1571 if (message != WM_PAINT &&
1572 message != WM_ERASEBKGND &&
1573 message != WM_NCPAINT &&
1574 message != WM_GETTEXT &&
1575 message != WM_MDIGETACTIVE)
1577 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1581 case WM_WINDOWPOSCHANGING:
1582 case WM_WINDOWPOSCHANGED:
1584 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1586 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1587 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1588 winpos->hwnd, winpos->hwndInsertAfter,
1589 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1591 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1592 * in the high word for internal purposes
1594 wParam = winpos->flags & 0xffff;
1599 msg.message = message;
1600 msg.flags = sent|wparam|lparam;
1601 msg.wParam = wParam;
1602 msg.lParam = lParam;
1606 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1609 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1611 static long defwndproc_counter = 0;
1615 /* do not log painting messages */
1616 if (message != WM_PAINT &&
1617 message != WM_ERASEBKGND &&
1618 message != WM_NCPAINT &&
1619 message != WM_GETTEXT)
1621 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1625 case WM_WINDOWPOSCHANGING:
1626 case WM_WINDOWPOSCHANGED:
1628 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1630 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1631 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1632 winpos->hwnd, winpos->hwndInsertAfter,
1633 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1635 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1636 * in the high word for internal purposes
1638 wParam = winpos->flags & 0xffff;
1642 case WM_MDIACTIVATE:
1644 HWND active, client = GetParent(hwnd);
1646 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1648 if (hwnd == (HWND)lParam) /* if we are being activated */
1649 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
1651 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
1656 msg.message = message;
1657 msg.flags = sent|wparam|lparam;
1658 if (defwndproc_counter) msg.flags |= defwinproc;
1659 msg.wParam = wParam;
1660 msg.lParam = lParam;
1664 defwndproc_counter++;
1665 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1666 defwndproc_counter--;
1671 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1673 static long defwndproc_counter = 0;
1677 /* do not log painting messages */
1678 if (message != WM_PAINT &&
1679 message != WM_ERASEBKGND &&
1680 message != WM_NCPAINT &&
1681 message != WM_GETTEXT)
1683 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1687 case WM_WINDOWPOSCHANGING:
1688 case WM_WINDOWPOSCHANGED:
1690 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1692 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1693 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1694 winpos->hwnd, winpos->hwndInsertAfter,
1695 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1697 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1698 * in the high word for internal purposes
1700 wParam = winpos->flags & 0xffff;
1705 msg.message = message;
1706 msg.flags = sent|wparam|lparam;
1707 if (defwndproc_counter) msg.flags |= defwinproc;
1708 msg.wParam = wParam;
1709 msg.lParam = lParam;
1713 defwndproc_counter++;
1714 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
1715 defwndproc_counter--;
1720 static BOOL mdi_RegisterWindowClasses(void)
1725 cls.lpfnWndProc = mdi_frame_wnd_proc;
1728 cls.hInstance = GetModuleHandleA(0);
1730 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1731 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1732 cls.lpszMenuName = NULL;
1733 cls.lpszClassName = "MDI_frame_class";
1734 if (!RegisterClassA(&cls)) return FALSE;
1736 cls.lpfnWndProc = mdi_child_wnd_proc;
1737 cls.lpszClassName = "MDI_child_class";
1738 if (!RegisterClassA(&cls)) return FALSE;
1740 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
1741 old_mdi_client_proc = cls.lpfnWndProc;
1742 cls.hInstance = GetModuleHandleA(0);
1743 cls.lpfnWndProc = mdi_client_hook_proc;
1744 cls.lpszClassName = "MDI_client_class";
1745 if (!RegisterClassA(&cls)) assert(0);
1750 static void test_mdi_messages(void)
1752 MDICREATESTRUCTA mdi_cs;
1753 CLIENTCREATESTRUCT client_cs;
1754 HWND mdi_frame, mdi_child, mdi_child2, active_child;
1756 HMENU hMenu = CreateMenu();
1758 assert(mdi_RegisterWindowClasses());
1762 trace("creating MDI frame window\n");
1763 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1764 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1765 WS_MAXIMIZEBOX | WS_VISIBLE,
1766 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1767 GetDesktopWindow(), hMenu,
1768 GetModuleHandleA(0), NULL);
1770 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
1772 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1773 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
1775 trace("creating MDI client window\n");
1776 client_cs.hWindowMenu = 0;
1777 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
1778 mdi_client = CreateWindowExA(0, "MDI_client_class",
1780 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
1782 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
1784 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
1786 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1787 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
1789 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1790 ok(!active_child, "wrong active MDI child %p\n", active_child);
1791 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1796 trace("creating invisible MDI child window\n");
1797 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1799 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1800 mdi_client, 0, GetModuleHandleA(0), NULL);
1804 ShowWindow(mdi_child, SW_SHOWNORMAL);
1805 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
1807 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1808 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1810 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1811 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1813 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1814 ok(!active_child, "wrong active MDI child %p\n", active_child);
1815 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1817 ShowWindow(mdi_child, SW_HIDE);
1818 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
1821 ShowWindow(mdi_child, SW_SHOW);
1822 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
1824 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1825 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1827 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1828 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1830 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1831 ok(!active_child, "wrong active MDI child %p\n", active_child);
1832 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1834 DestroyWindow(mdi_child);
1837 trace("creating visible MDI child window\n");
1838 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1839 WS_CHILD | WS_VISIBLE,
1840 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1841 mdi_client, 0, GetModuleHandleA(0), NULL);
1843 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", TRUE);
1845 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1846 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1848 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1849 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
1851 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1852 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
1853 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1856 DestroyWindow(mdi_child);
1857 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
1859 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1860 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1862 /* Win2k: MDI client still returns a just destroyed child as active
1863 * Win9x: MDI client returns 0
1865 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1866 ok(active_child == mdi_child || /* win2k */
1867 !active_child, /* win9x */
1868 "wrong active MDI child %p\n", active_child);
1869 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1873 trace("creating invisible MDI child window\n");
1874 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1876 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1877 mdi_client, 0, GetModuleHandleA(0), NULL);
1879 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
1881 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
1882 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
1884 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1885 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1887 /* Win2k: MDI client still returns a just destroyed child as active
1888 * Win9x: MDI client returns mdi_child2
1890 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1891 ok(active_child == mdi_child || /* win2k */
1892 active_child == mdi_child2, /* win9x */
1893 "wrong active MDI child %p\n", active_child);
1894 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1897 ShowWindow(mdi_child2, SW_MAXIMIZE);
1898 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
1900 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1901 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
1903 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1904 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1905 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1908 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1909 ok(GetFocus() == mdi_child2 || /* win2k */
1910 GetFocus() == 0, /* win9x */
1911 "wrong focus window %p\n", GetFocus());
1916 ShowWindow(mdi_child2, SW_HIDE);
1917 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1919 ShowWindow(mdi_child2, SW_RESTORE);
1920 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
1923 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1924 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
1926 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1927 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1928 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1934 ShowWindow(mdi_child2, SW_HIDE);
1935 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1937 ShowWindow(mdi_child2, SW_SHOW);
1938 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
1940 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1941 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1943 ShowWindow(mdi_child2, SW_MAXIMIZE);
1944 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
1946 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1947 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1949 ShowWindow(mdi_child2, SW_RESTORE);
1950 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
1952 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1953 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1958 ShowWindow(mdi_child2, SW_HIDE);
1959 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1961 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1962 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1964 DestroyWindow(mdi_child2);
1965 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
1967 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1968 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1970 /* test for maximized MDI children */
1971 trace("creating maximized visible MDI child window 1\n");
1972 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1973 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
1974 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1975 mdi_client, 0, GetModuleHandleA(0), NULL);
1977 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
1978 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
1980 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1981 ok(GetFocus() == mdi_child || /* win2k */
1982 GetFocus() == 0, /* win9x */
1983 "wrong focus window %p\n", GetFocus());
1985 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1986 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
1987 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1990 trace("creating maximized visible MDI child window 2\n");
1991 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1992 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
1993 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1994 mdi_client, 0, GetModuleHandleA(0), NULL);
1996 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
1997 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
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() == mdi_child2, "wrong focus window %p\n", GetFocus());
2003 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2004 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2005 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2008 trace("destroying maximized visible MDI child window 2\n");
2009 DestroyWindow(mdi_child2);
2010 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2012 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2014 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2015 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2017 /* Win2k: MDI client still returns a just destroyed child as active
2018 * Win9x: MDI client returns 0
2020 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2021 ok(active_child == mdi_child2 || /* win2k */
2022 !active_child, /* win9x */
2023 "wrong active MDI child %p\n", active_child);
2026 ShowWindow(mdi_child, SW_MAXIMIZE);
2027 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2030 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2031 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2033 trace("re-creating maximized visible MDI child window 2\n");
2034 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
2035 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
2036 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
2037 mdi_client, 0, GetModuleHandleA(0), NULL);
2039 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
2040 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
2041 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
2043 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2044 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
2046 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2047 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
2048 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2051 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
2052 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
2053 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
2055 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2056 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2057 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2059 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2060 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2061 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2064 DestroyWindow(mdi_child);
2065 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2067 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2068 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2070 /* Win2k: MDI client still returns a just destroyed child as active
2071 * Win9x: MDI client returns 0
2073 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2074 ok(active_child == mdi_child || /* win2k */
2075 !active_child, /* win9x */
2076 "wrong active MDI child %p\n", active_child);
2078 /* end of test for maximized MDI children */
2080 mdi_cs.szClass = "MDI_child_Class";
2081 mdi_cs.szTitle = "MDI child";
2082 mdi_cs.hOwner = GetModuleHandleA(0);
2085 mdi_cs.cx = CW_USEDEFAULT;
2086 mdi_cs.cy = CW_USEDEFAULT;
2087 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
2089 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
2090 ok(mdi_child != 0, "MDI child creation failed\n");
2091 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
2093 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
2095 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2096 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2098 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
2099 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2100 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2102 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2103 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2104 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2107 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
2108 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
2110 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
2111 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2112 ok(!active_child, "wrong active MDI child %p\n", active_child);
2117 DestroyWindow(mdi_client);
2118 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
2120 DestroyWindow(mdi_frame);
2121 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
2123 /************************* End of MDI test **********************************/
2125 static void test_WM_SETREDRAW(HWND hwnd)
2127 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
2131 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
2132 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
2134 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
2135 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
2138 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
2139 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
2141 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2142 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
2144 /* restore original WS_VISIBLE state */
2145 SetWindowLongA(hwnd, GWL_STYLE, style);
2150 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2154 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2156 msg.message = message;
2157 msg.flags = sent|wparam|lparam;
2158 msg.wParam = wParam;
2159 msg.lParam = lParam;
2162 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2163 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2167 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2169 DWORD style, exstyle;
2172 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2173 style = GetWindowLongA(hwnd, GWL_STYLE);
2174 /* do not be confused by WS_DLGFRAME set */
2175 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2177 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2178 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2180 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2181 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2182 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
2184 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2186 style = GetWindowLongA(hwnd, GWL_STYLE);
2187 if (set) ok(style & set, "style %08lx should be set\n", set);
2188 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2190 /* a subsequent call should do nothing */
2191 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2192 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2196 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2197 ok(GetScrollRange(hwnd, ctl, &xmin, &xmax), "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
2198 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2199 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
2200 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
2203 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2205 DWORD style, exstyle;
2208 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2209 style = GetWindowLongA(hwnd, GWL_STYLE);
2210 /* do not be confused by WS_DLGFRAME set */
2211 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2213 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2214 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2216 si.cbSize = sizeof(si);
2217 si.fMask = SIF_RANGE;
2220 SetScrollInfo(hwnd, ctl, &si, TRUE);
2221 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2222 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
2224 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2226 style = GetWindowLongA(hwnd, GWL_STYLE);
2227 if (set) ok(style & set, "style %08lx should be set\n", set);
2228 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2230 /* a subsequent call should do nothing */
2231 SetScrollInfo(hwnd, ctl, &si, TRUE);
2232 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2234 si.fMask = SIF_PAGE;
2236 SetScrollInfo(hwnd, ctl, &si, FALSE);
2237 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2241 SetScrollInfo(hwnd, ctl, &si, FALSE);
2242 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2244 si.fMask = SIF_RANGE;
2245 si.nMin = 0xdeadbeef;
2246 si.nMax = 0xdeadbeef;
2247 ok(GetScrollInfo(hwnd, ctl, &si), "GetScrollInfo error %ld\n", GetLastError());
2248 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2249 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
2250 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
2253 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2254 static void test_scroll_messages(HWND hwnd)
2261 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
2262 if (sequence->message != WmGetScrollRangeSeq[0].message)
2263 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2264 /* values of min and max are undefined */
2267 ok(SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE), "SetScrollRange error %ld\n", GetLastError());
2268 if (sequence->message != WmSetScrollRangeSeq[0].message)
2269 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2274 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
2275 if (sequence->message != WmGetScrollRangeSeq[0].message)
2276 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2277 /* values of min and max are undefined */
2280 si.cbSize = sizeof(si);
2281 si.fMask = SIF_RANGE;
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_PAGE;
2291 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2292 if (sequence->message != WmSetScrollRangeSeq[0].message)
2293 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2298 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2299 if (sequence->message != WmSetScrollRangeSeq[0].message)
2300 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2303 si.fMask = SIF_RANGE;
2304 si.nMin = 0xdeadbeef;
2305 si.nMax = 0xdeadbeef;
2306 ok(GetScrollInfo(hwnd, SB_CTL, &si), "GetScrollInfo error %ld\n", GetLastError());
2307 if (sequence->message != WmGetScrollInfoSeq[0].message)
2308 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2309 /* values of min and max are undefined */
2312 /* set WS_HSCROLL */
2313 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2314 /* clear WS_HSCROLL */
2315 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2317 /* set WS_HSCROLL */
2318 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2319 /* clear WS_HSCROLL */
2320 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2322 /* set WS_VSCROLL */
2323 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2324 /* clear WS_VSCROLL */
2325 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2327 /* set WS_VSCROLL */
2328 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2329 /* clear WS_VSCROLL */
2330 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2333 /* test if we receive the right sequence of messages */
2334 static void test_messages(void)
2336 HWND hwnd, hparent, hchild;
2337 HWND hchild2, hbutton;
2341 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2342 100, 100, 200, 200, 0, 0, 0, NULL);
2343 ok (hwnd != 0, "Failed to create overlapped window\n");
2344 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2346 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2347 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
2348 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
2350 /* test WM_SETREDRAW on a not visible top level window */
2351 test_WM_SETREDRAW(hwnd);
2353 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2354 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
2355 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
2357 ok(GetActiveWindow() == hwnd, "window should be active\n");
2358 ok(GetFocus() == hwnd, "window should have input focus\n");
2359 ShowWindow(hwnd, SW_HIDE);
2360 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
2362 ShowWindow(hwnd, SW_SHOW);
2363 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
2365 ok(GetActiveWindow() == hwnd, "window should be active\n");
2366 ok(GetFocus() == hwnd, "window should have input focus\n");
2367 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2368 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
2369 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
2371 /* test WM_SETREDRAW on a visible top level window */
2372 ShowWindow(hwnd, SW_SHOW);
2373 test_WM_SETREDRAW(hwnd);
2375 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
2376 test_scroll_messages(hwnd);
2378 DestroyWindow(hwnd);
2379 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
2381 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2382 100, 100, 200, 200, 0, 0, 0, NULL);
2383 ok (hparent != 0, "Failed to create parent window\n");
2386 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
2387 0, 0, 10, 10, hparent, 0, 0, NULL);
2388 ok (hchild != 0, "Failed to create child window\n");
2389 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
2390 DestroyWindow(hchild);
2393 /* visible child window with a caption */
2394 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
2395 WS_CHILD | WS_VISIBLE | WS_CAPTION,
2396 0, 0, 10, 10, hparent, 0, 0, NULL);
2397 ok (hchild != 0, "Failed to create child window\n");
2398 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
2400 trace("testing scroll APIs on a visible child window %p\n", hchild);
2401 test_scroll_messages(hchild);
2403 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2404 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
2406 DestroyWindow(hchild);
2409 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2410 0, 0, 10, 10, hparent, 0, 0, NULL);
2411 ok (hchild != 0, "Failed to create child window\n");
2412 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2414 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
2415 100, 100, 50, 50, hparent, 0, 0, NULL);
2416 ok (hchild2 != 0, "Failed to create child2 window\n");
2419 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
2420 0, 100, 50, 50, hchild, 0, 0, NULL);
2421 ok (hbutton != 0, "Failed to create button window\n");
2423 /* test WM_SETREDRAW on a not visible child window */
2424 test_WM_SETREDRAW(hchild);
2426 ShowWindow(hchild, SW_SHOW);
2427 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2429 ShowWindow(hchild, SW_HIDE);
2430 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
2432 ShowWindow(hchild, SW_SHOW);
2433 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2435 /* test WM_SETREDRAW on a visible child window */
2436 test_WM_SETREDRAW(hchild);
2438 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
2439 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
2441 ShowWindow(hchild, SW_HIDE);
2443 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2444 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
2446 ShowWindow(hchild, SW_HIDE);
2448 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2449 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
2451 /* DestroyWindow sequence below expects that a child has focus */
2455 DestroyWindow(hchild);
2456 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
2457 DestroyWindow(hchild2);
2458 DestroyWindow(hbutton);
2461 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
2462 0, 0, 100, 100, hparent, 0, 0, NULL);
2463 ok (hchild != 0, "Failed to create child popup window\n");
2464 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
2465 DestroyWindow(hchild);
2467 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
2469 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
2470 0, 0, 100, 100, hparent, 0, 0, NULL);
2471 ok (hchild != 0, "Failed to create popup window\n");
2472 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2473 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2474 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2476 ShowWindow(hchild, SW_SHOW);
2477 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2479 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2480 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2482 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2483 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
2484 DestroyWindow(hchild);
2486 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2487 * changes nothing in message sequences.
2490 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
2491 0, 0, 100, 100, hparent, 0, 0, NULL);
2492 ok (hchild != 0, "Failed to create popup window\n");
2493 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2494 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2495 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2497 ShowWindow(hchild, SW_SHOW);
2498 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2500 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2501 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2502 DestroyWindow(hchild);
2505 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
2506 0, 0, 100, 100, hparent, 0, 0, NULL);
2507 ok(hwnd != 0, "Failed to create custom dialog window\n");
2508 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
2510 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
2511 test_scroll_messages(hwnd);
2514 after_end_dialog = 1;
2515 EndDialog( hwnd, 0 );
2516 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
2518 DestroyWindow(hwnd);
2519 after_end_dialog = 0;
2522 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
2523 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
2525 /* test showing child with hidden parent */
2526 ShowWindow( hparent, SW_HIDE );
2529 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2530 0, 0, 10, 10, hparent, 0, 0, NULL);
2531 ok (hchild != 0, "Failed to create child window\n");
2532 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2534 ShowWindow( hchild, SW_SHOW );
2535 ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", TRUE);
2536 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2537 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2539 ShowWindow( hchild, SW_HIDE );
2540 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", TRUE);
2541 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
2542 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2544 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2545 ok_sequence(WmShowChildInvisibleParentSeq_2, "SetWindowPos:show child with invisible parent", TRUE);
2546 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2547 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2549 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2550 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", TRUE);
2551 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
2552 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2554 DestroyWindow(hchild);
2555 DestroyWindow(hparent);
2558 /* Message sequence for SetMenu */
2559 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
2560 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
2562 hmenu = CreateMenu();
2563 ok (hmenu != 0, "Failed to create menu\n");
2564 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
2565 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2566 100, 100, 200, 200, 0, hmenu, 0, NULL);
2567 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2568 ok (SetMenu(hwnd, 0), "SetMenu\n");
2569 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
2570 ok (SetMenu(hwnd, 0), "SetMenu\n");
2571 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
2572 ShowWindow(hwnd, SW_SHOW);
2574 ok (SetMenu(hwnd, 0), "SetMenu\n");
2575 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
2576 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
2577 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
2579 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
2580 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
2582 DestroyWindow(hwnd);
2585 /* Message sequence for EnableWindow */
2586 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2587 100, 100, 200, 200, 0, 0, 0, NULL);
2588 ok (hparent != 0, "Failed to create parent window\n");
2589 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
2590 0, 0, 10, 10, hparent, 0, 0, NULL);
2591 ok (hchild != 0, "Failed to create child window\n");
2596 EnableWindow(hparent, FALSE);
2597 ok_sequence(WmEnableWindowSeq, "EnableWindow", FALSE);
2599 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
2601 PostMessage( hparent, WM_USER, 0, 0 );
2602 PostMessage( hparent, WM_USER+1, 0, 0 );
2603 /* PeekMessage(NULL) fails, but still removes the message */
2604 SetLastError(0xdeadbeef);
2605 ok( !PeekMessage( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
2606 ok( GetLastError() == ERROR_NOACCESS, "last error is %ld\n", GetLastError() );
2607 ok( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
2608 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
2610 DestroyWindow(hchild);
2611 DestroyWindow(hparent);
2615 /****************** button message test *************************/
2616 static const struct message WmSetFocusButtonSeq[] =
2618 { HCBT_SETFOCUS, hook },
2619 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2620 { WM_SETFOCUS, sent|wparam, 0 },
2621 { WM_CTLCOLORBTN, sent|defwinproc },
2624 static const struct message WmKillFocusButtonSeq[] =
2626 { HCBT_SETFOCUS, hook },
2627 { WM_KILLFOCUS, sent|wparam, 0 },
2628 { WM_CTLCOLORBTN, sent|defwinproc },
2629 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2632 static const struct message WmSetFocusStaticSeq[] =
2634 { HCBT_SETFOCUS, hook },
2635 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2636 { WM_SETFOCUS, sent|wparam, 0 },
2637 { WM_CTLCOLORSTATIC, sent|defwinproc },
2640 static const struct message WmKillFocusStaticSeq[] =
2642 { HCBT_SETFOCUS, hook },
2643 { WM_KILLFOCUS, sent|wparam, 0 },
2644 { WM_CTLCOLORSTATIC, sent|defwinproc },
2645 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2648 static const struct message WmLButtonDownSeq[] =
2650 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
2651 { HCBT_SETFOCUS, hook },
2652 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2653 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
2654 { WM_CTLCOLORBTN, sent|defwinproc },
2655 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
2656 { WM_CTLCOLORBTN, sent|defwinproc },
2659 static const struct message WmLButtonUpSeq[] =
2661 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
2662 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
2663 { WM_CTLCOLORBTN, sent|defwinproc },
2664 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
2668 static WNDPROC old_button_proc;
2670 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2672 static long defwndproc_counter = 0;
2676 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2678 msg.message = message;
2679 msg.flags = sent|wparam|lparam;
2680 if (defwndproc_counter) msg.flags |= defwinproc;
2681 msg.wParam = wParam;
2682 msg.lParam = lParam;
2685 if (message == BM_SETSTATE)
2686 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
2688 defwndproc_counter++;
2689 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
2690 defwndproc_counter--;
2695 static void subclass_button(void)
2699 if (!GetClassInfoA(0, "button", &cls)) assert(0);
2701 old_button_proc = cls.lpfnWndProc;
2703 cls.hInstance = GetModuleHandle(0);
2704 cls.lpfnWndProc = button_hook_proc;
2705 cls.lpszClassName = "my_button_class";
2706 if (!RegisterClassA(&cls)) assert(0);
2709 static void test_button_messages(void)
2715 const struct message *setfocus;
2716 const struct message *killfocus;
2718 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
2719 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2720 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
2721 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2722 { BS_CHECKBOX, DLGC_BUTTON,
2723 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2724 { BS_AUTOCHECKBOX, DLGC_BUTTON,
2725 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2726 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
2727 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2728 { BS_3STATE, DLGC_BUTTON,
2729 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2730 { BS_AUTO3STATE, DLGC_BUTTON,
2731 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2732 { BS_GROUPBOX, DLGC_STATIC,
2733 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2734 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
2735 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2736 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
2737 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2738 { BS_OWNERDRAW, DLGC_BUTTON,
2739 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
2747 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
2749 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
2750 0, 0, 50, 14, 0, 0, 0, NULL);
2751 ok(hwnd != 0, "Failed to create button window\n");
2753 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
2754 ok(dlg_code == button[i].dlg_code, "%d: wrong dlg_code %08lx\n", i, dlg_code);
2756 ShowWindow(hwnd, SW_SHOW);
2761 trace("button style %08lx\n", button[i].style);
2763 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
2766 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
2768 DestroyWindow(hwnd);
2771 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
2772 0, 0, 50, 14, 0, 0, 0, NULL);
2773 ok(hwnd != 0, "Failed to create button window\n");
2778 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
2779 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
2781 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
2782 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONDOWN on a button", FALSE);
2783 DestroyWindow(hwnd);
2786 /************* painting message test ********************/
2788 static void dump_region(HRGN hrgn)
2791 RGNDATA *data = NULL;
2796 printf( "null region\n" );
2799 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
2800 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
2801 GetRegionData( hrgn, size, data );
2802 printf("%ld rects:", data->rdh.nCount );
2803 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
2804 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
2806 HeapFree( GetProcessHeap(), 0, data );
2809 static void check_update_rgn( HWND hwnd, HRGN hrgn )
2813 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
2814 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
2816 ret = GetUpdateRgn( hwnd, update, FALSE );
2817 ok( ret != ERROR, "GetUpdateRgn failed\n" );
2818 if (ret == NULLREGION)
2820 ok( !hrgn, "Update region shouldn't be empty\n" );
2824 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
2826 ok( 0, "Regions are different\n" );
2827 if (winetest_debug > 0)
2829 printf( "Update region: " );
2830 dump_region( update );
2831 printf( "Wanted region: " );
2832 dump_region( hrgn );
2836 GetRgnBox( update, &r1 );
2837 GetUpdateRect( hwnd, &r2, FALSE );
2838 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
2839 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
2840 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
2842 DeleteObject( tmp );
2843 DeleteObject( update );
2846 static const struct message WmInvalidateRgn[] = {
2847 { WM_NCPAINT, sent },
2848 { WM_GETTEXT, sent|defwinproc|optional },
2852 static const struct message WmGetUpdateRect[] = {
2853 { WM_NCPAINT, sent },
2854 { WM_GETTEXT, sent|defwinproc|optional },
2859 static const struct message WmInvalidateFull[] = {
2860 { WM_NCPAINT, sent|wparam, 1 },
2861 { WM_GETTEXT, sent|defwinproc|optional },
2865 static const struct message WmInvalidateErase[] = {
2866 { WM_NCPAINT, sent|wparam, 1 },
2867 { WM_GETTEXT, sent|defwinproc|optional },
2868 { WM_ERASEBKGND, sent },
2872 static const struct message WmInvalidatePaint[] = {
2874 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
2875 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2879 static const struct message WmInvalidateErasePaint[] = {
2881 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
2882 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2883 { WM_ERASEBKGND, sent|beginpaint },
2887 static const struct message WmInvalidateErasePaint2[] = {
2889 { WM_NCPAINT, sent|beginpaint },
2890 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2891 { WM_ERASEBKGND, sent|beginpaint },
2895 static const struct message WmErase[] = {
2896 { WM_ERASEBKGND, sent },
2900 static const struct message WmPaint[] = {
2905 static const struct message WmParentOnlyPaint[] = {
2906 { WM_PAINT, sent|parent },
2910 static const struct message WmInvalidateParent[] = {
2911 { WM_NCPAINT, sent|parent },
2912 { WM_GETTEXT, sent|defwinproc|parent|optional },
2913 { WM_ERASEBKGND, sent|parent },
2917 static const struct message WmInvalidateParentChild[] = {
2918 { WM_NCPAINT, sent|parent },
2919 { WM_GETTEXT, sent|defwinproc|parent|optional },
2920 { WM_ERASEBKGND, sent|parent },
2921 { WM_NCPAINT, sent },
2922 { WM_GETTEXT, sent|defwinproc|optional },
2923 { WM_ERASEBKGND, sent },
2927 static const struct message WmInvalidateParentChild2[] = {
2928 { WM_ERASEBKGND, sent|parent },
2929 { WM_NCPAINT, sent },
2930 { WM_GETTEXT, sent|defwinproc|optional },
2931 { WM_ERASEBKGND, sent },
2935 static const struct message WmParentPaint[] = {
2936 { WM_PAINT, sent|parent },
2941 static const struct message WmParentPaintNc[] = {
2942 { WM_PAINT, sent|parent },
2944 { WM_NCPAINT, sent|beginpaint },
2945 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2946 { WM_ERASEBKGND, sent|beginpaint },
2950 static const struct message WmChildPaintNc[] = {
2952 { WM_NCPAINT, sent|beginpaint },
2953 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2954 { WM_ERASEBKGND, sent|beginpaint },
2958 static const struct message WmParentErasePaint[] = {
2959 { WM_PAINT, sent|parent },
2960 { WM_NCPAINT, sent|parent|beginpaint },
2961 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
2962 { WM_ERASEBKGND, sent|parent|beginpaint },
2964 { WM_NCPAINT, sent|beginpaint },
2965 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2966 { WM_ERASEBKGND, sent|beginpaint },
2970 static const struct message WmParentOnlyNcPaint[] = {
2971 { WM_PAINT, sent|parent },
2972 { WM_NCPAINT, sent|parent|beginpaint },
2973 { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional },
2977 static const struct message WmSetParentStyle[] = {
2978 { WM_STYLECHANGING, sent|parent },
2979 { WM_STYLECHANGED, sent|parent },
2983 static void test_paint_messages(void)
2988 HWND hparent, hchild;
2989 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2990 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
2991 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2992 100, 100, 200, 200, 0, 0, 0, NULL);
2993 ok (hwnd != 0, "Failed to create overlapped window\n");
2995 ShowWindow( hwnd, SW_SHOW );
2996 UpdateWindow( hwnd );
2998 /* try to flush pending X expose events */
2999 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3000 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3002 check_update_rgn( hwnd, 0 );
3003 SetRectRgn( hrgn, 10, 10, 20, 20 );
3004 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3005 check_update_rgn( hwnd, hrgn );
3006 SetRectRgn( hrgn2, 20, 20, 30, 30 );
3007 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
3008 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
3009 check_update_rgn( hwnd, hrgn );
3010 /* validate everything */
3011 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
3012 check_update_rgn( hwnd, 0 );
3013 /* now with frame */
3014 SetRectRgn( hrgn, -5, -5, 20, 20 );
3016 /* flush pending messages */
3017 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3020 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3021 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3023 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
3024 check_update_rgn( hwnd, hrgn );
3027 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3028 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3031 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
3032 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
3034 GetClientRect( hwnd, &rect );
3035 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
3036 check_update_rgn( hwnd, hrgn );
3039 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
3040 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
3043 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
3044 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
3045 check_update_rgn( hwnd, 0 );
3048 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
3049 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
3050 check_update_rgn( hwnd, 0 );
3053 SetRectRgn( hrgn, 0, 0, 100, 100 );
3054 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
3055 SetRectRgn( hrgn, 0, 0, 50, 100 );
3056 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
3057 SetRectRgn( hrgn, 50, 0, 100, 100 );
3058 check_update_rgn( hwnd, hrgn );
3059 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3060 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
3061 check_update_rgn( hwnd, 0 );
3064 SetRectRgn( hrgn, 0, 0, 100, 100 );
3065 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3066 SetRectRgn( hrgn, 0, 0, 100, 50 );
3067 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
3068 ok_sequence( WmErase, "Erase", FALSE );
3069 SetRectRgn( hrgn, 0, 50, 100, 100 );
3070 check_update_rgn( hwnd, hrgn );
3073 SetRectRgn( hrgn, 0, 0, 100, 100 );
3074 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
3075 SetRectRgn( hrgn, 0, 0, 50, 50 );
3076 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
3077 ok_sequence( WmPaint, "Paint", FALSE );
3080 SetRectRgn( hrgn, -4, -4, -2, -2 );
3081 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3082 SetRectRgn( hrgn, -200, -200, -198, -198 );
3083 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
3084 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
3087 SetRectRgn( hrgn, -4, -4, -2, -2 );
3088 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3089 SetRectRgn( hrgn, -4, -4, -3, -3 );
3090 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
3091 SetRectRgn( hrgn, 0, 0, 1, 1 );
3092 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
3093 ok_sequence( WmPaint, "Paint", FALSE );
3096 SetRectRgn( hrgn, -4, -4, -1, -1 );
3097 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3098 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
3099 /* make sure no WM_PAINT was generated */
3100 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3101 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
3104 SetRectRgn( hrgn, -4, -4, -1, -1 );
3105 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
3106 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
3108 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
3110 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
3111 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
3112 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
3113 ret = GetUpdateRect( hwnd, &rect, FALSE );
3114 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
3115 /* this will send WM_NCPAINT and validate the non client area */
3116 ret = GetUpdateRect( hwnd, &rect, TRUE );
3117 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
3119 DispatchMessage( &msg );
3121 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
3123 DestroyWindow( hwnd );
3125 /* now test with a child window */
3127 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
3128 100, 100, 200, 200, 0, 0, 0, NULL);
3129 ok (hparent != 0, "Failed to create parent window\n");
3131 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
3132 10, 10, 100, 100, hparent, 0, 0, NULL);
3133 ok (hchild != 0, "Failed to create child window\n");
3135 ShowWindow( hparent, SW_SHOW );
3136 UpdateWindow( hparent );
3137 UpdateWindow( hchild );
3138 /* try to flush pending X expose events */
3139 MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
3140 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3143 log_all_parent_messages++;
3145 SetRect( &rect, 0, 0, 50, 50 );
3146 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3147 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3148 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
3150 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3152 MapWindowPoints( hchild, hparent, &pt, 1 );
3153 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
3154 check_update_rgn( hchild, hrgn );
3155 SetRectRgn( hrgn, 0, 0, 50, 50 );
3156 check_update_rgn( hparent, hrgn );
3157 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3158 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
3159 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3160 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3162 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3163 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
3165 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3166 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3167 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
3168 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
3169 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
3171 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
3172 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN );
3173 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
3175 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3177 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
3178 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3179 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
3181 /* flush all paint messages */
3182 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3185 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
3186 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
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( hrgn, 0, 0, 50, 50 );
3192 check_update_rgn( hparent, hrgn );
3194 /* flush all paint messages */
3195 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3196 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3199 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
3200 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3201 SetRectRgn( hrgn, 0, 0, 50, 50 );
3202 check_update_rgn( hparent, hrgn );
3203 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3204 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3205 SetRectRgn( hrgn2, 10, 10, 50, 50 );
3206 CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
3207 check_update_rgn( hparent, hrgn );
3208 /* flush all paint messages */
3209 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3212 /* same as above but parent gets completely validated */
3213 SetRect( &rect, 20, 20, 30, 30 );
3214 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3215 SetRectRgn( hrgn, 20, 20, 30, 30 );
3216 check_update_rgn( hparent, hrgn );
3217 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
3218 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3219 check_update_rgn( hparent, 0 ); /* no update region */
3220 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3221 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
3223 /* make sure RDW_VALIDATE on child doesn't have the same effect */
3225 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3226 SetRectRgn( hrgn, 20, 20, 30, 30 );
3227 check_update_rgn( hparent, hrgn );
3228 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
3229 SetRectRgn( hrgn, 20, 20, 30, 30 );
3230 check_update_rgn( hparent, hrgn );
3232 /* same as above but normal WM_PAINT doesn't validate parent */
3234 SetRect( &rect, 20, 20, 30, 30 );
3235 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3236 SetRectRgn( hrgn, 20, 20, 30, 30 );
3237 check_update_rgn( hparent, hrgn );
3238 /* no WM_PAINT in child while parent still pending */
3239 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3240 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3241 while (PeekMessage( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3242 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
3245 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
3246 /* no WM_PAINT in child while parent still pending */
3247 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3248 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3249 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN );
3250 /* now that parent is valid child should get WM_PAINT */
3251 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3252 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
3253 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3254 ok_sequence( WmEmptySeq, "No other message", FALSE );
3256 /* same thing with WS_CLIPCHILDREN in parent */
3258 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) | WS_CLIPCHILDREN );
3259 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3260 /* changing style invalidates non client area, but we need to invalidate something else to see it */
3261 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
3262 ok_sequence( WmEmptySeq, "No message", FALSE );
3263 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
3264 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
3267 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
3268 SetRectRgn( hrgn, 20, 20, 30, 30 );
3269 check_update_rgn( hparent, hrgn );
3270 /* no WM_PAINT in child while parent still pending */
3271 while (PeekMessage( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3272 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
3273 /* WM_PAINT in parent first */
3274 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3275 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
3277 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
3279 SetRect( &rect, 0, 0, 30, 30 );
3280 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN );
3281 SetRectRgn( hrgn, 0, 0, 30, 30 );
3282 check_update_rgn( hparent, hrgn );
3283 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3284 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
3286 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3288 SetRect( &rect, -10, 0, 30, 30 );
3289 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3290 SetRect( &rect, 0, 0, 20, 20 );
3291 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3292 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3293 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
3295 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3297 SetRect( &rect, -10, 0, 30, 30 );
3298 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
3299 SetRect( &rect, 0, 0, 100, 100 );
3300 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
3301 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
3302 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
3303 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
3304 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
3306 /* test RDW_INTERNALPAINT behavior */
3309 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN );
3310 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3311 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3313 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN );
3314 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3315 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3317 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3318 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3319 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
3321 SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
3322 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
3323 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
3324 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
3325 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
3327 log_all_parent_messages--;
3328 DestroyWindow( hparent );
3330 DeleteObject( hrgn );
3331 DeleteObject( hrgn2 );
3340 static DWORD WINAPI thread_proc(void *param)
3343 struct wnd_event *wnd_event = (struct wnd_event *)param;
3345 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
3346 100, 100, 200, 200, 0, 0, 0, NULL);
3347 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
3349 SetEvent(wnd_event->event);
3351 while (GetMessage(&msg, 0, 0, 0))
3353 TranslateMessage(&msg);
3354 DispatchMessage(&msg);
3360 static void test_interthread_messages(void)
3367 int len, expected_len;
3368 struct wnd_event wnd_event;
3370 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
3371 if (!wnd_event.event)
3373 trace("skipping interthread message test under win9x\n");
3377 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
3378 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
3380 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3382 CloseHandle(wnd_event.event);
3384 SetLastError(0xdeadbeef);
3385 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
3386 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
3388 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3389 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
3391 expected_len = lstrlenA("window caption text");
3392 memset(buf, 0, sizeof(buf));
3393 SetLastError(0xdeadbeef);
3394 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
3395 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
3396 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
3398 msg.hwnd = wnd_event.hwnd;
3399 msg.message = WM_GETTEXT;
3400 msg.wParam = sizeof(buf);
3401 msg.lParam = (LPARAM)buf;
3402 memset(buf, 0, sizeof(buf));
3403 SetLastError(0xdeadbeef);
3404 len = DispatchMessageA(&msg);
3405 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3406 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
3408 /* the following test causes an exception in user.exe under win9x */
3409 msg.hwnd = wnd_event.hwnd;
3410 msg.message = WM_TIMER;
3412 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3413 SetLastError(0xdeadbeef);
3414 len = DispatchMessageA(&msg);
3415 ok(!len && GetLastError() == 0xdeadbeef,
3416 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
3418 ok(PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0), "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
3420 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3421 CloseHandle(hThread);
3425 static const struct message WmVkN[] = {
3426 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3427 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3428 { WM_CHAR, wparam|lparam, 'n', 1 },
3429 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
3430 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3431 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3434 static const struct message WmShiftVkN[] = {
3435 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
3436 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
3437 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3438 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3439 { WM_CHAR, wparam|lparam, 'N', 1 },
3440 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
3441 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3442 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3443 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
3444 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
3447 static const struct message WmCtrlVkN[] = {
3448 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3449 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3450 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3451 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3452 { WM_CHAR, wparam|lparam, 0x000e, 1 },
3453 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3454 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3455 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3456 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3457 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3460 static const struct message WmCtrlVkN_2[] = {
3461 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3462 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3463 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3464 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3465 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3466 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3467 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3468 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3471 static const struct message WmAltVkN[] = {
3472 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3473 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3474 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3475 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3476 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
3477 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
3478 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
3479 { HCBT_SYSCOMMAND, hook },
3480 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
3481 { WM_SETCURSOR, sent|defwinproc },
3482 { WM_INITMENU, sent|defwinproc },
3483 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
3484 { WM_CAPTURECHANGED, sent|defwinproc },
3485 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
3486 { WM_EXITMENULOOP, sent|defwinproc },
3487 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
3488 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
3489 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3490 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3491 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3492 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3495 static const struct message WmAltVkN_2[] = {
3496 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3497 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3498 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3499 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
3500 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3501 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3502 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3503 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3506 static const struct message WmCtrlAltVkN[] = {
3507 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3508 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3509 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3510 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3511 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
3512 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3513 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
3514 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3515 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3516 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3517 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3518 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3522 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
3526 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
3528 struct message log_msg;
3530 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
3532 log_msg.message = msg.message;
3533 log_msg.flags = wparam|lparam;
3534 log_msg.wParam = msg.wParam;
3535 log_msg.lParam = msg.lParam;
3536 add_message(&log_msg);
3538 if (!TranslateAccelerator(hwnd, hAccel, &msg))
3540 TranslateMessage(&msg);
3541 DispatchMessage(&msg);
3546 static void test_accelerators(void)
3550 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
3551 100, 100, 200, 200, 0, 0, 0, NULL);
3555 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3557 state = GetKeyState(VK_SHIFT);
3558 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
3559 state = GetKeyState(VK_CAPITAL);
3560 ok(state == 0, "wrong CapsLock state %04x\n", state);
3562 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
3563 assert(hAccel != 0);
3565 trace("testing VK_N press/release\n");
3567 keybd_event('N', 0, 0, 0);
3568 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3569 pump_msg_loop(hwnd, hAccel);
3570 ok_sequence(WmVkN, "VK_N press/release", FALSE);
3572 trace("testing Shift+VK_N press/release\n");
3574 keybd_event(VK_SHIFT, 0, 0, 0);
3575 keybd_event('N', 0, 0, 0);
3576 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3577 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
3578 pump_msg_loop(hwnd, hAccel);
3579 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
3581 trace("testing Ctrl+VK_N press/release\n");
3583 keybd_event(VK_CONTROL, 0, 0, 0);
3584 keybd_event('N', 0, 0, 0);
3585 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3586 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3587 pump_msg_loop(hwnd, hAccel);
3588 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
3590 trace("testing Alt+VK_N press/release\n");
3592 keybd_event(VK_MENU, 0, 0, 0);
3593 keybd_event('N', 0, 0, 0);
3594 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3595 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3596 pump_msg_loop(hwnd, hAccel);
3597 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
3599 trace("testing Ctrl+Alt+VK_N press/release\n");
3601 keybd_event(VK_CONTROL, 0, 0, 0);
3602 keybd_event(VK_MENU, 0, 0, 0);
3603 keybd_event('N', 0, 0, 0);
3604 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3605 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3606 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3607 pump_msg_loop(hwnd, hAccel);
3608 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
3610 ok(DestroyAcceleratorTable(hAccel), "DestroyAcceleratorTable error %ld\n", GetLastError());
3612 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
3613 assert(hAccel != 0);
3615 trace("testing VK_N press/release\n");
3617 keybd_event('N', 0, 0, 0);
3618 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3619 pump_msg_loop(hwnd, hAccel);
3620 ok_sequence(WmVkN, "VK_N press/release", FALSE);
3622 trace("testing Shift+VK_N press/release\n");
3624 keybd_event(VK_SHIFT, 0, 0, 0);
3625 keybd_event('N', 0, 0, 0);
3626 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3627 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
3628 pump_msg_loop(hwnd, hAccel);
3629 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
3631 trace("testing Ctrl+VK_N press/release 2\n");
3633 keybd_event(VK_CONTROL, 0, 0, 0);
3634 keybd_event('N', 0, 0, 0);
3635 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3636 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3637 pump_msg_loop(hwnd, hAccel);
3638 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
3640 trace("testing Alt+VK_N press/release 2\n");
3642 keybd_event(VK_MENU, 0, 0, 0);
3643 keybd_event('N', 0, 0, 0);
3644 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3645 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3646 pump_msg_loop(hwnd, hAccel);
3647 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
3649 trace("testing Ctrl+Alt+VK_N press/release\n");
3651 keybd_event(VK_CONTROL, 0, 0, 0);
3652 keybd_event(VK_MENU, 0, 0, 0);
3653 keybd_event('N', 0, 0, 0);
3654 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3655 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3656 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3657 pump_msg_loop(hwnd, hAccel);
3658 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
3660 ok(DestroyAcceleratorTable(hAccel), "DestroyAcceleratorTable error %ld\n", GetLastError());
3662 DestroyWindow(hwnd);
3665 /************* window procedures ********************/
3667 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3669 static long defwndproc_counter = 0;
3670 static long beginpaint_counter = 0;
3674 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3678 case WM_WINDOWPOSCHANGING:
3679 case WM_WINDOWPOSCHANGED:
3681 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
3683 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
3684 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
3685 winpos->hwnd, winpos->hwndInsertAfter,
3686 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
3688 /* Log only documented flags, win2k uses 0x1000 and 0x2000
3689 * in the high word for internal purposes
3691 wParam = winpos->flags & 0xffff;
3696 msg.message = message;
3697 msg.flags = sent|wparam|lparam;
3698 if (defwndproc_counter) msg.flags |= defwinproc;
3699 if (beginpaint_counter) msg.flags |= beginpaint;
3700 msg.wParam = wParam;
3701 msg.lParam = lParam;
3704 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
3706 HWND parent = GetParent(hwnd);
3708 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
3710 GetClientRect(parent, &rc);
3711 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
3713 trace("ptReserved = (%ld,%ld)\n"
3714 "ptMaxSize = (%ld,%ld)\n"
3715 "ptMaxPosition = (%ld,%ld)\n"
3716 "ptMinTrackSize = (%ld,%ld)\n"
3717 "ptMaxTrackSize = (%ld,%ld)\n",
3718 minmax->ptReserved.x, minmax->ptReserved.y,
3719 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
3720 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
3721 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
3722 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
3724 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
3725 minmax->ptMaxSize.x, rc.right);
3726 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
3727 minmax->ptMaxSize.y, rc.bottom);
3730 if (message == WM_PAINT)
3733 beginpaint_counter++;
3734 BeginPaint( hwnd, &ps );
3735 beginpaint_counter--;
3736 EndPaint( hwnd, &ps );
3740 defwndproc_counter++;
3741 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3742 defwndproc_counter--;
3747 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3749 static long defwndproc_counter = 0;
3753 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3755 msg.message = message;
3756 msg.flags = sent|wparam|lparam;
3757 if (defwndproc_counter) msg.flags |= defwinproc;
3758 msg.wParam = wParam;
3759 msg.lParam = lParam;
3762 if (message == WM_CREATE)
3764 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
3765 SetWindowLongA(hwnd, GWL_STYLE, style);
3768 defwndproc_counter++;
3769 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3770 defwndproc_counter--;
3775 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3777 static long defwndproc_counter = 0;
3778 static long beginpaint_counter = 0;
3782 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3784 if (log_all_parent_messages ||
3785 message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
3786 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
3787 message == WM_ENABLE || message == WM_ENTERIDLE ||
3788 message == WM_IME_SETCONTEXT)
3790 msg.message = message;
3791 msg.flags = sent|parent|wparam|lparam;
3792 if (defwndproc_counter) msg.flags |= defwinproc;
3793 if (beginpaint_counter) msg.flags |= beginpaint;
3794 msg.wParam = wParam;
3795 msg.lParam = lParam;
3799 if (message == WM_PAINT)
3802 beginpaint_counter++;
3803 BeginPaint( hwnd, &ps );
3804 beginpaint_counter--;
3805 EndPaint( hwnd, &ps );
3809 defwndproc_counter++;
3810 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3811 defwndproc_counter--;
3816 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3818 static long defwndproc_counter = 0;
3822 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3824 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
3825 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
3826 if (after_end_dialog)
3827 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
3829 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
3831 msg.message = message;
3832 msg.flags = sent|wparam|lparam;
3833 if (defwndproc_counter) msg.flags |= defwinproc;
3834 msg.wParam = wParam;
3835 msg.lParam = lParam;
3838 defwndproc_counter++;
3839 ret = DefDlgProcA(hwnd, message, wParam, lParam);
3840 defwndproc_counter--;
3845 static BOOL RegisterWindowClasses(void)
3850 cls.lpfnWndProc = MsgCheckProcA;
3853 cls.hInstance = GetModuleHandleA(0);
3855 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
3856 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
3857 cls.lpszMenuName = NULL;
3858 cls.lpszClassName = "TestWindowClass";
3859 if(!RegisterClassA(&cls)) return FALSE;
3861 cls.lpfnWndProc = PopupMsgCheckProcA;
3862 cls.lpszClassName = "TestPopupClass";
3863 if(!RegisterClassA(&cls)) return FALSE;
3865 cls.lpfnWndProc = ParentMsgCheckProcA;
3866 cls.lpszClassName = "TestParentClass";
3867 if(!RegisterClassA(&cls)) return FALSE;
3869 cls.lpfnWndProc = DefWindowProcA;
3870 cls.lpszClassName = "SimpleWindowClass";
3871 if(!RegisterClassA(&cls)) return FALSE;
3873 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
3874 cls.lpfnWndProc = TestDlgProcA;
3875 cls.lpszClassName = "TestDialogClass";
3876 if(!RegisterClassA(&cls)) return FALSE;
3881 static HHOOK hCBT_hook;
3883 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
3887 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
3889 if (nCode == HCBT_SYSCOMMAND)
3893 msg.message = nCode;
3895 msg.wParam = wParam;
3896 msg.lParam = lParam;
3899 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
3902 /* Log also SetFocus(0) calls */
3903 if (!wParam) wParam = lParam;
3905 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
3907 if (!strcmp(buf, "TestWindowClass") ||
3908 !strcmp(buf, "TestParentClass") ||
3909 !strcmp(buf, "TestPopupClass") ||
3910 !strcmp(buf, "SimpleWindowClass") ||
3911 !strcmp(buf, "TestDialogClass") ||
3912 !strcmp(buf, "MDI_frame_class") ||
3913 !strcmp(buf, "MDI_client_class") ||
3914 !strcmp(buf, "MDI_child_class") ||
3915 !strcmp(buf, "my_button_class") ||
3916 !strcmp(buf, "#32770"))
3920 msg.message = nCode;
3922 msg.wParam = wParam;
3923 msg.lParam = lParam;
3927 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
3930 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
3931 static const WCHAR wszAnsi[] = {'U',0};
3933 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3937 case CB_FINDSTRINGEXACT:
3938 trace("String: %p\n", (LPCWSTR)lParam);
3939 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
3941 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
3945 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
3948 static void test_message_conversion(void)
3950 static const WCHAR wszMsgConversionClass[] =
3951 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
3958 cls.lpfnWndProc = MsgConversionProcW;
3961 cls.hInstance = GetModuleHandleW(NULL);
3963 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
3964 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
3965 cls.lpszMenuName = NULL;
3966 cls.lpszClassName = wszMsgConversionClass;
3967 /* this call will fail on Win9x, but that doesn't matter as this test is
3968 * meaningless on those platforms */
3969 if(!RegisterClassW(&cls)) return;
3971 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
3972 100, 100, 200, 200, 0, 0, 0, NULL);
3973 ok(hwnd != NULL, "Window creation failed\n");
3977 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
3978 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3979 ok(lRes == 0, "String should have been converted\n");
3980 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3981 ok(lRes == 1, "String shouldn't have been converted\n");
3985 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
3986 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3987 ok(lRes == 1, "String shouldn't have been converted\n");
3988 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3989 ok(lRes == 1, "String shouldn't have been converted\n");
3991 /* Synchronous messages */
3993 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3994 ok(lRes == 0, "String should have been converted\n");
3995 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3996 ok(lRes == 1, "String shouldn't have been converted\n");
3998 /* Asynchronous messages */
4001 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4002 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4003 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4005 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4006 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4007 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4009 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4010 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4011 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4013 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4014 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4015 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4017 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4018 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4019 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4021 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
4022 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4023 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4025 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4026 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4027 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4029 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
4030 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
4031 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
4034 typedef struct _thread_info
4041 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
4045 #define TIMER_ID 0x19
4047 static DWORD WINAPI timer_thread_proc(LPVOID x)
4049 thread_info *info = x;
4052 r = KillTimer(info->hWnd, 0x19);
4053 ok(r,"KillTimer failed in thread\n");
4054 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
4055 ok(r,"SetTimer failed in thread\n");
4056 ok(r==TIMER_ID,"SetTimer id different\n");
4057 r = SetEvent(info->handles[0]);
4058 ok(r,"SetEvent failed in thread\n");
4062 static void test_timers(void)
4067 info.hWnd = CreateWindow ("TestWindowClass", NULL,
4068 WS_OVERLAPPEDWINDOW ,
4069 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
4072 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
4073 ok(info.id, "SetTimer failed\n");
4074 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
4075 info.handles[0] = CreateEvent(NULL,0,0,NULL);
4076 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
4078 WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
4080 WaitForSingleObject(info.handles[1], INFINITE);
4082 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
4084 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
4089 if (!RegisterWindowClasses()) assert(0);
4091 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
4095 test_mdi_messages();
4096 test_button_messages();
4097 test_paint_messages();
4098 test_interthread_messages();
4099 test_message_conversion();
4100 test_accelerators();
4103 UnhookWindowsHookEx(hCBT_hook);