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;
773 static void add_message(const struct message *msg)
778 sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
780 if (sequence_cnt == sequence_size)
783 sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
787 sequence[sequence_cnt].message = msg->message;
788 sequence[sequence_cnt].flags = msg->flags;
789 sequence[sequence_cnt].wParam = msg->wParam;
790 sequence[sequence_cnt].lParam = msg->lParam;
795 static void flush_sequence()
797 HeapFree(GetProcessHeap(), 0, sequence);
799 sequence_cnt = sequence_size = 0;
802 static void ok_sequence(const struct message *expected, const char *context, int todo)
804 static const struct message end_of_sequence = { 0, 0, 0, 0 };
805 const struct message *actual;
807 add_message(&end_of_sequence);
811 while (expected->message && actual->message)
813 trace("expected %04x - actual %04x\n", expected->message, actual->message);
815 if (expected->message == actual->message)
817 if (expected->flags & wparam)
819 if (expected->wParam != actual->wParam && todo)
823 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
824 context, expected->message, expected->wParam, actual->wParam);
828 ok (expected->wParam == actual->wParam,
829 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
830 context, expected->message, expected->wParam, actual->wParam);
832 if (expected->flags & lparam)
833 ok (expected->lParam == actual->lParam,
834 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
835 context, expected->message, expected->lParam, actual->lParam);
836 ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
837 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
838 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
839 ok ((expected->flags & beginpaint) == (actual->flags & beginpaint),
840 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
841 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
842 ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
843 "%s: the msg 0x%04x should have been %s\n",
844 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
845 ok ((expected->flags & parent) == (actual->flags & parent),
846 "%s: the msg 0x%04x was expected in %s\n",
847 context, expected->message, (expected->flags & parent) ? "parent" : "child");
848 ok ((expected->flags & hook) == (actual->flags & hook),
849 "%s: the msg 0x%04x should have been sent by a hook\n",
850 context, expected->message);
854 else if (expected->flags & optional)
859 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
860 context, expected->message, actual->message);
867 ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
868 context, expected->message, actual->message);
874 /* skip all optional trailing messages */
875 while (expected->message && (expected->flags & optional))
881 if (expected->message || actual->message)
882 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
883 context, expected->message, actual->message);
888 if (expected->message || actual->message)
889 ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
890 context, expected->message, actual->message);
896 /******************************** MDI test **********************************/
898 /* CreateWindow for MDI frame window, initially visible */
899 static const struct message WmCreateMDIframeSeq[] = {
900 { HCBT_CREATEWND, hook },
901 { WM_GETMINMAXINFO, sent },
902 { WM_NCCREATE, sent },
903 { WM_NCCALCSIZE, sent|wparam, 0 },
905 { WM_SHOWWINDOW, sent|wparam, 1 },
906 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
907 { HCBT_ACTIVATE, hook },
908 { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
909 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
910 { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* Win9x */
911 { WM_ACTIVATEAPP, sent|wparam, 1 },
912 { WM_NCACTIVATE, sent|wparam, 1 },
913 { WM_ACTIVATE, sent|wparam, 1 },
914 { HCBT_SETFOCUS, hook },
915 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
916 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
917 /* Win9x adds SWP_NOZORDER below */
918 { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
923 /* DestroyWindow for MDI frame window, initially visible */
924 static const struct message WmDestroyMDIframeSeq[] = {
925 { HCBT_DESTROYWND, hook },
926 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
927 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
928 { WM_NCACTIVATE, sent|wparam, 0 },
929 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
930 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
931 { WM_DESTROY, sent },
932 { WM_NCDESTROY, sent },
935 /* CreateWindow for MDI client window, initially visible */
936 static const struct message WmCreateMDIclientSeq[] = {
937 { HCBT_CREATEWND, hook },
938 { WM_NCCREATE, sent },
939 { WM_NCCALCSIZE, sent|wparam, 0 },
943 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
944 { WM_SHOWWINDOW, sent|wparam, 1 },
945 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE },
946 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
949 /* DestroyWindow for MDI client window, initially visible */
950 static const struct message WmDestroyMDIclientSeq[] = {
951 { HCBT_DESTROYWND, hook },
952 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
953 { WM_SHOWWINDOW, sent|wparam, 0 },
954 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
955 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
956 { WM_DESTROY, sent },
957 { WM_NCDESTROY, sent },
960 /* CreateWindow for MDI child window, initially visible */
961 static const struct message WmCreateMDIchildVisibleSeq[] = {
962 { HCBT_CREATEWND, hook },
963 { WM_NCCREATE, sent },
964 { WM_NCCALCSIZE, sent|wparam, 0 },
968 /* Win2k sends wparam set to
969 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
970 * while Win9x doesn't bother to set child window id according to
971 * CLIENTCREATESTRUCT.idFirstChild
973 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
974 { WM_SHOWWINDOW, sent|wparam, 1 },
975 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
976 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
977 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
978 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
979 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
980 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
982 /* Win9x: message sequence terminates here. */
984 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
985 { HCBT_SETFOCUS, hook }, /* in MDI client */
986 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
987 { WM_SETFOCUS, sent }, /* in MDI client */
988 { HCBT_SETFOCUS, hook },
989 { WM_KILLFOCUS, sent }, /* in MDI client */
990 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
991 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
992 { WM_SETFOCUS, sent|defwinproc },
993 { WM_MDIACTIVATE, sent|defwinproc },
996 /* DestroyWindow for MDI child window, initially visible */
997 static const struct message WmDestroyMDIchildVisibleSeq[] = {
998 { HCBT_DESTROYWND, hook },
999 /* Win2k sends wparam set to
1000 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1001 * while Win9x doesn't bother to set child window id according to
1002 * CLIENTCREATESTRUCT.idFirstChild
1004 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1005 { WM_SHOWWINDOW, sent|wparam, 0 },
1006 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1007 { WM_ERASEBKGND, sent|parent|optional },
1008 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1010 /* { WM_DESTROY, sent }
1011 * Win9x: message sequence terminates here.
1014 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1015 { WM_KILLFOCUS, sent },
1016 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1017 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1018 { WM_SETFOCUS, sent }, /* in MDI client */
1020 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1021 { WM_KILLFOCUS, sent }, /* in MDI client */
1022 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1023 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1024 { WM_SETFOCUS, sent }, /* in MDI client */
1026 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1027 { WM_KILLFOCUS, sent },
1028 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1029 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1030 { WM_SETFOCUS, sent }, /* in MDI client */
1032 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1033 { WM_KILLFOCUS, sent }, /* in MDI client */
1034 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1035 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1036 { WM_SETFOCUS, sent }, /* in MDI client */
1038 { WM_DESTROY, sent },
1040 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
1041 { WM_KILLFOCUS, sent },
1042 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1043 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1044 { WM_SETFOCUS, sent }, /* in MDI client */
1046 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
1047 { WM_KILLFOCUS, sent }, /* in MDI client */
1048 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1049 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1050 { WM_SETFOCUS, sent }, /* in MDI client */
1052 { WM_NCDESTROY, sent },
1055 /* CreateWindow for MDI child window, initially invisible */
1056 static const struct message WmCreateMDIchildInvisibleSeq[] = {
1057 { HCBT_CREATEWND, hook },
1058 { WM_NCCREATE, sent },
1059 { WM_NCCALCSIZE, sent|wparam, 0 },
1060 { WM_CREATE, sent },
1063 /* Win2k sends wparam set to
1064 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1065 * while Win9x doesn't bother to set child window id according to
1066 * CLIENTCREATESTRUCT.idFirstChild
1068 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1071 /* DestroyWindow for MDI child window, initially invisible */
1072 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
1073 { HCBT_DESTROYWND, hook },
1074 /* Win2k sends wparam set to
1075 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1076 * while Win9x doesn't bother to set child window id according to
1077 * CLIENTCREATESTRUCT.idFirstChild
1079 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1080 { WM_DESTROY, sent },
1081 { WM_NCDESTROY, sent },
1084 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1085 static const struct message WmCreateMDIchildVisibleMaxSeq1[] = {
1086 { HCBT_CREATEWND, hook },
1087 { WM_NCCREATE, sent },
1088 { WM_NCCALCSIZE, sent|wparam, 0 },
1089 { WM_CREATE, sent },
1092 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1093 { WM_GETMINMAXINFO, sent },
1094 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1095 { WM_NCCALCSIZE, sent|wparam, 1 },
1096 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1097 { WM_SIZE, sent|defwinproc },
1099 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1100 { WM_NCCALCSIZE, sent|wparam, 1 },
1101 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1102 /* Win2k sends wparam set to
1103 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1104 * while Win9x doesn't bother to set child window id according to
1105 * CLIENTCREATESTRUCT.idFirstChild
1107 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1108 { WM_SHOWWINDOW, sent|wparam, 1 },
1109 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1110 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1111 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1112 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1113 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1114 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1116 /* Win9x: message sequence terminates here. */
1118 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1119 { HCBT_SETFOCUS, hook }, /* in MDI client */
1120 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1121 { WM_SETFOCUS, sent }, /* in MDI client */
1122 { HCBT_SETFOCUS, hook },
1123 { WM_KILLFOCUS, sent }, /* in MDI client */
1124 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1125 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1126 { WM_SETFOCUS, sent|defwinproc },
1127 { WM_MDIACTIVATE, sent|defwinproc },
1129 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1130 { WM_NCCALCSIZE, sent|wparam, 1 },
1131 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1134 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1135 static const struct message WmCreateMDIchildVisibleMaxSeq2[] = {
1136 /* restore the 1st MDI child */
1137 { WM_SETREDRAW, sent|wparam, 0 },
1138 { HCBT_MINMAX, hook },
1139 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1140 { WM_NCCALCSIZE, sent|wparam, 1 },
1141 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1142 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1143 { WM_SIZE, sent|defwinproc },
1145 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1146 { WM_NCCALCSIZE, sent|wparam, 1 },
1147 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1148 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
1149 /* create the 2nd MDI child */
1150 { HCBT_CREATEWND, hook },
1151 { WM_NCCREATE, sent },
1152 { WM_NCCALCSIZE, sent|wparam, 0 },
1153 { WM_CREATE, sent },
1156 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1157 { WM_GETMINMAXINFO, sent },
1158 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1159 { WM_NCCALCSIZE, sent|wparam, 1 },
1160 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1161 { WM_SIZE, sent|defwinproc },
1163 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1164 { WM_NCCALCSIZE, sent|wparam, 1 },
1165 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1166 /* Win2k sends wparam set to
1167 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1168 * while Win9x doesn't bother to set child window id according to
1169 * CLIENTCREATESTRUCT.idFirstChild
1171 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1172 { WM_SHOWWINDOW, sent|wparam, 1 },
1173 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1174 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1175 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1176 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1177 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1179 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1180 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1182 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1184 /* Win9x: message sequence terminates here. */
1186 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1187 { HCBT_SETFOCUS, hook },
1188 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
1189 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
1190 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1191 { WM_SETFOCUS, sent }, /* in MDI client */
1192 { HCBT_SETFOCUS, hook },
1193 { WM_KILLFOCUS, sent }, /* in MDI client */
1194 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1195 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1196 { WM_SETFOCUS, sent|defwinproc },
1198 { WM_MDIACTIVATE, sent|defwinproc },
1200 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1201 { WM_NCCALCSIZE, sent|wparam, 1 },
1202 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1205 /* WM_MDICREATE MDI child window, initially visible and maximized */
1206 static const struct message WmCreateMDIchildVisibleMaxSeq3[] = {
1207 { WM_MDICREATE, sent },
1208 { HCBT_CREATEWND, hook },
1209 { WM_NCCREATE, sent },
1210 { WM_NCCALCSIZE, sent|wparam, 0 },
1211 { WM_CREATE, sent },
1214 { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
1215 { WM_GETMINMAXINFO, sent },
1216 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|0x8000 },
1217 { WM_NCCALCSIZE, sent|wparam, 1 },
1218 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1219 { WM_SIZE, sent|defwinproc },
1221 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1222 { WM_NCCALCSIZE, sent|wparam, 1 },
1223 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1224 /* Win2k sends wparam set to
1225 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1226 * while Win9x doesn't bother to set child window id according to
1227 * CLIENTCREATESTRUCT.idFirstChild
1229 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
1230 { WM_SHOWWINDOW, sent|wparam, 1 },
1231 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1232 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1233 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
1234 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
1235 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1236 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1238 /* Win9x: message sequence terminates here. */
1240 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1241 { HCBT_SETFOCUS, hook }, /* in MDI client */
1242 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1243 { WM_SETFOCUS, sent }, /* in MDI client */
1244 { HCBT_SETFOCUS, hook },
1245 { WM_KILLFOCUS, sent }, /* in MDI client */
1246 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1247 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1248 { WM_SETFOCUS, sent|defwinproc },
1250 { WM_MDIACTIVATE, sent|defwinproc },
1253 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1254 { WM_NCCALCSIZE, sent|wparam, 1 },
1255 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1258 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1259 { WM_NCCALCSIZE, sent|wparam, 1 },
1260 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1261 { WM_MOVE, sent|defwinproc },
1262 { WM_SIZE, sent|defwinproc },
1265 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1266 { WM_NCCALCSIZE, sent|wparam, 1 },
1267 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1271 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1272 { WM_NCCALCSIZE, sent|wparam, 1 },
1273 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1274 { WM_SIZE, sent|defwinproc },
1278 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1279 static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = {
1280 { WM_SYSCOMMAND, sent|wparam, SC_CLOSE },
1281 { HCBT_SYSCOMMAND, hook },
1282 { WM_CLOSE, sent|defwinproc },
1283 { WM_MDIDESTROY, sent }, /* in MDI client */
1285 /* bring the 1st MDI child to top */
1286 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
1287 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
1288 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
1289 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
1290 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
1292 /* maximize the 1st MDI child */
1293 { HCBT_MINMAX, hook },
1294 { WM_GETMINMAXINFO, sent|defwinproc },
1295 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|0x8000 },
1296 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1297 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 },
1298 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1299 { WM_SIZE, sent|defwinproc },
1301 /* restore the 2nd MDI child */
1302 { WM_SETREDRAW, sent|defwinproc|wparam, 0 },
1303 { HCBT_MINMAX, hook },
1304 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOZORDER|0x8000 },
1305 { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
1306 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1307 { WM_SIZE, sent|defwinproc },
1308 { WM_SETREDRAW, sent|defwinproc|wparam, 1 },
1310 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1311 { WM_NCCALCSIZE, sent|wparam, 1 },
1312 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1314 /* bring the 1st MDI child to top */
1315 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1316 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1317 { HCBT_SETFOCUS, hook },
1318 { WM_KILLFOCUS, sent|defwinproc },
1319 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },
1320 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1321 { WM_SETFOCUS, sent }, /* in MDI client */
1322 { HCBT_SETFOCUS, hook },
1323 { WM_KILLFOCUS, sent }, /* in MDI client */
1324 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1325 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1326 { WM_SETFOCUS, sent|defwinproc },
1327 { WM_MDIACTIVATE, sent|defwinproc },
1328 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1330 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1331 { WM_SHOWWINDOW, sent|wparam, 1 },
1332 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1333 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1334 { WM_MDIREFRESHMENU, sent },
1336 { HCBT_DESTROYWND, hook },
1337 /* Win2k sends wparam set to
1338 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1339 * while Win9x doesn't bother to set child window id according to
1340 * CLIENTCREATESTRUCT.idFirstChild
1342 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1343 { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 },
1344 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1345 { WM_ERASEBKGND, sent|parent|optional },
1346 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1348 { WM_DESTROY, sent|defwinproc },
1349 { WM_NCDESTROY, sent|defwinproc },
1352 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1353 static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = {
1354 { WM_MDIDESTROY, sent }, /* in MDI client */
1355 { WM_SHOWWINDOW, sent|wparam, 0 },
1356 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1357 { WM_ERASEBKGND, sent|parent|optional },
1358 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1360 { HCBT_SETFOCUS, hook },
1361 { WM_KILLFOCUS, sent },
1362 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1363 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1364 { WM_SETFOCUS, sent }, /* in MDI client */
1365 { HCBT_SETFOCUS, hook },
1366 { WM_KILLFOCUS, sent }, /* in MDI client */
1367 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1368 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
1369 { WM_SETFOCUS, sent },
1372 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1373 { WM_NCCALCSIZE, sent|wparam, 1 },
1374 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1377 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1378 { WM_NCCALCSIZE, sent|wparam, 1 },
1379 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1380 { WM_MOVE, sent|defwinproc },
1381 { WM_SIZE, sent|defwinproc },
1384 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1385 { WM_NCCALCSIZE, sent|wparam, 1 },
1386 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1390 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1391 { WM_NCCALCSIZE, sent|wparam, 1 },
1392 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1393 { WM_SIZE, sent|defwinproc },
1396 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1397 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1398 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1401 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1402 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1403 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1404 { WM_MOVE, sent|defwinproc },
1405 { WM_SIZE, sent|defwinproc },
1408 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1409 { WM_NCCALCSIZE, sent|wparam, 1 },
1410 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1414 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOZORDER },
1415 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1416 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOCLIENTMOVE },
1417 { WM_SIZE, sent|defwinproc },
1420 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1421 { WM_NCCALCSIZE, sent|wparam, 1 },
1422 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1424 { WM_NCACTIVATE, sent|wparam, 0 },
1425 { WM_MDIACTIVATE, sent },
1427 { HCBT_MINMAX, hook },
1428 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|0x8000 },
1429 { WM_NCCALCSIZE, sent|wparam, 1 },
1430 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1431 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE|0x8000 },
1432 { WM_SIZE, sent|defwinproc },
1435 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1436 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
1437 { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1440 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1441 { WM_NCCALCSIZE, sent|wparam, 1 },
1442 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1443 { WM_MOVE, sent|defwinproc },
1444 { WM_SIZE, sent|defwinproc },
1447 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOZORDER },
1448 { WM_NCCALCSIZE, sent|wparam, 1 },
1449 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
1452 { HCBT_SETFOCUS, hook },
1453 { WM_KILLFOCUS, sent },
1454 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
1455 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1456 { WM_SETFOCUS, sent }, /* in MDI client */
1458 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
1460 { HCBT_DESTROYWND, hook },
1461 /* Win2k sends wparam set to
1462 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1463 * while Win9x doesn't bother to set child window id according to
1464 * CLIENTCREATESTRUCT.idFirstChild
1466 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
1468 { WM_SHOWWINDOW, sent|wparam, 0 },
1469 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1470 { WM_ERASEBKGND, sent|parent|optional },
1471 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1473 { WM_DESTROY, sent },
1474 { WM_NCDESTROY, sent },
1477 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1478 static const struct message WmMaximizeMDIchildInvisibleSeq[] = {
1479 { HCBT_MINMAX, hook },
1480 { WM_GETMINMAXINFO, sent },
1481 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1482 { WM_NCCALCSIZE, sent|wparam, 1 },
1483 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1485 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
1486 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
1487 { HCBT_SETFOCUS, hook },
1488 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
1489 { WM_SETFOCUS, sent }, /* in MDI client */
1490 { HCBT_SETFOCUS, hook },
1491 { WM_KILLFOCUS, sent }, /* in MDI client */
1492 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
1493 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
1494 { WM_SETFOCUS, sent|defwinproc },
1495 { WM_MDIACTIVATE, sent|defwinproc },
1496 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1497 { WM_SIZE, sent|defwinproc },
1499 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1500 { WM_NCCALCSIZE, sent|wparam, 1 },
1501 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1504 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1505 static const struct message WmMaximizeMDIchildVisibleSeq[] = {
1506 { HCBT_MINMAX, hook },
1507 { WM_GETMINMAXINFO, sent },
1508 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1509 { WM_NCCALCSIZE, sent|wparam, 1 },
1510 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1511 { WM_WINDOWPOSCHANGED, sent|wparam, 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_RESTORE) for a visible MDI child window */
1520 static const struct message WmRestoreMDIchildVisibleSeq[] = {
1521 { HCBT_MINMAX, hook },
1522 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
1523 { WM_NCCALCSIZE, sent|wparam, 1 },
1524 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1525 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1526 { WM_SIZE, sent|defwinproc },
1528 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1529 { WM_NCCALCSIZE, sent|wparam, 1 },
1530 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1533 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1534 static const struct message WmRestoreMDIchildInisibleSeq[] = {
1535 { HCBT_MINMAX, hook },
1536 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
1537 { WM_NCCALCSIZE, sent|wparam, 1 },
1538 { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
1539 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 },
1540 { WM_SIZE, sent|defwinproc },
1542 { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
1543 { WM_NCCALCSIZE, sent|wparam, 1 },
1544 { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
1548 static HWND mdi_client;
1549 static WNDPROC old_mdi_client_proc;
1551 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1555 /* do not log painting messages */
1556 if (message != WM_PAINT &&
1557 message != WM_ERASEBKGND &&
1558 message != WM_NCPAINT &&
1559 message != WM_GETTEXT &&
1560 message != WM_MDIGETACTIVE)
1562 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1566 case WM_WINDOWPOSCHANGING:
1567 case WM_WINDOWPOSCHANGED:
1569 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1571 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1572 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1573 winpos->hwnd, winpos->hwndInsertAfter,
1574 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1576 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1577 * in the high word for internal purposes
1579 wParam = winpos->flags & 0xffff;
1584 msg.message = message;
1585 msg.flags = sent|wparam|lparam;
1586 msg.wParam = wParam;
1587 msg.lParam = lParam;
1591 return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
1594 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1596 static long defwndproc_counter = 0;
1600 /* do not log painting messages */
1601 if (message != WM_PAINT &&
1602 message != WM_ERASEBKGND &&
1603 message != WM_NCPAINT &&
1604 message != WM_GETTEXT)
1606 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1610 case WM_WINDOWPOSCHANGING:
1611 case WM_WINDOWPOSCHANGED:
1613 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1615 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1616 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1617 winpos->hwnd, winpos->hwndInsertAfter,
1618 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1620 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1621 * in the high word for internal purposes
1623 wParam = winpos->flags & 0xffff;
1627 case WM_MDIACTIVATE:
1629 HWND active, client = GetParent(hwnd);
1631 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1633 if (hwnd == (HWND)lParam) /* if we are being activated */
1634 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
1636 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
1641 msg.message = message;
1642 msg.flags = sent|wparam|lparam;
1643 if (defwndproc_counter) msg.flags |= defwinproc;
1644 msg.wParam = wParam;
1645 msg.lParam = lParam;
1649 defwndproc_counter++;
1650 ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1651 defwndproc_counter--;
1656 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1658 static long defwndproc_counter = 0;
1662 /* do not log painting messages */
1663 if (message != WM_PAINT &&
1664 message != WM_ERASEBKGND &&
1665 message != WM_NCPAINT &&
1666 message != WM_GETTEXT)
1668 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1672 case WM_WINDOWPOSCHANGING:
1673 case WM_WINDOWPOSCHANGED:
1675 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1677 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1678 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1679 winpos->hwnd, winpos->hwndInsertAfter,
1680 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1682 /* Log only documented flags, win2k uses 0x1000 and 0x2000
1683 * in the high word for internal purposes
1685 wParam = winpos->flags & 0xffff;
1690 msg.message = message;
1691 msg.flags = sent|wparam|lparam;
1692 if (defwndproc_counter) msg.flags |= defwinproc;
1693 msg.wParam = wParam;
1694 msg.lParam = lParam;
1698 defwndproc_counter++;
1699 ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
1700 defwndproc_counter--;
1705 static BOOL mdi_RegisterWindowClasses(void)
1710 cls.lpfnWndProc = mdi_frame_wnd_proc;
1713 cls.hInstance = GetModuleHandleA(0);
1715 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1716 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1717 cls.lpszMenuName = NULL;
1718 cls.lpszClassName = "MDI_frame_class";
1719 if (!RegisterClassA(&cls)) return FALSE;
1721 cls.lpfnWndProc = mdi_child_wnd_proc;
1722 cls.lpszClassName = "MDI_child_class";
1723 if (!RegisterClassA(&cls)) return FALSE;
1725 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
1726 old_mdi_client_proc = cls.lpfnWndProc;
1727 cls.hInstance = GetModuleHandleA(0);
1728 cls.lpfnWndProc = mdi_client_hook_proc;
1729 cls.lpszClassName = "MDI_client_class";
1730 if (!RegisterClassA(&cls)) assert(0);
1735 static void test_mdi_messages(void)
1737 MDICREATESTRUCTA mdi_cs;
1738 CLIENTCREATESTRUCT client_cs;
1739 HWND mdi_frame, mdi_child, mdi_child2, active_child;
1741 HMENU hMenu = CreateMenu();
1743 assert(mdi_RegisterWindowClasses());
1747 trace("creating MDI frame window\n");
1748 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1749 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1750 WS_MAXIMIZEBOX | WS_VISIBLE,
1751 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1752 GetDesktopWindow(), hMenu,
1753 GetModuleHandleA(0), NULL);
1755 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", TRUE);
1757 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1758 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
1760 trace("creating MDI client window\n");
1761 client_cs.hWindowMenu = 0;
1762 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
1763 mdi_client = CreateWindowExA(0, "MDI_client_class",
1765 WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
1767 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
1769 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
1771 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1772 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
1774 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1775 ok(!active_child, "wrong active MDI child %p\n", active_child);
1776 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1781 trace("creating visible MDI child window\n");
1782 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1783 WS_CHILD | WS_VISIBLE,
1784 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1785 mdi_client, 0, GetModuleHandleA(0), NULL);
1787 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", TRUE);
1789 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1790 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1792 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1793 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
1795 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1796 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
1797 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1800 DestroyWindow(mdi_child);
1801 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
1803 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1804 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1806 /* Win2k: MDI client still returns a just destroyed child as active
1807 * Win9x: MDI client returns 0
1809 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1810 ok(active_child == mdi_child || /* win2k */
1811 !active_child, /* win9x */
1812 "wrong active MDI child %p\n", active_child);
1813 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1817 trace("creating invisible MDI child window\n");
1818 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1820 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1821 mdi_client, 0, GetModuleHandleA(0), NULL);
1823 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
1825 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
1826 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
1828 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1829 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1831 /* Win2k: MDI client still returns a just destroyed child as active
1832 * Win9x: MDI client returns mdi_child2
1834 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1835 ok(active_child == mdi_child || /* win2k */
1836 active_child == mdi_child2, /* win9x */
1837 "wrong active MDI child %p\n", active_child);
1838 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1841 ShowWindow(mdi_child2, SW_MAXIMIZE);
1842 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE);
1844 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1845 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
1847 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1848 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1849 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1852 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1853 ok(GetFocus() == mdi_child2 || /* win2k */
1854 GetFocus() == 0, /* win9x */
1855 "wrong focus window %p\n", GetFocus());
1860 ShowWindow(mdi_child2, SW_HIDE);
1861 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1863 ShowWindow(mdi_child2, SW_RESTORE);
1864 ok_sequence(WmRestoreMDIchildInisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE);
1867 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1868 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
1870 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1871 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1872 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
1878 ShowWindow(mdi_child2, SW_HIDE);
1879 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1881 ShowWindow(mdi_child2, SW_SHOW);
1882 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", TRUE);
1884 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1885 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1887 ShowWindow(mdi_child2, SW_MAXIMIZE);
1888 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE);
1890 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1891 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1893 ShowWindow(mdi_child2, SW_RESTORE);
1894 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):MDI child", TRUE);
1896 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1897 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1902 ShowWindow(mdi_child2, SW_HIDE);
1903 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
1905 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1906 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1908 DestroyWindow(mdi_child2);
1909 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", TRUE);
1911 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1912 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1914 /* test for maximized MDI children */
1915 trace("creating maximized visible MDI child window 1\n");
1916 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1917 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
1918 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1919 mdi_client, 0, GetModuleHandleA(0), NULL);
1921 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
1922 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
1924 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1925 ok(GetFocus() == mdi_child || /* win2k */
1926 GetFocus() == 0, /* win9x */
1927 "wrong focus window %p\n", GetFocus());
1929 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1930 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
1931 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1934 trace("creating maximized visible MDI child window 2\n");
1935 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1936 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
1937 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1938 mdi_client, 0, GetModuleHandleA(0), NULL);
1940 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
1941 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
1942 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
1944 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1945 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
1947 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1948 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1949 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1952 trace("destroying maximized visible MDI child window 2\n");
1953 DestroyWindow(mdi_child2);
1954 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
1956 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
1958 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1959 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
1961 /* Win2k: MDI client still returns a just destroyed child as active
1962 * Win9x: MDI client returns 0
1964 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1965 ok(active_child == mdi_child2 || /* win2k */
1966 !active_child, /* win9x */
1967 "wrong active MDI child %p\n", active_child);
1970 ShowWindow(mdi_child, SW_MAXIMIZE);
1971 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
1974 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1975 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
1977 trace("re-creating maximized visible MDI child window 2\n");
1978 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1979 WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE,
1980 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1981 mdi_client, 0, GetModuleHandleA(0), NULL);
1983 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
1984 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
1985 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
1987 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
1988 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
1990 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
1991 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
1992 ok(zoomed, "wrong zoomed state %d\n", zoomed);
1995 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
1996 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
1997 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
1999 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
2000 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2001 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2003 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2004 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2005 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2008 DestroyWindow(mdi_child);
2009 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
2011 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2012 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2014 /* Win2k: MDI client still returns a just destroyed child as active
2015 * Win9x: MDI client returns 0
2017 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2018 ok(active_child == mdi_child || /* win2k */
2019 !active_child, /* win9x */
2020 "wrong active MDI child %p\n", active_child);
2022 /* end of test for maximized MDI children */
2024 mdi_cs.szClass = "MDI_child_Class";
2025 mdi_cs.szTitle = "MDI child";
2026 mdi_cs.hOwner = GetModuleHandleA(0);
2029 mdi_cs.cx = CW_USEDEFAULT;
2030 mdi_cs.cy = CW_USEDEFAULT;
2031 mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE;
2033 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
2034 ok(mdi_child != 0, "MDI child creation failed\n");
2035 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
2037 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
2039 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2040 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2042 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
2043 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
2044 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
2046 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2047 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
2048 ok(zoomed, "wrong zoomed state %d\n", zoomed);
2051 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
2052 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
2054 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
2055 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
2056 ok(!active_child, "wrong active MDI child %p\n", active_child);
2061 DestroyWindow(mdi_client);
2062 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
2064 DestroyWindow(mdi_frame);
2065 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
2067 /************************* End of MDI test **********************************/
2069 static void test_WM_SETREDRAW(HWND hwnd)
2071 DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
2075 SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
2076 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
2078 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
2079 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
2082 SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
2083 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
2085 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2086 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
2088 /* restore original WS_VISIBLE state */
2089 SetWindowLongA(hwnd, GWL_STYLE, style);
2094 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2098 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2100 msg.message = message;
2101 msg.flags = sent|wparam|lparam;
2102 msg.wParam = wParam;
2103 msg.lParam = lParam;
2106 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
2107 if (message == WM_TIMER) EndDialog( hwnd, 0 );
2111 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2113 DWORD style, exstyle;
2116 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2117 style = GetWindowLongA(hwnd, GWL_STYLE);
2118 /* do not be confused by WS_DLGFRAME set */
2119 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2121 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2122 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2124 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2125 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2126 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
2128 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", TRUE);
2130 style = GetWindowLongA(hwnd, GWL_STYLE);
2131 if (set) ok(style & set, "style %08lx should be set\n", set);
2132 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2134 /* a subsequent call should do nothing */
2135 ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
2136 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2140 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2141 ok(GetScrollRange(hwnd, ctl, &xmin, &xmax), "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
2142 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2143 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
2144 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
2147 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
2149 DWORD style, exstyle;
2152 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
2153 style = GetWindowLongA(hwnd, GWL_STYLE);
2154 /* do not be confused by WS_DLGFRAME set */
2155 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
2157 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
2158 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
2160 si.cbSize = sizeof(si);
2161 si.fMask = SIF_RANGE;
2164 SetScrollInfo(hwnd, ctl, &si, TRUE);
2165 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
2166 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
2168 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", TRUE);
2170 style = GetWindowLongA(hwnd, GWL_STYLE);
2171 if (set) ok(style & set, "style %08lx should be set\n", set);
2172 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
2174 /* a subsequent call should do nothing */
2175 SetScrollInfo(hwnd, ctl, &si, TRUE);
2176 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2178 si.fMask = SIF_PAGE;
2180 SetScrollInfo(hwnd, ctl, &si, FALSE);
2181 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2185 SetScrollInfo(hwnd, ctl, &si, FALSE);
2186 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
2188 si.fMask = SIF_RANGE;
2189 si.nMin = 0xdeadbeef;
2190 si.nMax = 0xdeadbeef;
2191 ok(GetScrollInfo(hwnd, ctl, &si), "GetScrollInfo error %ld\n", GetLastError());
2192 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)", FALSE);
2193 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
2194 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
2197 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2198 static void test_scroll_messages(HWND hwnd)
2205 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
2206 if (sequence->message != WmGetScrollRangeSeq[0].message)
2207 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2208 /* values of min and max are undefined */
2211 ok(SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE), "SetScrollRange error %ld\n", GetLastError());
2212 if (sequence->message != WmSetScrollRangeSeq[0].message)
2213 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2218 ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
2219 if (sequence->message != WmGetScrollRangeSeq[0].message)
2220 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
2221 /* values of min and max are undefined */
2224 si.cbSize = sizeof(si);
2225 si.fMask = SIF_RANGE;
2228 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2229 if (sequence->message != WmSetScrollRangeSeq[0].message)
2230 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2233 si.fMask = SIF_PAGE;
2235 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2236 if (sequence->message != WmSetScrollRangeSeq[0].message)
2237 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2242 SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
2243 if (sequence->message != WmSetScrollRangeSeq[0].message)
2244 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2247 si.fMask = SIF_RANGE;
2248 si.nMin = 0xdeadbeef;
2249 si.nMax = 0xdeadbeef;
2250 ok(GetScrollInfo(hwnd, SB_CTL, &si), "GetScrollInfo error %ld\n", GetLastError());
2251 if (sequence->message != WmGetScrollInfoSeq[0].message)
2252 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
2253 /* values of min and max are undefined */
2256 /* set WS_HSCROLL */
2257 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2258 /* clear WS_HSCROLL */
2259 test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2261 /* set WS_HSCROLL */
2262 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
2263 /* clear WS_HSCROLL */
2264 test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
2266 /* set WS_VSCROLL */
2267 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2268 /* clear WS_VSCROLL */
2269 test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2271 /* set WS_VSCROLL */
2272 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
2273 /* clear WS_VSCROLL */
2274 test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
2277 /* test if we receive the right sequence of messages */
2278 static void test_messages(void)
2280 HWND hwnd, hparent, hchild;
2281 HWND hchild2, hbutton;
2284 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2285 100, 100, 200, 200, 0, 0, 0, NULL);
2286 ok (hwnd != 0, "Failed to create overlapped window\n");
2287 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2289 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2290 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
2291 ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
2293 /* test WM_SETREDRAW on a not visible top level window */
2294 test_WM_SETREDRAW(hwnd);
2296 SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2297 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
2298 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
2300 ok(GetActiveWindow() == hwnd, "window should be active\n");
2301 ok(GetFocus() == hwnd, "window should have input focus\n");
2302 ShowWindow(hwnd, SW_HIDE);
2303 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
2305 ShowWindow(hwnd, SW_SHOW);
2306 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
2308 ok(GetActiveWindow() == hwnd, "window should be active\n");
2309 ok(GetFocus() == hwnd, "window should have input focus\n");
2310 SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2311 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", TRUE);
2312 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
2314 /* test WM_SETREDRAW on a visible top level window */
2315 ShowWindow(hwnd, SW_SHOW);
2316 test_WM_SETREDRAW(hwnd);
2318 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
2319 test_scroll_messages(hwnd);
2321 DestroyWindow(hwnd);
2322 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
2324 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2325 100, 100, 200, 200, 0, 0, 0, NULL);
2326 ok (hparent != 0, "Failed to create parent window\n");
2329 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
2330 0, 0, 10, 10, hparent, 0, 0, NULL);
2331 ok (hchild != 0, "Failed to create child window\n");
2332 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", TRUE);
2333 DestroyWindow(hchild);
2336 /* visible child window with a caption */
2337 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
2338 WS_CHILD | WS_VISIBLE | WS_CAPTION,
2339 0, 0, 10, 10, hparent, 0, 0, NULL);
2340 ok (hchild != 0, "Failed to create child window\n");
2341 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
2343 trace("testing scroll APIs on a visible child window %p\n", hchild);
2344 test_scroll_messages(hchild);
2346 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2347 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
2349 DestroyWindow(hchild);
2352 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2353 0, 0, 10, 10, hparent, 0, 0, NULL);
2354 ok (hchild != 0, "Failed to create child window\n");
2355 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2357 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
2358 100, 100, 50, 50, hparent, 0, 0, NULL);
2359 ok (hchild2 != 0, "Failed to create child2 window\n");
2362 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
2363 0, 100, 50, 50, hchild, 0, 0, NULL);
2364 ok (hbutton != 0, "Failed to create button window\n");
2366 /* test WM_SETREDRAW on a not visible child window */
2367 test_WM_SETREDRAW(hchild);
2369 ShowWindow(hchild, SW_SHOW);
2370 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2372 ShowWindow(hchild, SW_HIDE);
2373 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
2375 ShowWindow(hchild, SW_SHOW);
2376 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
2378 /* test WM_SETREDRAW on a visible child window */
2379 test_WM_SETREDRAW(hchild);
2381 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
2382 ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE);
2384 ShowWindow(hchild, SW_HIDE);
2386 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2387 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
2389 ShowWindow(hchild, SW_HIDE);
2391 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2392 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
2394 /* DestroyWindow sequence below expects that a child has focus */
2398 DestroyWindow(hchild);
2399 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
2400 DestroyWindow(hchild2);
2401 DestroyWindow(hbutton);
2404 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
2405 0, 0, 100, 100, hparent, 0, 0, NULL);
2406 ok (hchild != 0, "Failed to create child popup window\n");
2407 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
2408 DestroyWindow(hchild);
2410 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
2412 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
2413 0, 0, 100, 100, hparent, 0, 0, NULL);
2414 ok (hchild != 0, "Failed to create popup window\n");
2415 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2416 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2417 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2419 ShowWindow(hchild, SW_SHOW);
2420 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2422 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2423 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2425 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
2426 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
2427 DestroyWindow(hchild);
2429 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
2430 * changes nothing in message sequences.
2433 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
2434 0, 0, 100, 100, hparent, 0, 0, NULL);
2435 ok (hchild != 0, "Failed to create popup window\n");
2436 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
2437 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2438 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
2440 ShowWindow(hchild, SW_SHOW);
2441 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
2443 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2444 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
2445 DestroyWindow(hchild);
2448 hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
2449 0, 0, 100, 100, hparent, 0, 0, NULL);
2450 ok(hwnd != 0, "Failed to create custom dialog window\n");
2451 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
2453 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
2454 test_scroll_messages(hwnd);
2457 after_end_dialog = 1;
2458 EndDialog( hwnd, 0 );
2459 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
2461 DestroyWindow(hwnd);
2462 after_end_dialog = 0;
2465 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
2466 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
2468 /* test showing child with hidden parent */
2469 ShowWindow( hparent, SW_HIDE );
2472 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
2473 0, 0, 10, 10, hparent, 0, 0, NULL);
2474 ok (hchild != 0, "Failed to create child window\n");
2475 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
2477 ShowWindow( hchild, SW_SHOW );
2478 ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", TRUE);
2479 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2480 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2482 ShowWindow( hchild, SW_HIDE );
2483 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", TRUE);
2484 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
2485 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2487 SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2488 ok_sequence(WmShowChildInvisibleParentSeq_2, "SetWindowPos:show child with invisible parent", TRUE);
2489 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
2490 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2492 SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
2493 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", TRUE);
2494 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
2495 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
2497 DestroyWindow(hchild);
2498 DestroyWindow(hparent);
2501 /* Message sequence for SetMenu */
2502 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
2503 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
2505 hmenu = CreateMenu();
2506 ok (hmenu != 0, "Failed to create menu\n");
2507 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
2508 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2509 100, 100, 200, 200, 0, hmenu, 0, NULL);
2510 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
2511 ok (SetMenu(hwnd, 0), "SetMenu\n");
2512 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
2513 ok (SetMenu(hwnd, 0), "SetMenu\n");
2514 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
2515 ShowWindow(hwnd, SW_SHOW);
2517 ok (SetMenu(hwnd, 0), "SetMenu\n");
2518 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
2519 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
2520 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
2522 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
2523 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
2525 DestroyWindow(hwnd);
2528 /* Message sequence for EnableWindow */
2529 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2530 100, 100, 200, 200, 0, 0, 0, NULL);
2531 ok (hparent != 0, "Failed to create parent window\n");
2532 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
2533 0, 0, 10, 10, hparent, 0, 0, NULL);
2534 ok (hchild != 0, "Failed to create child window\n");
2539 EnableWindow(hparent, FALSE);
2540 ok_sequence(WmEnableWindowSeq, "EnableWindow", FALSE);
2542 DestroyWindow(hchild);
2543 DestroyWindow(hparent);
2547 /****************** button message test *************************/
2548 static const struct message WmSetFocusButtonSeq[] =
2550 { HCBT_SETFOCUS, hook },
2551 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2552 { WM_SETFOCUS, sent|wparam, 0 },
2553 { WM_CTLCOLORBTN, sent|defwinproc },
2556 static const struct message WmKillFocusButtonSeq[] =
2558 { HCBT_SETFOCUS, hook },
2559 { WM_KILLFOCUS, sent|wparam, 0 },
2560 { WM_CTLCOLORBTN, sent|defwinproc },
2561 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2564 static const struct message WmSetFocusStaticSeq[] =
2566 { HCBT_SETFOCUS, hook },
2567 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
2568 { WM_SETFOCUS, sent|wparam, 0 },
2569 { WM_CTLCOLORSTATIC, sent|defwinproc },
2572 static const struct message WmKillFocusStaticSeq[] =
2574 { HCBT_SETFOCUS, hook },
2575 { WM_KILLFOCUS, sent|wparam, 0 },
2576 { WM_CTLCOLORSTATIC, sent|defwinproc },
2577 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
2580 static const struct message WmLButtonDownSeq[] =
2582 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
2583 { HCBT_SETFOCUS, hook },
2584 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
2585 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
2586 { WM_CTLCOLORBTN, sent|defwinproc },
2587 { BM_SETSTATE, sent|wparam|defwinproc, TRUE },
2588 { WM_CTLCOLORBTN, sent|defwinproc },
2591 static const struct message WmLButtonUpSeq[] =
2593 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
2594 { BM_SETSTATE, sent|wparam|defwinproc, FALSE },
2595 { WM_CTLCOLORBTN, sent|defwinproc },
2596 { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 },
2600 static WNDPROC old_button_proc;
2602 static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2604 static long defwndproc_counter = 0;
2608 trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
2610 msg.message = message;
2611 msg.flags = sent|wparam|lparam;
2612 if (defwndproc_counter) msg.flags |= defwinproc;
2613 msg.wParam = wParam;
2614 msg.lParam = lParam;
2617 if (message == BM_SETSTATE)
2618 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
2620 defwndproc_counter++;
2621 ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam);
2622 defwndproc_counter--;
2627 static void subclass_button(void)
2631 if (!GetClassInfoA(0, "button", &cls)) assert(0);
2633 old_button_proc = cls.lpfnWndProc;
2635 cls.hInstance = GetModuleHandle(0);
2636 cls.lpfnWndProc = button_hook_proc;
2637 cls.lpszClassName = "my_button_class";
2638 if (!RegisterClassA(&cls)) assert(0);
2641 static void test_button_messages(void)
2647 const struct message *setfocus;
2648 const struct message *killfocus;
2650 { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
2651 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2652 { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
2653 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2654 { BS_CHECKBOX, DLGC_BUTTON,
2655 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2656 { BS_AUTOCHECKBOX, DLGC_BUTTON,
2657 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2658 { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
2659 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2660 { BS_3STATE, DLGC_BUTTON,
2661 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2662 { BS_AUTO3STATE, DLGC_BUTTON,
2663 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2664 { BS_GROUPBOX, DLGC_STATIC,
2665 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2666 { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
2667 WmSetFocusButtonSeq, WmKillFocusButtonSeq },
2668 { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
2669 WmSetFocusStaticSeq, WmKillFocusStaticSeq },
2670 { BS_OWNERDRAW, DLGC_BUTTON,
2671 WmSetFocusButtonSeq, WmKillFocusButtonSeq }
2679 for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
2681 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP,
2682 0, 0, 50, 14, 0, 0, 0, NULL);
2683 ok(hwnd != 0, "Failed to create button window\n");
2685 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
2686 ok(dlg_code == button[i].dlg_code, "%d: wrong dlg_code %08lx\n", i, dlg_code);
2688 ShowWindow(hwnd, SW_SHOW);
2693 trace("button style %08lx\n", button[i].style);
2695 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
2698 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
2700 DestroyWindow(hwnd);
2703 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON | WS_POPUP | WS_VISIBLE,
2704 0, 0, 50, 14, 0, 0, 0, NULL);
2705 ok(hwnd != 0, "Failed to create button window\n");
2710 SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
2711 ok_sequence(WmLButtonDownSeq, "WM_LBUTTONDOWN on a button", FALSE);
2713 SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
2714 ok_sequence(WmLButtonUpSeq, "WM_LBUTTONDOWN on a button", FALSE);
2715 DestroyWindow(hwnd);
2718 /************* painting message test ********************/
2720 static void dump_region(HRGN hrgn)
2723 RGNDATA *data = NULL;
2728 printf( "null region\n" );
2731 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
2732 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
2733 GetRegionData( hrgn, size, data );
2734 printf("%ld rects:", data->rdh.nCount );
2735 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
2736 printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
2738 HeapFree( GetProcessHeap(), 0, data );
2741 static void check_update_rgn( HWND hwnd, HRGN hrgn )
2745 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
2746 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
2748 ret = GetUpdateRgn( hwnd, update, FALSE );
2749 ok( ret != ERROR, "GetUpdateRgn failed\n" );
2750 if (ret == NULLREGION)
2752 ok( !hrgn, "Update region shouldn't be empty\n" );
2756 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
2758 ok( 0, "Regions are different\n" );
2759 if (winetest_debug > 0)
2761 printf( "Update region: " );
2762 dump_region( update );
2763 printf( "Wanted region: " );
2764 dump_region( hrgn );
2768 GetRgnBox( update, &r1 );
2769 GetUpdateRect( hwnd, &r2, FALSE );
2770 ok( r1.left == r2.left && r1.top == r2.top && r1.right == r2.right && r1.bottom == r2.bottom,
2771 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
2772 r1.left, r1.top, r1.right, r1.bottom, r2.left, r2.top, r2.right, r2.bottom );
2774 DeleteObject( tmp );
2775 DeleteObject( update );
2778 static const struct message WmInvalidateRgn[] = {
2779 { WM_NCPAINT, sent },
2780 { WM_GETTEXT, sent|defwinproc|optional },
2784 static const struct message WmInvalidateFull[] = {
2785 { WM_NCPAINT, sent|wparam, 1 },
2786 { WM_GETTEXT, sent|defwinproc|optional },
2790 static const struct message WmInvalidateErase[] = {
2791 { WM_NCPAINT, sent|wparam, 1 },
2792 { WM_GETTEXT, sent|defwinproc|optional },
2793 { WM_ERASEBKGND, sent },
2797 static const struct message WmInvalidatePaint[] = {
2799 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
2800 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2804 static const struct message WmInvalidateErasePaint[] = {
2806 { WM_NCPAINT, sent|wparam|beginpaint, 1 },
2807 { WM_GETTEXT, sent|beginpaint|defwinproc|optional },
2808 { WM_ERASEBKGND, sent|beginpaint },
2812 static const struct message WmErase[] = {
2813 { WM_ERASEBKGND, sent },
2817 static const struct message WmPaint[] = {
2822 static void test_paint_messages(void)
2826 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2827 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
2828 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
2829 100, 100, 200, 200, 0, 0, 0, NULL);
2830 ok (hwnd != 0, "Failed to create overlapped window\n");
2832 ShowWindow( hwnd, SW_SHOW );
2833 UpdateWindow( hwnd );
2834 check_update_rgn( hwnd, 0 );
2835 SetRectRgn( hrgn, 10, 10, 20, 20 );
2836 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
2837 check_update_rgn( hwnd, hrgn );
2838 SetRectRgn( hrgn2, 20, 20, 30, 30 );
2839 RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
2840 CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
2841 check_update_rgn( hwnd, hrgn );
2842 /* validate everything */
2843 RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
2844 check_update_rgn( hwnd, 0 );
2845 /* now with frame */
2846 SetRectRgn( hrgn, -5, -5, 20, 20 );
2849 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
2850 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
2852 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
2853 check_update_rgn( hwnd, hrgn );
2856 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
2857 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
2860 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW );
2861 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
2863 GetClientRect( hwnd, &rect );
2864 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
2865 check_update_rgn( hwnd, hrgn );
2868 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW );
2869 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
2872 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW );
2873 ok_sequence( WmInvalidatePaint, "InvalidatePaint", TRUE );
2874 check_update_rgn( hwnd, 0 );
2877 RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW );
2878 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
2879 check_update_rgn( hwnd, 0 );
2882 SetRectRgn( hrgn, 0, 0, 100, 100 );
2883 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
2884 SetRectRgn( hrgn, 0, 0, 50, 100 );
2885 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
2886 SetRectRgn( hrgn, 50, 0, 100, 100 );
2887 check_update_rgn( hwnd, hrgn );
2888 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
2889 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
2890 check_update_rgn( hwnd, 0 );
2893 SetRectRgn( hrgn, 0, 0, 100, 100 );
2894 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
2895 SetRectRgn( hrgn, 0, 0, 100, 50 );
2896 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW );
2897 ok_sequence( WmErase, "Erase", FALSE );
2898 SetRectRgn( hrgn, 0, 50, 100, 100 );
2899 check_update_rgn( hwnd, hrgn );
2902 SetRectRgn( hrgn, 0, 0, 100, 100 );
2903 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
2904 SetRectRgn( hrgn, 0, 0, 50, 50 );
2905 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW );
2906 ok_sequence( WmPaint, "Paint", FALSE );
2909 SetRectRgn( hrgn, -4, -4, -2, -2 );
2910 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
2911 SetRectRgn( hrgn, -4, -4, -3, -3 );
2912 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW );
2913 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
2916 SetRectRgn( hrgn, -4, -4, -2, -2 );
2917 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
2918 SetRectRgn( hrgn, -4, -4, -3, -3 );
2919 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME );
2920 SetRectRgn( hrgn, 0, 0, 1, 1 );
2921 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW );
2922 ok_sequence( WmPaint, "Paint", TRUE );
2925 SetRectRgn( hrgn, -4, -4, -1, -1 );
2926 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
2927 RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW );
2928 /* make sure no WM_PAINT was generated */
2929 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
2930 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
2933 SetRectRgn( hrgn, -4, -4, -1, -1 );
2934 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME );
2935 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
2937 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
2939 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
2940 INT ret = GetUpdateRgn( hwnd, hrgn, FALSE );
2941 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
2942 ret = GetUpdateRect( hwnd, &rect, FALSE );
2943 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
2944 /* this will send WM_NCPAINT and validate the non client area */
2945 ret = GetUpdateRect( hwnd, &rect, TRUE );
2946 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
2948 else DispatchMessage( &msg );
2950 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
2952 DeleteObject( hrgn );
2953 DeleteObject( hrgn2 );
2954 DestroyWindow( hwnd );
2963 static DWORD WINAPI thread_proc(void *param)
2966 struct wnd_event *wnd_event = (struct wnd_event *)param;
2968 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
2969 100, 100, 200, 200, 0, 0, 0, NULL);
2970 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
2972 SetEvent(wnd_event->event);
2974 while (GetMessage(&msg, 0, 0, 0))
2976 TranslateMessage(&msg);
2977 DispatchMessage(&msg);
2983 static void test_interthread_messages(void)
2990 int len, expected_len;
2991 struct wnd_event wnd_event;
2993 wnd_event.event = CreateEventW(NULL, 0, 0, NULL);
2994 if (!wnd_event.event)
2996 trace("skipping interthread message test under win9x\n");
3000 hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid);
3001 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
3003 ok(WaitForSingleObject(wnd_event.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3005 CloseHandle(wnd_event.event);
3007 SetLastError(0xdeadbeef);
3008 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n");
3009 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error code %ld\n", GetLastError());
3011 proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3012 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
3014 expected_len = lstrlenA("window caption text");
3015 memset(buf, 0, sizeof(buf));
3016 SetLastError(0xdeadbeef);
3017 len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
3018 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
3019 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
3021 msg.hwnd = wnd_event.hwnd;
3022 msg.message = WM_GETTEXT;
3023 msg.wParam = sizeof(buf);
3024 msg.lParam = (LPARAM)buf;
3025 memset(buf, 0, sizeof(buf));
3026 SetLastError(0xdeadbeef);
3027 len = DispatchMessageA(&msg);
3028 ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3029 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len, GetLastError());
3031 /* the following test causes an exception in user.exe under win9x */
3032 msg.hwnd = wnd_event.hwnd;
3033 msg.message = WM_TIMER;
3035 msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC);
3036 SetLastError(0xdeadbeef);
3037 len = DispatchMessageA(&msg);
3038 ok(!len && GetLastError() == 0xdeadbeef,
3039 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
3041 ok(PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0), "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
3043 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3044 CloseHandle(hThread);
3048 static const struct message WmVkN[] = {
3049 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3050 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3051 { WM_CHAR, wparam|lparam, 'n', 1 },
3052 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
3053 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3054 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3057 static const struct message WmShiftVkN[] = {
3058 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 },
3059 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 },
3060 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3061 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3062 { WM_CHAR, wparam|lparam, 'N', 1 },
3063 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
3064 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3065 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3066 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
3067 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
3070 static const struct message WmCtrlVkN[] = {
3071 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3072 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3073 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3074 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
3075 { WM_CHAR, wparam|lparam, 0x000e, 1 },
3076 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3077 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3078 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3079 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3080 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3083 static const struct message WmCtrlVkN_2[] = {
3084 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3085 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3086 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
3087 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
3088 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
3089 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
3090 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3091 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3094 static const struct message WmAltVkN[] = {
3095 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3096 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3097 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3098 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3099 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
3100 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
3101 { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' },
3102 { HCBT_SYSCOMMAND, hook },
3103 { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
3104 { WM_SETCURSOR, sent|defwinproc },
3105 { WM_INITMENU, sent|defwinproc },
3106 { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
3107 { WM_CAPTURECHANGED, sent|defwinproc },
3108 { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) },
3109 { WM_EXITMENULOOP, sent|defwinproc },
3110 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
3111 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
3112 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3113 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3114 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3115 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3118 static const struct message WmAltVkN_2[] = {
3119 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3120 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3121 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
3122 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
3123 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
3124 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3125 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3126 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3129 static const struct message WmCtrlAltVkN[] = {
3130 { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 },
3131 { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 },
3132 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
3133 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
3134 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
3135 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
3136 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
3137 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
3138 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
3139 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
3140 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
3141 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
3145 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
3149 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
3151 struct message log_msg;
3153 trace("accel: %p, %04x, %08x, %08lx\n", msg.hwnd, msg.message, msg.wParam, msg.lParam);
3155 log_msg.message = msg.message;
3156 log_msg.flags = wparam|lparam;
3157 log_msg.wParam = msg.wParam;
3158 log_msg.lParam = msg.lParam;
3159 add_message(&log_msg);
3161 if (!TranslateAccelerator(hwnd, hAccel, &msg))
3163 TranslateMessage(&msg);
3164 DispatchMessage(&msg);
3169 static void test_accelerators(void)
3173 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
3174 100, 100, 200, 200, 0, 0, 0, NULL);
3178 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3180 state = GetKeyState(VK_SHIFT);
3181 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
3182 state = GetKeyState(VK_CAPITAL);
3183 ok(state == 0, "wrong CapsLock state %04x\n", state);
3185 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
3186 assert(hAccel != 0);
3188 trace("testing VK_N press/release\n");
3190 keybd_event('N', 0, 0, 0);
3191 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3192 pump_msg_loop(hwnd, hAccel);
3193 ok_sequence(WmVkN, "VK_N press/release", FALSE);
3195 trace("testing Shift+VK_N press/release\n");
3197 keybd_event(VK_SHIFT, 0, 0, 0);
3198 keybd_event('N', 0, 0, 0);
3199 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3200 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
3201 pump_msg_loop(hwnd, hAccel);
3202 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
3204 trace("testing Ctrl+VK_N press/release\n");
3206 keybd_event(VK_CONTROL, 0, 0, 0);
3207 keybd_event('N', 0, 0, 0);
3208 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3209 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3210 pump_msg_loop(hwnd, hAccel);
3211 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
3213 trace("testing Alt+VK_N press/release\n");
3215 keybd_event(VK_MENU, 0, 0, 0);
3216 keybd_event('N', 0, 0, 0);
3217 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3218 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3219 pump_msg_loop(hwnd, hAccel);
3220 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
3222 trace("testing Ctrl+Alt+VK_N press/release\n");
3224 keybd_event(VK_CONTROL, 0, 0, 0);
3225 keybd_event(VK_MENU, 0, 0, 0);
3226 keybd_event('N', 0, 0, 0);
3227 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3228 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3229 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3230 pump_msg_loop(hwnd, hAccel);
3231 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
3233 ok(DestroyAcceleratorTable(hAccel), "DestroyAcceleratorTable error %ld\n", GetLastError());
3235 hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
3236 assert(hAccel != 0);
3238 trace("testing VK_N press/release\n");
3240 keybd_event('N', 0, 0, 0);
3241 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3242 pump_msg_loop(hwnd, hAccel);
3243 ok_sequence(WmVkN, "VK_N press/release", FALSE);
3245 trace("testing Shift+VK_N press/release\n");
3247 keybd_event(VK_SHIFT, 0, 0, 0);
3248 keybd_event('N', 0, 0, 0);
3249 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3250 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
3251 pump_msg_loop(hwnd, hAccel);
3252 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
3254 trace("testing Ctrl+VK_N press/release 2\n");
3256 keybd_event(VK_CONTROL, 0, 0, 0);
3257 keybd_event('N', 0, 0, 0);
3258 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3259 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3260 pump_msg_loop(hwnd, hAccel);
3261 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
3263 trace("testing Alt+VK_N press/release 2\n");
3265 keybd_event(VK_MENU, 0, 0, 0);
3266 keybd_event('N', 0, 0, 0);
3267 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3268 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3269 pump_msg_loop(hwnd, hAccel);
3270 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
3272 trace("testing Ctrl+Alt+VK_N press/release\n");
3274 keybd_event(VK_CONTROL, 0, 0, 0);
3275 keybd_event(VK_MENU, 0, 0, 0);
3276 keybd_event('N', 0, 0, 0);
3277 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
3278 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
3279 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
3280 pump_msg_loop(hwnd, hAccel);
3281 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
3283 ok(DestroyAcceleratorTable(hAccel), "DestroyAcceleratorTable error %ld\n", GetLastError());
3285 DestroyWindow(hwnd);
3288 /************* window procedures ********************/
3290 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3292 static long defwndproc_counter = 0;
3293 static long beginpaint_counter = 0;
3297 trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3301 case WM_WINDOWPOSCHANGING:
3302 case WM_WINDOWPOSCHANGED:
3304 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
3306 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
3307 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
3308 winpos->hwnd, winpos->hwndInsertAfter,
3309 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
3311 /* Log only documented flags, win2k uses 0x1000 and 0x2000
3312 * in the high word for internal purposes
3314 wParam = winpos->flags & 0xffff;
3319 msg.message = message;
3320 msg.flags = sent|wparam|lparam;
3321 if (defwndproc_counter) msg.flags |= defwinproc;
3322 if (beginpaint_counter) msg.flags |= beginpaint;
3323 msg.wParam = wParam;
3324 msg.lParam = lParam;
3327 if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
3329 HWND parent = GetParent(hwnd);
3331 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
3333 GetClientRect(parent, &rc);
3334 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
3336 trace("ptReserved = (%ld,%ld)\n"
3337 "ptMaxSize = (%ld,%ld)\n"
3338 "ptMaxPosition = (%ld,%ld)\n"
3339 "ptMinTrackSize = (%ld,%ld)\n"
3340 "ptMaxTrackSize = (%ld,%ld)\n",
3341 minmax->ptReserved.x, minmax->ptReserved.y,
3342 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
3343 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
3344 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
3345 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
3347 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
3348 minmax->ptMaxSize.x, rc.right);
3349 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
3350 minmax->ptMaxSize.y, rc.bottom);
3353 if (message == WM_PAINT)
3356 beginpaint_counter++;
3357 BeginPaint( hwnd, &ps );
3358 beginpaint_counter--;
3359 EndPaint( hwnd, &ps );
3363 defwndproc_counter++;
3364 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3365 defwndproc_counter--;
3370 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3372 static long defwndproc_counter = 0;
3376 trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3378 msg.message = message;
3379 msg.flags = sent|wparam|lparam;
3380 if (defwndproc_counter) msg.flags |= defwinproc;
3381 msg.wParam = wParam;
3382 msg.lParam = lParam;
3385 if (message == WM_CREATE)
3387 DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
3388 SetWindowLongA(hwnd, GWL_STYLE, style);
3391 defwndproc_counter++;
3392 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3393 defwndproc_counter--;
3398 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3400 static long defwndproc_counter = 0;
3404 trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3406 if (message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
3407 message == WM_SETFOCUS || message == WM_KILLFOCUS ||
3408 message == WM_ENABLE || message == WM_ENTERIDLE ||
3409 message == WM_IME_SETCONTEXT)
3411 msg.message = message;
3412 msg.flags = sent|parent|wparam|lparam;
3413 if (defwndproc_counter) msg.flags |= defwinproc;
3414 msg.wParam = wParam;
3415 msg.lParam = lParam;
3419 defwndproc_counter++;
3420 ret = DefWindowProcA(hwnd, message, wParam, lParam);
3421 defwndproc_counter--;
3426 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3428 static long defwndproc_counter = 0;
3432 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
3434 DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
3435 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
3436 if (after_end_dialog)
3437 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
3439 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
3441 msg.message = message;
3442 msg.flags = sent|wparam|lparam;
3443 if (defwndproc_counter) msg.flags |= defwinproc;
3444 msg.wParam = wParam;
3445 msg.lParam = lParam;
3448 defwndproc_counter++;
3449 ret = DefDlgProcA(hwnd, message, wParam, lParam);
3450 defwndproc_counter--;
3455 static BOOL RegisterWindowClasses(void)
3460 cls.lpfnWndProc = MsgCheckProcA;
3463 cls.hInstance = GetModuleHandleA(0);
3465 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
3466 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
3467 cls.lpszMenuName = NULL;
3468 cls.lpszClassName = "TestWindowClass";
3469 if(!RegisterClassA(&cls)) return FALSE;
3471 cls.lpfnWndProc = PopupMsgCheckProcA;
3472 cls.lpszClassName = "TestPopupClass";
3473 if(!RegisterClassA(&cls)) return FALSE;
3475 cls.lpfnWndProc = ParentMsgCheckProcA;
3476 cls.lpszClassName = "TestParentClass";
3477 if(!RegisterClassA(&cls)) return FALSE;
3479 cls.lpfnWndProc = DefWindowProcA;
3480 cls.lpszClassName = "SimpleWindowClass";
3481 if(!RegisterClassA(&cls)) return FALSE;
3483 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
3484 cls.lpfnWndProc = TestDlgProcA;
3485 cls.lpszClassName = "TestDialogClass";
3486 if(!RegisterClassA(&cls)) return FALSE;
3491 static HHOOK hCBT_hook;
3493 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
3497 trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
3499 if (nCode == HCBT_SYSCOMMAND)
3503 msg.message = nCode;
3505 msg.wParam = wParam;
3506 msg.lParam = lParam;
3509 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
3512 /* Log also SetFocus(0) calls */
3513 if (!wParam) wParam = lParam;
3515 if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
3517 if (!strcmp(buf, "TestWindowClass") ||
3518 !strcmp(buf, "TestParentClass") ||
3519 !strcmp(buf, "TestPopupClass") ||
3520 !strcmp(buf, "SimpleWindowClass") ||
3521 !strcmp(buf, "TestDialogClass") ||
3522 !strcmp(buf, "MDI_frame_class") ||
3523 !strcmp(buf, "MDI_client_class") ||
3524 !strcmp(buf, "MDI_child_class") ||
3525 !strcmp(buf, "my_button_class") ||
3526 !strcmp(buf, "#32770"))
3530 msg.message = nCode;
3532 msg.wParam = wParam;
3533 msg.lParam = lParam;
3537 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
3540 static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
3541 static const WCHAR wszAnsi[] = {'U',0};
3543 static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3547 case CB_FINDSTRINGEXACT:
3548 trace("String: %p\n", (LPCWSTR)lParam);
3549 if (!lstrcmpW((LPCWSTR)lParam, wszUnicode))
3551 if (!lstrcmpW((LPCWSTR)lParam, wszAnsi))
3555 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
3558 static void test_message_conversion(void)
3560 static const WCHAR wszMsgConversionClass[] =
3561 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
3568 cls.lpfnWndProc = MsgConversionProcW;
3571 cls.hInstance = GetModuleHandleW(NULL);
3573 cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
3574 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
3575 cls.lpszMenuName = NULL;
3576 cls.lpszClassName = wszMsgConversionClass;
3577 /* this call will fail on Win9x, but that doesn't matter as this test is
3578 * meaningless on those platforms */
3579 if(!RegisterClassW(&cls)) return;
3581 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
3582 100, 100, 200, 200, 0, 0, 0, NULL);
3583 ok(hwnd != NULL, "Window creation failed\n");
3587 wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
3588 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3589 ok(lRes == 0, "String should have been converted\n");
3590 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3591 ok(lRes == 1, "String shouldn't have been converted\n");
3595 wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
3596 lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3597 ok(lRes == 1, "String shouldn't have been converted\n");
3598 lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3599 ok(lRes == 1, "String shouldn't have been converted\n");
3601 /* Synchronous messages */
3603 lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3604 ok(lRes == 0, "String should have been converted\n");
3605 lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3606 ok(lRes == 1, "String shouldn't have been converted\n");
3608 /* Asynchronous messages */
3611 lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3612 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3613 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3615 lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3616 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3617 "PostMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3619 lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3620 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3621 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3623 lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3624 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3625 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3627 lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3628 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3629 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3631 lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode);
3632 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3633 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3635 lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
3636 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3637 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3639 lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
3640 ok(lRes == 0 && GetLastError() == ERROR_MESSAGE_SYNC_ONLY,
3641 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
3646 if (!RegisterWindowClasses()) assert(0);
3648 hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
3652 test_mdi_messages();
3653 test_button_messages();
3654 test_paint_messages();
3655 test_interthread_messages();
3656 test_message_conversion();
3657 test_accelerators();
3659 UnhookWindowsHookEx(hCBT_hook);