ReactOS 0.4.17-dev-482-g1b46029
msg.c
Go to the documentation of this file.
1/*
2 * Unit tests for window message handling
3 *
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004,2005,2016 Dmitry Timoshkov
7 *
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.
12 *
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.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23#include <limits.h>
24#include <stdarg.h>
25#include <stdbool.h>
26#include <stdio.h>
27
28#include "windef.h"
29#include "winbase.h"
30#include "wingdi.h"
31#include "winuser.h"
32#include "winnls.h"
33#include "dbt.h"
34#include "commctrl.h"
35#include "imm.h"
36
37#include "wine/test.h"
38
39#define MDI_FIRST_CHILD_ID 2004
40
41/* undocumented SWP flags - from SDK 3.1 */
42#define SWP_NOCLIENTSIZE 0x0800
43#define SWP_NOCLIENTMOVE 0x1000
44#define SWP_STATECHANGED 0x8000
45
46#define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
47
48#ifndef WM_KEYF1
49#define WM_KEYF1 0x004d
50#endif
51
52#ifndef WM_SYSTIMER
53#define WM_SYSTIMER 0x0118
54#endif
55
56#define WND_PARENT_ID 1
57#define WND_POPUP_ID 2
58#define WND_CHILD_ID 3
59
60#ifndef WM_LBTRACKPOINT
61#define WM_LBTRACKPOINT 0x0131
62#endif
63
64#ifdef __i386__
65#define ARCH "x86"
66#elif defined __aarch64__ || defined__arm64ec__
67#define ARCH "arm64"
68#elif defined __x86_64__
69#define ARCH "amd64"
70#elif defined __arm__
71#define ARCH "arm"
72#else
73#define ARCH "none"
74#endif
75#ifdef __REACTOS__
76// Temp for now to see where this is crashing on WS03 testbot
77extern int winetest_debug;
78#endif
79
80static void pump_msg_loop(HWND hwnd, HACCEL hAccel);
81
82/* encoded DRAWITEMSTRUCT into an LPARAM */
83typedef struct
84{
85 union
86 {
87 struct
88 {
89 UINT type : 4; /* ODT_* flags */
90 UINT ctl_id : 4; /* Control ID */
91 UINT item_id : 4; /* Menu item ID */
92 UINT action : 4; /* ODA_* flags */
93 UINT state : 16; /* ODS_* flags */
96 } u;
98
99/* encoded MEASUREITEMSTRUCT into a WPARAM */
100typedef struct
101{
102 union
103 {
104 struct
105 {
106 UINT CtlType : 4;
107 UINT CtlID : 4;
108 UINT itemID : 4;
109 UINT wParam : 20;
111 WPARAM wp;
112 } u;
114
119static HHOOK hKBD_hook;
120static HHOOK hCBT_hook;
123
124static const WCHAR testWindowClassW[] =
125{ 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
126
128
129static void register_class(const WNDCLASSA *class)
130{
131 BOOL ret = RegisterClassA(class);
132 ok(ret, "Failed to register class %s, error %lu.\n",
133 debugstr_a(class->lpszClassName), GetLastError());
134}
135
136/*
137FIXME: add tests for these
138Window Edge Styles (Win31/Win95/98 look), in order of precedence:
139 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
140 WS_THICKFRAME: thick border
141 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
142 WS_BORDER (default for overlapped windows): single black border
143 none (default for child (and popup?) windows): no border
144*/
145
146typedef enum {
147 sent=0x1,
151 lparam=0x10,
155 hook=0x100,
157 kbd_hook=0x400,
158 msg_todo=0x800,
159 wine_only=0x1000
161
162struct message {
163 UINT message; /* the WM_* code */
164 msg_flags_t flags; /* message props */
165 WPARAM wParam; /* expected value of wParam */
166 LPARAM lParam; /* expected value of lParam */
167 WPARAM wp_mask; /* mask for wParam checks */
168 LPARAM lp_mask; /* mask for lParam checks */
169};
170
171struct recvd_message {
172 UINT message; /* the WM_* code */
173 msg_flags_t flags; /* message props */
174 HWND hwnd; /* window that received the message */
175 WPARAM wParam; /* expected value of wParam */
176 LPARAM lParam; /* expected value of lParam */
177 int line; /* source line where logged */
178 const char *descr; /* description for trace output */
179 char output[512]; /* trace output */
180};
181
182/* Empty message sequence */
183static const struct message WmEmptySeq[] =
184{
185 { 0 }
186};
187/* CreateWindow (for overlapped window, not initially visible) (16/32) */
188static const struct message WmCreateOverlappedSeq[] = {
189 { HCBT_CREATEWND, hook },
191 { WM_NCCREATE, sent },
192 { WM_NCCALCSIZE, sent|wparam, 0 },
193 { 0x0093, sent|defwinproc|optional },
194 { 0x0094, sent|defwinproc|optional },
195 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on win10. */
196 { WM_CREATE, sent },
197 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
198 { 0 }
199};
200/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
201 * for a not visible overlapped window.
202 */
203static const struct message WmSWP_ShowOverlappedSeq[] = {
205 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
209 { HCBT_ACTIVATE, hook },
210 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
211 { WM_NOTIFYFORMAT, sent|optional },
212 { WM_QUERYUISTATE, sent|optional },
214 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
215 { WM_ACTIVATEAPP, sent|wparam, 1 },
216 { WM_NCACTIVATE, sent },
218 { WM_ACTIVATE, sent|wparam, 1 },
219 { HCBT_SETFOCUS, hook },
222 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
228 /* Win9x adds SWP_NOZORDER below */
234 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on win10 */
241 { 0 }
242};
243/* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
244 * for a visible overlapped window.
245 */
246static const struct message WmSWP_HideOverlappedSeq[] = {
248 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
255 { 0 }
256};
257
258/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
259 * for a visible overlapped window.
260 */
261static const struct message WmSWP_ResizeSeq[] = {
274 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
275 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
276 { 0 }
277};
278
279/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
280 * for a visible popup window.
281 */
282static const struct message WmSWP_ResizePopupSeq[] = {
284 { WM_GETMINMAXINFO, sent|defwinproc|optional }, /* Win9x */
295 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
296 { 0 }
297};
298
299/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
300 * for a visible overlapped window.
301 */
302static const struct message WmSWP_MoveSeq[] = {
309 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
310 { 0 }
311};
312/* Resize with SetWindowPos(SWP_NOZORDER)
313 * for a visible overlapped window
314 * SWP_NOZORDER is stripped by the logging code
315 */
316static const struct message WmSWP_ResizeNoZOrder[] = {
317 { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE },
323 { WM_WINDOWPOSCHANGED, sent|wparam|optional, /*SWP_NOZORDER|*/SWP_NOACTIVATE, 0,
327 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */
328 { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */
329 { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */
330 { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */
331 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
332 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on win10. */
333 { 0 }
334};
335
336/* Switch visible mdi children */
337static const struct message WmSwitchChild[] = {
338 /* Switch MDI child */
339 { WM_MDIACTIVATE, sent },/* in the MDI client */
340 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */
341 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
342 { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */
343 /* Deactivate 2nd MDI child */
344 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */
345 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */
347 /* Preparing for maximize and maximize the 1st MDI child */
348 { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */
350 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */
351 { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
353 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */
354 /* Lock redraw 2nd MDI child */
355 { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */
357 /* Restore 2nd MDI child */
359 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */
360 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */
362 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */
363 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */
364 /* Redraw 2nd MDI child */
365 { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */
366 /* Redraw MDI frame */
368 { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */
370 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */
371 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
373 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */
374 { HCBT_SETFOCUS, hook },
375 { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */
376 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },/* in the 1st MDI child */
377 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
378 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
379 { WM_SETFOCUS, sent },/* in the MDI client */
380 { HCBT_SETFOCUS, hook },
381 { WM_KILLFOCUS, sent },/* in the MDI client */
382 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
383 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, /* in the 1st MDI child */
384 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
385 { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */
386 { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */
388 { 0 }
389};
390
391/* Switch visible not maximized mdi children */
392static const struct message WmSwitchNotMaximizedChild[] = {
393 /* Switch not maximized MDI child */
394 { WM_MDIACTIVATE, sent },/* in the MDI client */
395 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 2nd MDI child */
396 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
397 { WM_CHILDACTIVATE, sent },/* in the 2nd MDI child */
398 /* Deactivate 1st MDI child */
399 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
400 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
401 /* Activate 2nd MDI child */
403 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 2nd MDI child */
404 { HCBT_SETFOCUS, hook }, /* in the 1st MDI child */
405 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
406 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */
407 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */
408 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
409 { WM_SETFOCUS, sent, 0 }, /* in the MDI client */
410 { HCBT_SETFOCUS, hook },
411 { WM_KILLFOCUS, sent }, /* in the MDI client */
412 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */
413 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */
414 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
415 { WM_SETFOCUS, sent|defwinproc }, /* in the 2nd MDI child */
416 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */
418 { 0 }
419};
420
421
422/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
423 SWP_NOZORDER|SWP_FRAMECHANGED)
424 * for a visible overlapped window with WS_CLIPCHILDREN style set.
425 */
426static const struct message WmSWP_FrameChanged_clip[] = {
429 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */
432 { WM_NCPAINT, sent }, /* wparam != 1 */
433 { WM_ERASEBKGND, sent },
435 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
436 { WM_PAINT, sent },
437 { 0 }
438};
439/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
440 SWP_NOZORDER|SWP_FRAMECHANGED)
441 * for a visible overlapped window.
442 */
443static const struct message WmSWP_FrameChangedDeferErase[] = {
447 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
449 { WM_NCPAINT, sent|beginpaint|parent|optional }, /* wparam != 1 */
451 { WM_PAINT, sent },
452 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
454 { 0 }
455};
456
457/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
458 SWP_NOZORDER|SWP_FRAMECHANGED)
459 * for a visible overlapped window without WS_CLIPCHILDREN style set.
460 */
461static const struct message WmSWP_FrameChanged_noclip[] = {
464 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */
468 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
469 { WM_PAINT, sent },
470 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
472 { 0 }
473};
474
475/* ShowWindow(SW_SHOW) for a not visible overlapped window */
476static const struct message WmShowOverlappedSeq[] = {
477 { WM_SHOWWINDOW, sent|wparam, 1 },
480 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
485 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|optional, 0, 0 },
496 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
502 /* Win9x adds SWP_NOZORDER below */
509#if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
510 * messages. Does that mean that CreateWindow doesn't set initial
511 * window dimensions for overlapped windows?
512 */
513 { WM_SIZE, sent },
514 { WM_MOVE, sent },
515#endif
518 { 0 }
519};
520/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
521static const struct message WmShowMaxOverlappedSeq[] = {
527 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
529 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|optional, 0, 0 },
539 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
545 /* Win9x adds SWP_NOZORDER below */
553 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
554 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on win10. */
560 { 0 }
561};
562/* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
563static const struct message WmShowRestoreMaxOverlappedSeq[] = {
582 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
583 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
585 { 0 }
586};
587/* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
588static const struct message WmShowRestoreMinOverlappedSeq[] = {
593 { WM_WINDOWPOSCHANGING, sent|optional }, /* SWP_NOSIZE|SWP_NOMOVE */
596 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Sent on Win7. */
597 { WM_MOVE, sent|optional },
599 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Sent on Win7. */
604 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Sent on Win10. */
606 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|optional, 0, 0 },
616 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
621 { WM_ERASEBKGND, sent },
630 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
631 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
632 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 },
634 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
636 { WM_ACTIVATE, sent|wparam, 1 },
642 { 0 }
643};
644/* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
645static const struct message WmShowMinOverlappedSeq[] = {
648 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
656 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
663 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
664 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on win10. */
665 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
670
671 /* Vista sometimes restores the window right away... */
697
701 { 0 }
702};
703/* ShowWindow(SW_HIDE) for a visible overlapped window */
704static const struct message WmHideOverlappedSeq[] = {
705 { WM_SHOWWINDOW, sent|wparam, 0 },
707 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
709 { WM_SIZE, sent|optional }, /* XP doesn't send it */
710 { WM_MOVE, sent|optional }, /* XP doesn't send it */
715 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
719 { 0 }
720};
721/* DestroyWindow for a visible overlapped window */
722static const struct message WmDestroyOverlappedSeq[] = {
724 { 0x0090, sent|optional },
726 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
727 { 0x0090, sent|optional },
735 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
736 { WM_DESTROY, sent },
737 { WM_NCDESTROY, sent },
738 { 0 }
739};
740/* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
741static const struct message WmCreateMaxPopupSeq[] = {
742 { HCBT_CREATEWND, hook },
743 { WM_NCCREATE, sent },
744 { WM_NCCALCSIZE, sent|wparam, 0 },
745 { WM_CREATE, sent },
746 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
748 { WM_MOVE, sent },
756 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
757 { WM_SHOWWINDOW, sent|wparam, 1 },
759 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
760 { HCBT_ACTIVATE, hook },
761 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
767 { WM_ACTIVATEAPP, sent|wparam, 1 },
768 { WM_NCACTIVATE, sent },
769 { WM_ACTIVATE, sent|wparam, 1 },
770 { HCBT_SETFOCUS, hook },
773 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
782 { 0 }
783};
784/* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
785static const struct message WmCreateInvisibleMaxPopupSeq[] = {
786 { HCBT_CREATEWND, hook },
787 { WM_NCCREATE, sent },
788 { WM_NCCALCSIZE, sent|wparam, 0 },
789 { WM_CREATE, sent },
790 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
792 { WM_MOVE, sent },
800 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
801 { 0 }
802};
803/* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
804static const struct message WmShowMaxPopupResizedSeq[] = {
809 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
810 { HCBT_ACTIVATE, hook },
811 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
817 { WM_ACTIVATEAPP, sent|wparam, 1 },
818 { WM_NCACTIVATE, sent },
819 { WM_ACTIVATE, sent|wparam, 1 },
820 { HCBT_SETFOCUS, hook },
823 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
829 /* WinNT4.0 sends WM_MOVE */
832 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
833 { 0 }
834};
835/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
836static const struct message WmShowMaxPopupSeq[] = {
841 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
842 { HCBT_ACTIVATE, hook },
843 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
849 { WM_ACTIVATEAPP, sent|wparam, 1 },
850 { WM_NCACTIVATE, sent },
851 { WM_ACTIVATE, sent|wparam, 1 },
852 { HCBT_SETFOCUS, hook },
855 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
865 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
866 { 0 }
867};
868/* CreateWindow(WS_VISIBLE) for popup window */
869static const struct message WmCreatePopupSeq[] = {
870 { HCBT_CREATEWND, hook },
871 { WM_NCCREATE, sent },
872 { WM_NCCALCSIZE, sent|wparam, 0 },
873 { WM_CREATE, sent },
874 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
876 { WM_MOVE, sent },
877 { WM_SHOWWINDOW, sent|wparam, 1 },
879 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
880 { HCBT_ACTIVATE, hook },
881 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
887 { WM_ACTIVATEAPP, sent|wparam, 1 },
888 { WM_NCACTIVATE, sent },
889 { WM_ACTIVATE, sent|wparam, 1 },
890 { HCBT_SETFOCUS, hook },
893 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
900 { 0 }
901};
902/* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
903static const struct message WmShowVisMaxPopupSeq[] = {
916 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
917 { 0 }
918};
919/* ShowWindow(hwnd, SW_RESTORE) to a minimized window */
921{
922 { HCBT_MINMAX, hook },
923 { WM_QUERYOPEN, sent },
927 { WM_NCCALCSIZE, sent },
928 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
929 { HCBT_ACTIVATE, hook },
930 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
932 { WM_NCACTIVATE, sent },
935 { HCBT_SETFOCUS, hook },
936 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
938 { WM_NCPAINT, sent },
941 { WM_ERASEBKGND, sent },
948 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
949 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
950 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
951 /* Note this WM_ACTIVATE message even if the window is already active and focused */
954 { WM_PAINT, sent },
956 { 0 }
957};
958/* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to a minimized window */
960{
961 { HCBT_MINMAX, hook },
962 { WM_QUERYOPEN, sent },
966 { WM_NCCALCSIZE, sent },
967 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
968 { WM_NCPAINT, sent },
970 { WM_ERASEBKGND, sent },
974 /* Following optional messages are on XP/2003 */
978 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
979 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
980 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
992 /* Note this WM_ACTIVATE message on XP even if the window is already active and focused */
995 { WM_PAINT, sent },
997 { 0 }
998};
999/* ShowWindow(hwnd, SW_RESTORE) to an active minimized window */
1001{
1002 { HCBT_MINMAX, hook },
1003 { WM_QUERYOPEN, sent },
1005 { WM_NCACTIVATE, sent },
1009 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 sends this. */
1010 { WM_MOVE, sent|optional },
1011 { WM_SIZE, sent|optional },
1012 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 sends this. */
1016 { WM_NCCALCSIZE, sent },
1017 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win8+ sends this. */
1018 { WM_NCPAINT, sent },
1020 { WM_ERASEBKGND, sent },
1022 { WM_MOVE, sent|defwinproc },
1023 { WM_SIZE, sent|defwinproc },
1027 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1028 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
1029 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1030 { HCBT_SETFOCUS, hook },
1031 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1032 { WM_SETFOCUS, sent },
1033 /* Note this WM_ACTIVATE message even if the window is already active */
1036 { WM_PAINT, sent },
1038 { 0 }
1039};
1040/* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to an active minimized window */
1042{
1043 { HCBT_MINMAX, hook },
1044 { WM_QUERYOPEN, sent },
1046 { WM_NCACTIVATE, sent },
1050 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 sends this. */
1051 { WM_MOVE, sent|optional },
1052 { WM_SIZE, sent|optional },
1053 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 sends this. */
1057 { WM_NCCALCSIZE, sent },
1058 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win8+ sends this. */
1059 { WM_NCPAINT, sent },
1061 { WM_ERASEBKGND, sent },
1063 { WM_MOVE, sent|defwinproc },
1064 { WM_SIZE, sent|defwinproc },
1068 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1069 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
1070 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1071 /* Following optional messages are present on XP */
1074 /* Note this WM_ACTIVATE message even if the window is already active and with flag SW_SHOWNOACTIVATE */
1077 { WM_PAINT, sent },
1079 { 0 }
1080};
1081/* CreateWindow (for a child popup window, not initially visible) */
1082static const struct message WmCreateChildPopupSeq[] = {
1083 { HCBT_CREATEWND, hook },
1084 { WM_NCCREATE, sent },
1085 { WM_NCCALCSIZE, sent|wparam, 0 },
1086 { WM_CREATE, sent },
1087 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1089 { WM_MOVE, sent },
1090 { 0 }
1091};
1092/* CreateWindow (for a popup window, not initially visible,
1093 * which sets WS_VISIBLE in WM_CREATE handler)
1094 */
1095static const struct message WmCreateInvisiblePopupSeq[] = {
1096 { HCBT_CREATEWND, hook },
1097 { WM_NCCREATE, sent },
1098 { WM_NCCALCSIZE, sent|wparam, 0 },
1099 { WM_CREATE, sent },
1100 { WM_STYLECHANGING, sent },
1101 { WM_STYLECHANGED, sent },
1102 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1104 { WM_MOVE, sent },
1105 { 0 }
1106};
1107/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
1108 * for a popup window with WS_VISIBLE style set
1109 */
1110static const struct message WmShowVisiblePopupSeq_2[] = {
1112 { 0 }
1113};
1114/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1115 * for a popup window with WS_VISIBLE style set
1116 */
1117static const struct message WmShowVisiblePopupSeq_3[] = {
1119 { HCBT_ACTIVATE, hook },
1120 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1123 { WM_NCACTIVATE, sent },
1124 { WM_ACTIVATE, sent|wparam, 1 },
1125 { HCBT_SETFOCUS, hook },
1130 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1134 { 0 }
1135};
1136/* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
1137 */
1139 { HCBT_CREATEWND, hook },
1140 { WM_NCCREATE, sent },
1141 { WM_NCCALCSIZE, sent|wparam, 0 },
1142 { WM_CREATE, sent },
1143 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1145 { WM_MOVE, sent },
1146 { WM_SHOWWINDOW, sent|wparam, 1 },
1148 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1149 { HCBT_ACTIVATE, hook },
1150 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1153
1154 /* occasionally received on test machines */
1158
1159 { WM_ACTIVATEAPP, sent },
1160 { WM_NCACTIVATE, sent },
1161 { WM_ACTIVATE, sent },
1165 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, /* Not sent on Win10. */
1166 { HCBT_SETFOCUS, hook },
1167 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1169 { WM_NCPAINT, sent|wparam|optional, 1 }, /* Not always sent on Win8+ */
1170 { WM_ERASEBKGND, sent|optional }, /* Not always sent on Win8+ */
1172 /* occasionally received on test machines */
1175 { 0 }
1176};
1177/* CreateWindow (for a popup window with WS_VISIBLE style set)
1178 */
1179static const struct message WmShowPopupFirstDrawSeq_1[] = {
1180 { HCBT_CREATEWND, hook },
1181 { WM_NCCREATE, sent },
1182 { WM_NCCALCSIZE, sent|wparam, 0 },
1183 { WM_CREATE, sent },
1184 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1186 { WM_MOVE, sent },
1187 { WM_SHOWWINDOW, sent|wparam, 1 },
1189 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1190 { HCBT_ACTIVATE, hook },
1191 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1194 { WM_ACTIVATEAPP, sent },
1195 { WM_NCACTIVATE, sent },
1196 { WM_ACTIVATE, sent },
1200 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, /* Not sent on Win10. */
1201 { HCBT_SETFOCUS, hook },
1202 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1204 { WM_NCPAINT, sent|wparam, 1 },
1205 { WM_ERASEBKGND, sent },
1207 { WM_PAINT, sent },
1208 /* occasionally received on test machines */
1211 { 0 }
1212};
1213/* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1214 */
1215static const struct message WmShowPopupFirstDrawSeq_2[] = {
1216 { HCBT_CREATEWND, hook },
1217 { WM_NCCREATE, sent },
1218 { WM_NCCALCSIZE, sent|wparam, 0 },
1219 { WM_CREATE, sent },
1220 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1222 { WM_MOVE, sent },
1227 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1228 { HCBT_ACTIVATE, hook },
1229 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1235 { WM_ACTIVATEAPP, sent },
1236 { WM_NCACTIVATE, sent },
1237 { WM_ACTIVATE, sent },
1241 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, /* Not sent on Win10. */
1242 { HCBT_SETFOCUS, hook },
1243 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1245 { WM_NCPAINT, sent|wparam, 1 },
1246 { WM_ERASEBKGND, sent },
1248 { WM_MOVE, sent|defwinproc },
1249 { WM_SIZE, sent|defwinproc, 0 },
1250 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1251 { WM_PAINT, sent},
1252 /* occasionally received on test machines */
1255 { 0 }
1256};
1257static const struct message WmFirstDrawSetWindowPosSeq1[] = {
1258 { HCBT_CREATEWND, hook },
1259 { WM_NCCREATE, sent },
1260 { WM_NCCALCSIZE, sent|wparam, 0 },
1261 { WM_CREATE, sent },
1262 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1264 { WM_MOVE, sent },
1266 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1267 { HCBT_ACTIVATE, hook },
1268 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1271 { WM_ACTIVATEAPP, sent },
1272 { WM_NCACTIVATE, sent },
1273 { WM_ACTIVATE, sent },
1277 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, /* Not sent on Win10. */
1278 { HCBT_SETFOCUS, hook },
1279 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1281 { WM_NCPAINT, sent|wparam, 1 },
1282 { WM_ERASEBKGND, sent },
1284 { WM_MOVE, sent|defwinproc },
1285 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1286 { 0 }
1287};
1288static const struct message WmFirstDrawSetWindowPosSeq2[] = {
1289 { HCBT_CREATEWND, hook },
1290 { WM_NCCREATE, sent },
1291 { WM_NCCALCSIZE, sent|wparam, 0 },
1292 { WM_CREATE, sent },
1293 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1295 { WM_MOVE, sent },
1297 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not always sent. */
1298 { HCBT_ACTIVATE, hook },
1299 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1302 { WM_ACTIVATEAPP, sent },
1303 { WM_NCACTIVATE, sent },
1304 { WM_ACTIVATE, sent },
1308 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, /* Not sent on Win10. */
1309 { HCBT_SETFOCUS, hook },
1310 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1313 { WM_MOVE, sent|defwinproc },
1314 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1315 { 0 }
1316};
1317static const struct message WmFirstDrawSetWindowPosSeq3[] = {
1318 { HCBT_CREATEWND, hook },
1319 { WM_NCCREATE, sent },
1320 { WM_NCCALCSIZE, sent|wparam, 0 },
1321 { WM_CREATE, sent },
1322 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1324 { WM_MOVE, sent },
1325 { EVENT_OBJECT_SHOW, winevent_hook|wine_only },
1327 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|wine_only, 0, 0 },
1333 { EVENT_OBJECT_FOCUS, winevent_hook|lparam|wparam|wine_only, OBJID_CLIENT, 0 },
1335 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|lparam|wparam|wine_only, 0, 0 },
1336 { 0 }
1337};
1338static const struct message WmFirstDrawSetWindowPosSeq4[] = {
1339 { HCBT_CREATEWND, hook },
1340 { WM_NCCREATE, sent },
1341 { WM_NCCALCSIZE, sent|wparam, 0 },
1342 { WM_CREATE, sent },
1343 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1345 { WM_MOVE, sent },
1347 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1348 { HCBT_ACTIVATE, hook },
1349 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1352 { WM_ACTIVATEAPP, sent },
1353 { WM_NCACTIVATE, sent },
1354 { WM_ACTIVATE, sent },
1358 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, /* Not sent on Win10. */
1359 { HCBT_SETFOCUS, hook },
1360 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1362 { WM_NCPAINT, sent|wparam, 1 },
1363 { WM_ERASEBKGND, sent },
1365 { 0 }
1366};
1367static const struct message WmFirstDrawSetWindowPosSeq5[] = {
1368 { HCBT_CREATEWND, hook },
1369 { WM_NCCREATE, sent },
1370 { WM_NCCALCSIZE, sent|wparam, 0 },
1371 { WM_CREATE, sent },
1372 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1374 { WM_MOVE, sent },
1376 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1377 { HCBT_ACTIVATE, hook },
1378 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1381 { WM_ACTIVATEAPP, sent },
1382 { WM_NCACTIVATE, sent },
1383 { WM_ACTIVATE, sent },
1387 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, /* Not sent on Win10. */
1388 { HCBT_SETFOCUS, hook },
1389 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1392 { 0 }
1393};
1394static const struct message WmFirstDrawSetWindowPosSeq6[] = {
1395 { HCBT_CREATEWND, hook },
1396 { WM_NCCREATE, sent },
1397 { WM_NCCALCSIZE, sent|wparam, 0 },
1398 { WM_CREATE, sent },
1399 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1401 { WM_MOVE, sent },
1402 { EVENT_OBJECT_SHOW, winevent_hook|wine_only },
1404 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|wine_only, 0, 0 },
1410 { EVENT_OBJECT_FOCUS, winevent_hook|lparam|wparam|wine_only, OBJID_CLIENT, 0 },
1412 { 0 }
1413};
1414static const struct message WmFirstDrawChildSeq1[] = {
1415 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1416 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
1417 { 0 }
1418};
1419static const struct message WmFirstDrawChildSeq2[] = {
1420 { WM_NCPAINT, sent|wparam, 1 },
1421 { WM_ERASEBKGND, sent },
1422 /* occasionally received on test machines */
1425 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1426 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
1427 { 0 }
1428};
1429/* CreateWindow (for child window, not initially visible) */
1430static const struct message WmCreateChildSeq[] = {
1431 { HCBT_CREATEWND, hook },
1432 { WM_NCCREATE, sent },
1433 /* child is inserted into parent's child list after WM_NCCREATE returns */
1434 { WM_NCCALCSIZE, sent|wparam, 0 },
1435 { WM_CREATE, sent },
1436 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1438 { WM_MOVE, sent },
1440 { 0 }
1441};
1442/* CreateWindow (for maximized child window, not initially visible) */
1443static const struct message WmCreateMaximizedChildSeq[] = {
1444 { HCBT_CREATEWND, hook },
1445 { WM_NCCREATE, sent },
1446 { WM_NCCALCSIZE, sent|wparam, 0 },
1447 { WM_CREATE, sent },
1448 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1450 { WM_MOVE, sent },
1454 { WM_NCCALCSIZE, sent|wparam, 1 },
1457 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1459 { 0 }
1460};
1461/* CreateWindow (for a child window, initially visible) */
1462static const struct message WmCreateVisibleChildSeq[] = {
1463 { HCBT_CREATEWND, hook },
1464 { WM_NCCREATE, sent },
1465 /* child is inserted into parent's child list after WM_NCCREATE returns */
1466 { WM_NCCALCSIZE, sent|wparam, 0 },
1467 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win10. */
1468 { WM_CREATE, sent },
1469 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1471 { WM_MOVE, sent },
1473 { WM_SHOWWINDOW, sent|wparam, 1 },
1475 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1478 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */
1479 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1480 { 0 }
1481};
1482/* ShowWindow(SW_SHOW) for a not visible child window */
1483static const struct message WmShowChildSeq[] = {
1484 { WM_SHOWWINDOW, sent|wparam, 1 },
1486 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1489 { 0 }
1490};
1491/* ShowWindow(SW_HIDE) for a visible child window */
1492static const struct message WmHideChildSeq[] = {
1493 { WM_SHOWWINDOW, sent|wparam, 0 },
1495 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1498 { 0 }
1499};
1500/* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1501static const struct message WmHideChildSeq2[] = {
1502 { WM_SHOWWINDOW, sent|wparam, 0 },
1504 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1507 { 0 }
1508};
1509/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1510 * for a not visible child window
1511 */
1512static const struct message WmShowChildSeq_2[] = {
1514 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1517 { 0 }
1518};
1519/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1520 * for a not visible child window
1521 */
1522static const struct message WmShowChildSeq_3[] = {
1524 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1526 { 0 }
1527};
1528/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1529 * for a visible child window with a caption
1530 */
1531static const struct message WmShowChildSeq_4[] = {
1534 { 0 }
1535};
1536/* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1540 { WM_NCCALCSIZE, sent|wparam, 1 },
1541 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1544 { WM_MOVE, sent|defwinproc },
1546 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1547 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
1549 { 0 }
1550};
1551/* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1554 { 0 }
1555};
1556/* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1561 { WM_NCCALCSIZE, sent|wparam, 1 },
1562 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1566 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1567 { 0 }
1568};
1569/* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1572 { 0 }
1573};
1574/* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1578 { WM_NCCALCSIZE, sent|wparam, 1 },
1579 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1582 { WM_MOVE, sent|defwinproc },
1584 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1585 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
1587 { 0 }
1588};
1589/* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1592 { 0 }
1593};
1594/* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1598 { WM_NCCALCSIZE, sent|wparam, 1 },
1599 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1601 { WM_MOVE, sent|defwinproc },
1603 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1604 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
1605 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1607 { 0 }
1608};
1609/* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1612 { 0 }
1613};
1614/* ShowWindow(SW_SHOW) for child with invisible parent */
1616 { WM_SHOWWINDOW, sent|wparam, 1 },
1617 { 0 }
1618};
1619/* ShowWindow(SW_HIDE) for child with invisible parent */
1621 { WM_SHOWWINDOW, sent|wparam, 0 },
1622 { 0 }
1623};
1624/* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1627 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1629 { 0 }
1630};
1631/* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1634 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1636 { 0 }
1637};
1638/* DestroyWindow for a visible child window */
1639static const struct message WmDestroyChildSeq[] = {
1640 { HCBT_DESTROYWND, hook },
1641 { 0x0090, sent|optional },
1643 { WM_SHOWWINDOW, sent|wparam, 0 },
1645 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1648 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
1649 { WM_KILLFOCUS, sent },
1652 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1653 { WM_SETFOCUS, sent|parent },
1654 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1655 { WM_DESTROY, sent },
1656 { WM_DESTROY, sent|optional }, /* some other (IME?) window */
1657 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */
1658 { WM_NCDESTROY, sent },
1659 { 0 }
1660};
1661/* visible child window destroyed by thread exit */
1662static const struct message WmExitThreadSeq[] = {
1663 { WM_NCDESTROY, sent }, /* actually in grandchild */
1664 { WM_PAINT, sent|parent },
1666 { 0 }
1667};
1668/* DestroyWindow for a visible child window with invisible parent */
1669static const struct message WmDestroyInvisibleChildSeq[] = {
1670 { HCBT_DESTROYWND, hook },
1671 { 0x0090, sent|optional },
1673 { WM_SHOWWINDOW, sent|wparam, 0 },
1674 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1675 { WM_DESTROY, sent },
1676 { WM_NCDESTROY, sent },
1677 { 0 }
1678};
1679/* Resizing child window with MoveWindow (32) */
1682 { WM_NCCALCSIZE, sent|wparam, 1 },
1686 { WM_MOVE, sent|defwinproc },
1688 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1689 { 0 }
1690};
1691/* Creation of a custom dialog (32) */
1692static const struct message WmCreateCustomDialogSeq[] = {
1693 { HCBT_CREATEWND, hook },
1695 { WM_NCCREATE, sent },
1696 { WM_NCCALCSIZE, sent|wparam, 0 },
1697 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win10. */
1698 { WM_CREATE, sent },
1699 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1700 { WM_NOTIFYFORMAT, sent|optional },
1701 { WM_QUERYUISTATE, sent|optional },
1706 { WM_SHOWWINDOW, sent|wparam, 1 },
1708 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1709 { HCBT_ACTIVATE, hook },
1710 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1711
1712
1714
1716
1717 { WM_NCACTIVATE, sent },
1721 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
1722 { WM_ACTIVATE, sent|wparam, 1 },
1728 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1729 { WM_SETFOCUS, sent },
1731 { WM_NCPAINT, sent|wparam, 1 },
1734 { WM_ERASEBKGND, sent },
1745 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win10. */
1747 { WM_MOVE, sent },
1748 { 0 }
1749};
1750/* Calling EndDialog for a custom dialog (32) */
1751static const struct message WmEndCustomDialogSeq[] = {
1753 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1756 { HCBT_ACTIVATE, hook },
1757 { WM_NCACTIVATE, sent|wparam, 0 },
1760 { WM_ACTIVATE, sent|wparam, 0 },
1761 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1766 { HCBT_SETFOCUS, hook },
1767 { WM_KILLFOCUS, sent },
1771 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1773 { 0 }
1774};
1775/* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1776static const struct message WmShowCustomDialogSeq[] = {
1777 { WM_SHOWWINDOW, sent|wparam, 1 },
1779 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1780 { HCBT_ACTIVATE, hook },
1781 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1782
1784
1787 { WM_NCACTIVATE, sent },
1788 { WM_ACTIVATE, sent|wparam, 1 },
1790
1795 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1796 { WM_SETFOCUS, sent },
1798 { WM_NCPAINT, sent|wparam, 1 },
1799 { WM_ERASEBKGND, sent },
1802 { 0 }
1803};
1804/* Creation and destruction of a modal dialog (32) */
1805static const struct message WmModalDialogSeq[] = {
1807 { HCBT_SETFOCUS, hook },
1808 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1811 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1812 { WM_ENABLE, sent|parent|wparam, 0 },
1813 { HCBT_CREATEWND, hook },
1814 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win10. */
1815 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1816 { WM_SETFONT, sent },
1817 { WM_INITDIALOG, sent },
1818 { WM_CHANGEUISTATE, sent|optional },
1819 { WM_UPDATEUISTATE, sent|optional },
1820 { WM_SHOWWINDOW, sent },
1821 { HCBT_ACTIVATE, hook },
1822 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1825 { WM_NCACTIVATE, sent },
1827 { WM_ACTIVATE, sent|wparam, 1 },
1829 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1841 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win10. */
1842 { WM_PAINT, sent|optional },
1865 { WM_TIMER, sent },
1866 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1867 { WM_ENABLE, sent|parent|wparam, 1 },
1869 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1872 { HCBT_ACTIVATE, hook },
1873 { WM_NCACTIVATE, sent|wparam, 0 },
1875 { WM_ACTIVATE, sent|wparam, 0 },
1876 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1879 { HCBT_SETFOCUS, hook },
1881 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1883 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
1884 { HCBT_DESTROYWND, hook },
1885 { 0x0090, sent|optional },
1886 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1887 { WM_DESTROY, sent },
1888 { WM_NCDESTROY, sent },
1889 { 0 }
1890};
1891static const struct message WmModalDialogSeq_2[] = {
1892 { WM_CANCELMODE, sent },
1893 { HCBT_SETFOCUS, hook },
1894 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1895 { WM_KILLFOCUS, sent },
1897 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1898 { WM_ENABLE, sent|wparam, 0 },
1899 { HCBT_CREATEWND, hook },
1900 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
1901 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1902 { WM_SETFONT, sent },
1903 { WM_INITDIALOG, sent },
1904 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1905 { WM_CHANGEUISTATE, sent|optional },
1906 { WM_UPDATEUISTATE, sent|optional },
1907 { WM_ENABLE, sent|wparam, 1 },
1909 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 },
1910 { WM_CHANGEUISTATE, sent|optional },
1911 { WM_UPDATEUISTATE, sent|optional },
1912 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
1913 { HCBT_DESTROYWND, hook },
1914 { 0x0090, sent|optional },
1915 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1916 { WM_DESTROY, sent },
1917 { WM_NCDESTROY, sent },
1918 { 0 }
1919};
1920/* SetMenu for NonVisible windows with size change*/
1923 { WM_NCCALCSIZE, sent|wparam, 1 },
1924 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1926 { WM_MOVE, sent|defwinproc },
1928 { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */
1929 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1930 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1933 { 0 }
1934};
1935/* SetMenu for NonVisible windows with no size change */
1938 { WM_NCCALCSIZE, sent|wparam, 1 },
1940 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1941 { 0 }
1942};
1943/* SetMenu for Visible windows with size change */
1946 { WM_NCCALCSIZE, sent|wparam, 1 },
1947 { 0x0093, sent|defwinproc|optional },
1948 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
1949 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1950 { 0x0093, sent|defwinproc|optional },
1951 { 0x0093, sent|defwinproc|optional },
1952 { 0x0091, sent|defwinproc|optional },
1953 { 0x0092, sent|defwinproc|optional },
1958 { WM_MOVE, sent|defwinproc },
1960 { 0x0093, sent|optional },
1962 { 0x0093, sent|defwinproc|optional },
1963 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1964 { 0x0093, sent|defwinproc|optional },
1965 { 0x0093, sent|defwinproc|optional },
1966 { 0x0091, sent|defwinproc|optional },
1967 { 0x0092, sent|defwinproc|optional },
1969 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1970 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1971 { 0 }
1972};
1973/* SetMenu for Visible windows with no size change */
1976 { WM_NCCALCSIZE, sent|wparam, 1 },
1977 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1982 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1983 { 0 }
1984};
1985/* DrawMenuBar for a visible window */
1986static const struct message WmDrawMenuBarSeq[] =
1987{
1989 { WM_NCCALCSIZE, sent|wparam, 1 },
1990 { 0x0093, sent|defwinproc|optional },
1991 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1992 { 0x0093, sent|defwinproc|optional },
1993 { 0x0093, sent|defwinproc|optional },
1994 { 0x0091, sent|defwinproc|optional },
1995 { 0x0092, sent|defwinproc|optional },
1999 { 0x0093, sent|optional },
2000 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
2001 { 0 }
2002};
2003
2004static const struct message WmSetRedrawFalseSeq[] =
2005{
2006 { WM_SETREDRAW, sent|wparam, 0 },
2007 { 0 }
2008};
2009
2010static const struct message WmSetRedrawTrueSeq[] =
2011{
2012 { WM_SETREDRAW, sent|wparam, 1 },
2013 { 0 }
2014};
2015
2016static const struct message WmEnableWindowSeq_1[] =
2017{
2018 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 },
2019 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
2022 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 },
2023 { 0 }
2024};
2025
2026static const struct message WmEnableWindowSeq_2[] =
2027{
2028 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 },
2029 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win10. */
2030 { 0 }
2031};
2032
2033static const struct message WmEnableWindowSeq_3[] =
2034{
2035 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
2036 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 },
2037 { 0 }
2038};
2039
2040static const struct message WmEnableWindowSeq_4[] =
2041{
2042 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win10. */
2043 { 0 }
2044};
2045
2046static const struct message WmGetScrollRangeSeq[] =
2047{
2048 { SBM_GETRANGE, sent },
2049 { 0 }
2050};
2051static const struct message WmGetScrollInfoSeq[] =
2052{
2053 { SBM_GETSCROLLINFO, sent },
2054 { 0 }
2055};
2056static const struct message WmSetScrollRangeSeq[] =
2057{
2058 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
2059 sends SBM_SETSCROLLINFO.
2060 */
2061 { SBM_SETSCROLLINFO, sent },
2062 { 0 }
2063};
2064/* SetScrollRange for a window without a non-client area */
2066{
2067 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 },
2068 { 0 }
2069};
2071{
2072 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 },
2073 { 0 }
2074};
2075static const struct message WmSetScrollRangeHVSeq[] =
2076{
2078 { WM_NCCALCSIZE, sent|wparam, 1 },
2082 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
2083 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2084 { 0 }
2085};
2086/* SetScrollRange for a window with a non-client area */
2087static const struct message WmSetScrollRangeHV_NC_Seq[] =
2088{
2090 { WM_NCCALCSIZE, sent|wparam, 1 },
2091 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2093 { WM_STYLECHANGING, sent|defwinproc|optional },
2094 { WM_STYLECHANGED, sent|defwinproc|optional },
2095 { WM_STYLECHANGING, sent|defwinproc|optional },
2096 { WM_STYLECHANGED, sent|defwinproc|optional },
2097 { WM_STYLECHANGING, sent|defwinproc|optional },
2098 { WM_STYLECHANGED, sent|defwinproc|optional },
2099 { WM_STYLECHANGING, sent|defwinproc|optional },
2100 { WM_STYLECHANGED, sent|defwinproc|optional },
2104 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
2107 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
2108 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2113 { 0 }
2114};
2115/* test if we receive the right sequence of messages */
2116/* after calling ShowWindow( SW_SHOWNA) */
2117static const struct message WmSHOWNAChildInvisParInvis[] = {
2118 { WM_SHOWWINDOW, sent|wparam, 1 },
2119 { 0 }
2120};
2121static const struct message WmSHOWNAChildVisParInvis[] = {
2122 { WM_SHOWWINDOW, sent|wparam, 1 },
2123 { 0 }
2124};
2125static const struct message WmSHOWNAChildVisParVis[] = {
2126 { WM_SHOWWINDOW, sent|wparam, 1 },
2128 { 0 }
2129};
2130static const struct message WmSHOWNAChildInvisParVis[] = {
2131 { WM_SHOWWINDOW, sent|wparam, 1 },
2133 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2136 { 0 }
2137};
2138static const struct message WmSHOWNATopVisible[] = {
2139 { WM_SHOWWINDOW, sent|wparam, 1 },
2145 { 0 }
2146};
2147static const struct message WmSHOWNATopInvisible[] = {
2148 { WM_NOTIFYFORMAT, sent|optional },
2149 { WM_QUERYUISTATE, sent|optional },
2154 { WM_SHOWWINDOW, sent|wparam, 1 },
2156 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2164 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
2166 { WM_MOVE, sent },
2167 { 0 }
2168};
2169
2171 { HCBT_CREATEWND, hook },
2172 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2174 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2175 { WM_INITMENU, sent|lparam, 0, 0 },
2176 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2177 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
2178 { 0x0093, sent|optional },
2179 { 0x0094, sent|optional },
2180 { 0x0094, sent|optional },
2181 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2182 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2183 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 },
2184 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2185 { WM_ENTERIDLE, sent|wparam, 2 },
2186 { HCBT_MINMAX, hook },
2187 { HCBT_SETFOCUS, hook },
2188 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2189 { WM_KILLFOCUS, sent|wparam, 0 },
2194 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2196 { WM_MOVE, sent|defwinproc },
2197 { WM_SIZE, sent|defwinproc },
2200 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2201 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
2202 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2203 { WM_CANCELMODE, sent },
2204 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2206 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2207 { HCBT_DESTROYWND, hook },
2208 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2209 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2210 { WM_UNINITMENUPOPUP, sent|defwinproc|lparam, 0, 0 },
2211 { WM_MENUSELECT, sent|defwinproc|wparam|lparam, 0xffff0000, 0 },
2212 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2214 { WM_NCACTIVATE, sent },
2217 { WM_ACTIVATE, sent },
2218 { WM_ACTIVATEAPP, sent|wparam, 0 },
2219 { 0 }
2220};
2221
2222static const struct message WmTrackPopupMenu[] = {
2223 { HCBT_CREATEWND, hook },
2224 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2226 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2227 { WM_INITMENU, sent|lparam, 0, 0 },
2228 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2229 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
2230 { 0x0093, sent|optional },
2231 { 0x0094, sent|optional },
2232 { 0x0094, sent|optional },
2233 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2234 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2235 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 },
2236 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2237 { WM_ENTERIDLE, sent|wparam, 2 },
2238 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2240 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2241 { HCBT_DESTROYWND, hook },
2242 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2243 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2244 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
2245 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
2246 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2247 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
2248 { 0 }
2249};
2250
2251static const struct message WmTrackPopupMenuEsc[] = {
2252 { 0 }
2253};
2254
2255static const struct message WmTrackPopupMenuCapture[] = {
2256 { HCBT_CREATEWND, hook },
2257 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2259 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2260 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2262 { WM_INITMENU, sent|lparam, 0, 0 },
2263 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2264 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
2265 { 0x0093, sent|optional },
2266 { 0x0094, sent|optional },
2267 { 0x0094, sent|optional },
2268 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2269 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2270 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 },
2271 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2272 { WM_ENTERIDLE, sent|wparam, 2 },
2273 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2275 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2276 { HCBT_DESTROYWND, hook },
2277 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2278 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2279 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
2280 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
2281 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2282 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
2283 { 0 }
2284};
2285
2286static const struct message WmTrackPopupMenuEmpty[] = {
2287 { HCBT_CREATEWND, hook },
2288 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2290 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2291 { WM_INITMENU, sent|lparam, 0, 0 },
2292 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2293 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
2294 { 0x0093, sent|optional },
2295 { 0x0094, sent|optional },
2296 { 0x0094, sent|optional },
2297 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2298 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2299 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2301 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
2302 { HCBT_DESTROYWND, hook },
2303 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2304 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
2305 { 0 }
2306};
2307
2308static const struct message WmTrackPopupMenuAbort[] = {
2309 { HCBT_CREATEWND, hook },
2310 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2312 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2313 { WM_INITMENU, sent|lparam, 0, 0 },
2314 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2315 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
2316 { 0x0093, sent|optional },
2317 { 0x0094, sent|optional },
2318 { 0x0094, sent|optional },
2319 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2320 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2321 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 },
2322 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2323 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2325 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
2326 { HCBT_DESTROYWND, hook },
2327 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2328 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2329 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
2330 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
2331 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
2332 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
2333 { 0 }
2334};
2335
2341
2342/* user32 functions */
2343static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG);
2345static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*);
2346static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK);
2347static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
2348static UINT_PTR (WINAPI *pSetSystemTimer)(HWND, UINT_PTR, UINT, TIMERPROC);
2349static UINT_PTR (WINAPI *pKillSystemTimer)(HWND, UINT_PTR);
2350static UINT_PTR (WINAPI *pSetCoalescableTimer)(HWND, UINT_PTR, UINT, TIMERPROC, ULONG);
2351/* kernel32 functions */
2352static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
2353
2354static void init_procs(void)
2355{
2356 HMODULE user32 = GetModuleHandleA("user32.dll");
2357 HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
2358
2359#define GET_PROC(dll, func) \
2360 p ## func = (void*)GetProcAddress(dll, #func); \
2361 if(!p ## func) { \
2362 trace("GetProcAddress(%s) failed\n", #func); \
2363 }
2364
2365 GET_PROC(user32, NotifyWinEvent)
2366 GET_PROC(user32, SetWinEventHook)
2367 GET_PROC(user32, TrackMouseEvent)
2368 GET_PROC(user32, UnhookWinEvent)
2370 GET_PROC(user32, SetSystemTimer)
2371 GET_PROC(user32, KillSystemTimer)
2372 GET_PROC(user32, SetCoalescableTimer)
2373
2374 GET_PROC(kernel32, GetCPInfoExA)
2375
2376#undef GET_PROC
2377}
2378
2379static const char *get_winpos_flags(UINT flags)
2380{
2381 static char buffer[300];
2382
2383 buffer[0] = 0;
2384#define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2394 DUMP( SWP_NOZORDER );
2395 DUMP( SWP_NOREDRAW );
2396 DUMP( SWP_NOSIZE );
2397 DUMP( SWP_NOMOVE );
2400 if (flags) sprintf(buffer + strlen(buffer),"|0x%04x", flags);
2401 return buffer + 1;
2402#undef DUMP
2403}
2404
2406{
2407 /* these are always ignored */
2408 return (message >= 0xc000 ||
2409 message == WM_GETICON ||
2410 message == WM_GETOBJECT ||
2412 message == WM_DISPLAYCHANGE ||
2416}
2417
2418static unsigned hash_Ly_W(const WCHAR *str)
2419{
2420 unsigned hash = 0;
2421
2422 for (; *str; str++)
2423 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
2424
2425 return hash;
2426}
2427
2428static unsigned hash_Ly(const char *str)
2429{
2430 unsigned hash = 0;
2431
2432 for (; *str; str++)
2433 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
2434
2435 return hash;
2436}
2437
2438#define add_message(msg) add_message_(__LINE__,msg);
2439static void add_message_(int line, const struct recvd_message *msg)
2440{
2441 struct recvd_message *seq;
2442
2444 if (!sequence)
2445 {
2446 sequence_size = 10;
2447 sequence = malloc( sequence_size * sizeof(*sequence) );
2448 }
2450 {
2451 sequence_size *= 2;
2453 }
2454
2455 seq = &sequence[sequence_cnt++];
2456 seq->hwnd = msg->hwnd;
2457 seq->message = msg->message;
2458 seq->flags = msg->flags;
2459 seq->wParam = msg->wParam;
2460 seq->lParam = msg->lParam;
2461 seq->line = line;
2462 seq->descr = msg->descr;
2463 seq->output[0] = 0;
2465
2466 if (msg->descr)
2467 {
2468 if (msg->flags & hook)
2469 {
2470 static const char * const CBT_code_name[10] =
2471 {
2472 "HCBT_MOVESIZE",
2473 "HCBT_MINMAX",
2474 "HCBT_QS",
2475 "HCBT_CREATEWND",
2476 "HCBT_DESTROYWND",
2477 "HCBT_ACTIVATE",
2478 "HCBT_CLICKSKIPPED",
2479 "HCBT_KEYSKIPPED",
2480 "HCBT_SYSCOMMAND",
2481 "HCBT_SETFOCUS"
2482 };
2483 const char *code_name = (msg->message <= HCBT_SETFOCUS) ? CBT_code_name[msg->message] : "Unknown";
2484
2485 sprintf( seq->output, "%s: hook %d (%s) wp %08Ix lp %08Ix",
2486 msg->descr, msg->message, code_name, msg->wParam, msg->lParam );
2487 }
2488 else if (msg->flags & winevent_hook)
2489 {
2490 sprintf( seq->output, "%s: winevent %p %08x %08Ix %08Ix",
2491 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam );
2492 }
2493 else
2494 {
2495 switch (msg->message)
2496 {
2499 {
2500 WINDOWPOS *winpos = (WINDOWPOS *)msg->lParam;
2501
2502 sprintf( seq->output, "%s: %p WM_WINDOWPOS%s wp %08Ix lp %08Ix after %p x %d y %d cx %d cy %d flags %s",
2503 msg->descr, msg->hwnd,
2504 (msg->message == WM_WINDOWPOSCHANGING) ? "CHANGING" : "CHANGED",
2505 msg->wParam, msg->lParam, winpos->hwndInsertAfter,
2506 winpos->x, winpos->y, winpos->cx, winpos->cy,
2507 get_winpos_flags(winpos->flags) );
2508
2509 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2510 * in the high word for internal purposes
2511 */
2512 seq->wParam = winpos->flags & 0xffff;
2513 /* We are not interested in the flags that don't match under XP and Win9x */
2514 seq->wParam &= ~SWP_NOZORDER;
2515 seq->lParam = (!!winpos->cx) | ((!!winpos->cy) << 1)
2516 | ((!!winpos->x) << 2) | ((!!winpos->y) << 3);
2517 break;
2518 }
2519
2520 case WM_NCCALCSIZE:
2521 if (msg->wParam)
2522 {
2524 WINDOWPOS *winpos = p->lppos;
2525
2526 sprintf(seq->output, "%s: %p WM_NCCALCSIZE: winpos->cx %u, winpos->cy %u",
2527 msg->descr, msg->hwnd, winpos->cx, winpos->cy);
2528 seq->lParam = (!!winpos->cx) | ((!!winpos->cy) << 1)
2529 | ((!!winpos->x) << 2) | ((!!winpos->y) << 3);
2530 }
2531 else
2532 {
2533 RECT *rect = (RECT*)msg->lParam;
2534
2535 sprintf(seq->output, "%s: %p WM_NCCALCSIZE: %s",
2536 msg->descr, msg->hwnd, wine_dbgstr_rect(rect));
2537 seq->lParam = 0;
2538 }
2539 break;
2540 case WM_DRAWITEM:
2541 {
2543 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)msg->lParam;
2544
2545 sprintf( seq->output, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2546 msg->descr, msg->hwnd, dis->CtlType, dis->CtlID,
2547 dis->itemID, dis->itemAction, dis->itemState);
2548
2549 di.u.lp = 0;
2550 di.u.item.type = dis->CtlType;
2551 di.u.item.ctl_id = dis->CtlID;
2552 if (dis->CtlType == ODT_LISTBOX ||
2553 dis->CtlType == ODT_COMBOBOX ||
2554 dis->CtlType == ODT_MENU)
2555 di.u.item.item_id = dis->itemID;
2556 di.u.item.action = dis->itemAction;
2557 di.u.item.state = dis->itemState;
2558
2559 seq->lParam = di.u.lp;
2560 break;
2561 }
2562
2563 case WM_MEASUREITEM:
2564 {
2566 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam;
2567 BOOL is_unicode_data = TRUE;
2568
2569 sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#Ix",
2570 msg->descr, msg->hwnd, mis->CtlType, mis->CtlID,
2571 mis->itemID, mis->itemData);
2572
2573 if (mis->CtlType == ODT_LISTBOX)
2574 {
2575 HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID);
2576 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
2577 }
2578
2579 mi.u.wp = 0;
2580 mi.u.item.CtlType = mis->CtlType;
2581 mi.u.item.CtlID = mis->CtlID;
2582 mi.u.item.itemID = mis->itemID;
2583 mi.u.item.wParam = msg->wParam;
2584 seq->wParam = mi.u.wp;
2585 if (is_unicode_data)
2586 seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0;
2587 else
2588 seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0;
2589 break;
2590 }
2591
2592 case WM_COMPAREITEM:
2593 {
2594 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam;
2595 HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID);
2596 BOOL is_unicode_data = TRUE;
2597
2598 ok(msg->wParam == cis->CtlID, "expected %#x, got %#Ix\n", cis->CtlID, msg->wParam);
2599 ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem);
2600 ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1);
2601 ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
2602
2603 sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#Ix, itemID2 %#x, itemData2 %#Ix",
2604 msg->descr, msg->hwnd, cis->CtlType, cis->CtlID,
2605 cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2);
2606
2607 if (cis->CtlType == ODT_LISTBOX)
2608 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
2609
2610 if (is_unicode_data)
2611 {
2612 seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0;
2613 seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0;
2614 }
2615 else
2616 {
2617 seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0;
2618 seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0;
2619 }
2620 break;
2621 }
2622
2623 default:
2624 if (msg->message >= 0xc000) return; /* ignore registered messages */
2625 sprintf( seq->output, "%s: %p %04x wp %08Ix lp %08Ix",
2626 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam );
2627 }
2628 if (msg->flags & (sent|posted|parent|defwinproc|beginpaint))
2629 sprintf( seq->output + strlen(seq->output), " (flags %x)", msg->flags );
2630 }
2631 }
2632}
2633
2634/* try to make sure pending X events have been processed before continuing */
2635static void flush_events(void)
2636{
2637 MSG msg;
2638 int diff = 200;
2639 int min_timeout = 100;
2640 DWORD time = GetTickCount() + diff;
2641
2642 while (diff > 0)
2643 {
2644 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
2645 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
2646 diff = time - GetTickCount();
2647 }
2648}
2649
2650static void flush_sequence(void)
2651{
2653 free( sequence );
2654 sequence = 0;
2657}
2658
2659static const char* message_type_name(int flags) {
2660 if (flags & hook) return "hook";
2661 if (flags & kbd_hook) return "kbd_hook";
2662 if (flags & winevent_hook) return "winevent_hook";
2663 return "msg";
2664}
2665
2667{
2668 if (expected->flags & optional) return TRUE;
2669
2670 if ((expected->flags & winevent_hook) && !hEvent_hook) return TRUE;
2671 if ((expected->flags & kbd_hook) && !hKBD_hook) return TRUE;
2672 if ((expected->flags & hook) && !hCBT_hook) return TRUE;
2673
2674 if ((expected->flags & msg_todo) && !strcmp(winetest_platform, "wine")) return TRUE;
2675
2676 if ((expected->flags & wine_only) && strcmp(winetest_platform, "wine")) return TRUE;
2677
2678 return FALSE;
2679}
2680
2681static BOOL messages_equal(const struct message *expected, const struct recvd_message *actual,
2682 BOOL expect_equal, const char* file, int line)
2683{
2684 int todo = (expected->flags & msg_todo) != 0;
2685 int msg_wine_only = (expected->flags & wine_only) != 0;
2686 const int message_type_flags = hook|winevent_hook|kbd_hook;
2687 static int todo_reported;
2688
2690 expect_equal = FALSE;
2691
2692 if (msg_wine_only && strcmp(winetest_platform, "wine"))
2693 {
2694 /* Ignore Wine-only message records on Windows. */
2695 return FALSE;
2696 }
2697
2698 if (!expected->message || !actual->message) {
2699 if (expect_equal && (!todo || !todo_reported++))
2700 todo_wine_if(todo || msg_wine_only)
2701 ok_( file, line) (msg_wine_only, "the msg sequence is not complete: expected %s %04x - actual %s %04x\n",
2702 message_type_name(expected->flags), expected->message, message_type_name(actual->flags), actual->message);
2703 return FALSE;
2704 }
2705
2706 if (expected->message != actual->message ||
2707 (expected->flags & message_type_flags) != (actual->flags & message_type_flags))
2708 {
2709 if (expect_equal && (!todo || !todo_reported++))
2710 todo_wine_if(todo || msg_wine_only)
2711 ok_( file, line) (msg_wine_only, "the %s 0x%04x was expected, but got %s 0x%04x instead\n",
2712 message_type_name(expected->flags), expected->message, message_type_name(actual->flags), actual->message);
2713 return FALSE;
2714 }
2715
2716 if (expected->flags & optional)
2717 {
2718 /* If a message can be sent in 2 different ways at the same time, we may need to treat
2719 * them as unequal so that the optional message can be properly skipped. */
2720 if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) {
2721 /* don't match messages if their defwinproc status differs */
2722 return FALSE;
2723 }
2724 }
2725
2726 if (expect_equal)
2727 todo_wine_if(todo || msg_wine_only)
2728 ok_( file, line) (!msg_wine_only, "got %s 0x%04x as expected\n",
2729 message_type_name(expected->flags), expected->message);
2730
2731 return TRUE;
2732}
2733
2734static BOOL sequence_contains_message(const struct message *expected, const struct recvd_message *actual)
2735{
2736 while (expected->message)
2737 {
2738 if (messages_equal(expected, actual, FALSE, __FILE__, __LINE__))
2739 return TRUE;
2740 expected++;
2741 }
2742 return FALSE;
2743}
2744
2745static void dump_sequence(const struct message *expected, const char *context, const char *file, int line)
2746{
2747 const struct recvd_message *actual = sequence;
2748 unsigned int count = 0;
2749
2750 trace_(file, line)("Failed sequence %s:\n", context );
2751 while (expected->message && actual->message)
2752 {
2753 if (actual->output[0])
2754 {
2755 trace_(file, line)( " %u: expected: %s %04x - actual: %s\n",
2756 count, message_type_name(expected->flags), expected->message, actual->output );
2757 }
2758
2759 if (messages_equal(expected, actual, FALSE, file, line))
2760 {
2761 expected++;
2762 actual++;
2763 count++;
2764 }
2766 {
2767 expected++;
2768 count++;
2769 }
2770 else
2771 {
2772 actual++;
2773 }
2774 }
2775
2776 /* optional trailing messages */
2777 while (can_skip_message(expected))
2778 {
2779 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message );
2780 expected++;
2781 count++;
2782 }
2783
2784 if (expected->message)
2785 {
2786 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message );
2787 return;
2788 }
2789
2790 while (actual->message && actual->output[0])
2791 {
2792 trace_(file, line)( " %u: expected: nothing - actual: %s\n", count, actual->output );
2793 actual++;
2794 count++;
2795 }
2796}
2797
2798#define ok_sequence( exp, contx, todo) \
2799 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2800
2801
2802static void ok_sequence_(const struct message *expected_list, const char *context, BOOL todo,
2803 const char *file, int line)
2804{
2805 static const struct recvd_message end_of_sequence;
2806 const struct message *expected = expected_list;
2807 const struct recvd_message *actual;
2808 int failcount = 0, dump = 0;
2809 unsigned int count = 0;
2810 BOOL is_wine = !strcmp(winetest_platform, "wine");
2811
2812 add_message(&end_of_sequence);
2813
2814 actual = sequence;
2815
2817
2818 while (expected->message && actual->message)
2819 {
2820 if (messages_equal(expected, actual, !todo, file, line))
2821 {
2822 if (expected->flags & wparam)
2823 {
2824 if (((expected->wParam ^ actual->wParam) & ~expected->wp_mask) && todo)
2825 {
2826 todo_wine {
2827 failcount ++;
2828 dump++;
2829 ok_( file, line) (FALSE,
2830 "in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2831 expected->message, expected->wParam, actual->wParam);
2832 }
2833 if (is_wine) goto done;
2834 }
2835 else
2836 {
2837 ok_( file, line)( ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) == 0,
2838 "in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2839 expected->message, expected->wParam, actual->wParam);
2840 if ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) dump++;
2841 }
2842
2843 }
2844 if (expected->flags & lparam)
2845 {
2846 if (((expected->lParam ^ actual->lParam) & ~expected->lp_mask) && todo)
2847 {
2848 todo_wine {
2849 failcount ++;
2850 dump++;
2851 ok_( file, line) (FALSE,
2852 "in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2853 expected->message, expected->lParam, actual->lParam);
2854 }
2855 if (is_wine) goto done;
2856 }
2857 else
2858 {
2859 ok_( file, line)(((expected->lParam ^ actual->lParam) & ~expected->lp_mask) == 0,
2860 "in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2861 expected->message, expected->lParam, actual->lParam);
2862 if ((expected->lParam ^ actual->lParam) & ~expected->lp_mask) dump++;
2863 }
2864 }
2865 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo)
2866 {
2867 todo_wine {
2868 failcount ++;
2869 dump++;
2870 ok_( file, line) (FALSE,
2871 "the msg 0x%04x should %shave been sent by DefWindowProc\n",
2872 expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
2873 }
2874 if (is_wine) goto done;
2875 }
2876 else
2877 {
2878 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
2879 "the msg 0x%04x should %shave been sent by DefWindowProc\n",
2880 expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
2881 if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++;
2882 }
2883
2884 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
2885 "the msg 0x%04x should %shave been sent by BeginPaint\n",
2886 expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
2887 if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++;
2888
2889 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
2890 "the msg 0x%04x should have been %s\n",
2891 expected->message, (expected->flags & posted) ? "posted" : "sent");
2892 if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++;
2893
2894 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
2895 "the msg 0x%04x was expected in %s\n",
2896 expected->message, (expected->flags & parent) ? "parent" : "child");
2897 if ((expected->flags & parent) != (actual->flags & parent)) dump++;
2898
2899 expected++;
2900 count++;
2901 actual++;
2902 }
2903 /*
2904 * silently drop hook messages if there is no support for them
2905 */
2906 else if (can_skip_message(expected))
2907 {
2908 expected++;
2909 count++;
2910 }
2911 else if (todo)
2912 {
2914 failcount++;
2915 dump++;
2916 goto done;
2917 }
2918 else if (sequence_contains_message(expected, actual))
2919 {
2920 dump++;
2921 expected++;
2922 count++;
2923 }
2924 else
2925 {
2926 dump++;
2927 actual++;
2928 }
2929
2932 }
2933
2934 /* skip all optional trailing messages */
2935 while (can_skip_message(expected))
2936 {
2937 messages_equal(expected, actual, TRUE, file, line); /* check for message todo's */
2938 expected++;
2939 }
2940
2941 if (todo)
2942 {
2943 todo_wine {
2944 if (expected->message || actual->message) {
2945 failcount++;
2946 dump++;
2947 messages_equal(expected, actual, TRUE, file, line);
2948 }
2949 }
2950 if (is_wine && !failcount) /* succeeded yet marked todo */
2951 todo_wine {
2952 dump++;
2953 ok_( file, line)( TRUE, "marked \"todo_wine\" but succeeds\n");
2954 }
2955 }
2956 else
2957 {
2958 if (expected->message || actual->message)
2959 {
2960 dump++;
2961 messages_equal(expected, actual, TRUE, file, line);
2962 }
2963 }
2964
2965done:
2967 if (dump && (!is_wine || winetest_debug > 1)) dump_sequence(expected_list, context, file, line);
2969}
2970
2971#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
2972
2973/******************************** MDI test **********************************/
2974
2975/* CreateWindow for MDI frame window, initially visible */
2976static const struct message WmCreateMDIframeSeq[] = {
2977 { HCBT_CREATEWND, hook },
2979 { WM_NCCREATE, sent },
2980 { WM_NCCALCSIZE, sent|wparam, 0 },
2981 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win8+. */
2982 { WM_CREATE, sent },
2983 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2984 { WM_NOTIFYFORMAT, sent|optional },
2985 { WM_QUERYUISTATE, sent|optional },
2990 { WM_SHOWWINDOW, sent|wparam, 1 },
2992 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2993 { HCBT_ACTIVATE, hook },
2994 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
2997 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, /* Win9x doesn't send it */
2998 { WM_NCACTIVATE, sent },
3000 { WM_ACTIVATE, sent|wparam, 1 },
3002 { HCBT_SETFOCUS, hook },
3005 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3007 /* Win9x adds SWP_NOZORDER below */
3009 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
3010 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win8+. */
3012 { WM_MOVE, sent },
3013 { 0 }
3014};
3015/* DestroyWindow for MDI frame window, initially visible */
3016static const struct message WmDestroyMDIframeSeq[] = {
3017 { HCBT_DESTROYWND, hook },
3018 { 0x0090, sent|optional },
3020 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3021 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
3023 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */
3024 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
3025 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
3026 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|msg_todo, OBJID_CARET, 0 },
3027 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
3028 { WM_DESTROY, sent },
3029 { WM_NCDESTROY, sent },
3030 { 0 }
3031};
3032/* CreateWindow for MDI client window, initially visible */
3033static const struct message WmCreateMDIclientSeq[] = {
3034 { HCBT_CREATEWND, hook },
3035 { WM_NCCREATE, sent },
3036 { WM_NCCALCSIZE, sent|wparam, 0 },
3037 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
3038 { WM_CREATE, sent },
3039 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
3040 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
3042 { WM_MOVE, sent },
3043 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
3044 { WM_SHOWWINDOW, sent|wparam, 1 },
3046 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3048 { 0 }
3049};
3050/* ShowWindow(SW_SHOW) for MDI client window */
3051static const struct message WmShowMDIclientSeq[] = {
3052 { WM_SHOWWINDOW, sent|wparam, 1 },
3054 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3056 { 0 }
3057};
3058/* ShowWindow(SW_HIDE) for MDI client window */
3059static const struct message WmHideMDIclientSeq[] = {
3060 { WM_SHOWWINDOW, sent|wparam, 0 },
3062 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */
3063 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */
3065 { 0 }
3066};
3067/* DestroyWindow for MDI client window, initially visible */
3068static const struct message WmDestroyMDIclientSeq[] = {
3069 { HCBT_DESTROYWND, hook },
3070 { 0x0090, sent|optional },
3071 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
3072 { WM_SHOWWINDOW, sent|wparam, 0 },
3074 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3076 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
3077 { WM_DESTROY, sent },
3078 { WM_NCDESTROY, sent },
3079 { 0 }
3080};
3081/* CreateWindow for MDI child window, initially visible */
3082static const struct message WmCreateMDIchildVisibleSeq[] = {
3083 { HCBT_CREATEWND, hook },
3084 { WM_NCCREATE, sent },
3085 { WM_NCCALCSIZE, sent|wparam, 0 },
3086 { WM_CREATE, sent },
3087 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
3089 { WM_MOVE, sent },
3090 /* Win2k sends wparam set to
3091 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3092 * while Win9x doesn't bother to set child window id according to
3093 * CLIENTCREATESTRUCT.idFirstChild
3094 */
3095 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3096 { WM_SHOWWINDOW, sent|wparam, 1 },
3098 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3100 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
3104
3105 /* Win9x: message sequence terminates here. */
3106
3108 { HCBT_SETFOCUS, hook }, /* in MDI client */
3109 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3110 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
3111 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3112 { WM_SETFOCUS, sent }, /* in MDI client */
3113 { HCBT_SETFOCUS, hook },
3114 { WM_KILLFOCUS, sent }, /* in MDI client */
3115 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3117 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3120 { 0 }
3121};
3122/* WM_CHILDACTIVATE sent to disabled window */
3125 { 0 }
3126};
3127/* WM_CHILDACTIVATE sent to enabled window */
3128static const struct message WmChildActivateWindowSeq[] = {
3133 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
3136 { HCBT_SETFOCUS, hook },
3138 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3139 { WM_SETFOCUS, sent },
3140 { HCBT_SETFOCUS, hook },
3141 { WM_KILLFOCUS, sent },
3142 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3145 { 0 }
3146};
3147/* CreateWindow for MDI child window with invisible parent */
3149 { HCBT_CREATEWND, hook },
3151 { WM_NCCREATE, sent },
3152 { WM_NCCALCSIZE, sent|wparam, 0 },
3153 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
3154 { WM_CREATE, sent },
3155 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
3157 { WM_MOVE, sent },
3158 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3159 { WM_SHOWWINDOW, sent|wparam, 1 },
3160 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
3164
3165 /* Win9x: message sequence terminates here. */
3166
3168 { HCBT_SETFOCUS, hook }, /* in MDI client */
3169 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3170 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
3171 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3172 { WM_SETFOCUS, sent }, /* in MDI client */
3173 { HCBT_SETFOCUS, hook },
3174 { WM_KILLFOCUS, sent }, /* in MDI client */
3175 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3177 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3180 { 0 }
3181};
3182/* DestroyWindow for MDI child window, initially visible */
3183static const struct message WmDestroyMDIchildVisibleSeq[] = {
3184 { HCBT_DESTROYWND, hook },
3185 /* Win2k sends wparam set to
3186 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3187 * while Win9x doesn't bother to set child window id according to
3188 * CLIENTCREATESTRUCT.idFirstChild
3189 */
3190 { 0x0090, sent|optional },
3191 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
3192 { WM_SHOWWINDOW, sent|wparam, 0 },
3194 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3197
3198 /* { WM_DESTROY, sent }
3199 * Win9x: message sequence terminates here.
3200 */
3201
3202 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
3203 { WM_KILLFOCUS, sent },
3205 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3206 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3207 { WM_SETFOCUS, sent }, /* in MDI client */
3208
3209 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
3210 { WM_KILLFOCUS, sent }, /* in MDI client */
3211 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3213 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3214 { WM_SETFOCUS, sent }, /* in MDI client */
3215
3216 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
3217
3218 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
3219 { WM_KILLFOCUS, sent },
3221 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3222 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3223 { WM_SETFOCUS, sent }, /* in MDI client */
3224
3225 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
3226 { WM_KILLFOCUS, sent }, /* in MDI client */
3227 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3229 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3230 { WM_SETFOCUS, sent }, /* in MDI client */
3231
3232 { WM_DESTROY, sent },
3233
3234 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
3235 { WM_KILLFOCUS, sent },
3237 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3238 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3239 { WM_SETFOCUS, sent }, /* in MDI client */
3240
3241 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
3242 { WM_KILLFOCUS, sent }, /* in MDI client */
3243 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3245 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3246 { WM_SETFOCUS, sent }, /* in MDI client */
3247
3248 { WM_NCDESTROY, sent },
3249 { 0 }
3250};
3251/* CreateWindow for MDI child window, initially invisible */
3252static const struct message WmCreateMDIchildInvisibleSeq[] = {
3253 { HCBT_CREATEWND, hook },
3254 { WM_NCCREATE, sent },
3255 { WM_NCCALCSIZE, sent|wparam, 0 },
3256 { WM_CREATE, sent },
3257 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
3259 { WM_MOVE, sent },
3260 /* Win2k sends wparam set to
3261 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3262 * while Win9x doesn't bother to set child window id according to
3263 * CLIENTCREATESTRUCT.idFirstChild
3264 */
3265 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3266 { 0 }
3267};
3268/* DestroyWindow for MDI child window, initially invisible */
3270 { HCBT_DESTROYWND, hook },
3271 /* Win2k sends wparam set to
3272 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3273 * while Win9x doesn't bother to set child window id according to
3274 * CLIENTCREATESTRUCT.idFirstChild
3275 */
3276 { 0x0090, sent|optional },
3277 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
3278 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
3279 { WM_DESTROY, sent },
3280 { WM_NCDESTROY, sent },
3281 { 0 }
3282};
3283/* CreateWindow for the 1st MDI child window, initially visible and maximized */
3285 { HCBT_CREATEWND, hook },
3286 { WM_NCCREATE, sent },
3287 { WM_NCCALCSIZE, sent|wparam, 0 },
3288 { WM_CREATE, sent },
3289 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
3291 { WM_MOVE, sent },
3295 { WM_NCCALCSIZE, sent|wparam, 1 },
3298 /* in MDI frame */
3300 { WM_NCCALCSIZE, sent|wparam, 1 },
3302 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3303 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3304 /* Win2k sends wparam set to
3305 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3306 * while Win9x doesn't bother to set child window id according to
3307 * CLIENTCREATESTRUCT.idFirstChild
3308 */
3309 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3310 { WM_SHOWWINDOW, sent|wparam, 1 },
3312 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3314 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
3318
3319 /* Win9x: message sequence terminates here. */
3320
3322 { HCBT_SETFOCUS, hook|optional }, /* in MDI client */
3323 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3324 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
3325 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3326 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3328 { WM_KILLFOCUS, sent|optional }, /* in MDI client */
3329 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3331 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3334 /* in MDI frame */
3336 { WM_NCCALCSIZE, sent|wparam, 1 },
3338 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3339 { 0 }
3340};
3341/* CreateWindow for the 2nd MDI child window, initially visible and maximized */
3343 /* restore the 1st MDI child */
3344 { WM_SETREDRAW, sent|wparam, 0 },
3347 { WM_NCCALCSIZE, sent|wparam, 1 },
3351 /* in MDI frame */
3353 { WM_NCCALCSIZE, sent|wparam, 1 },
3355 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3356 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3357 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
3358 /* create the 2nd MDI child */
3359 { HCBT_CREATEWND, hook },
3360 { WM_NCCREATE, sent },
3361 { WM_NCCALCSIZE, sent|wparam, 0 },
3362 { WM_CREATE, sent },
3363 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
3365 { WM_MOVE, sent },
3369 { WM_NCCALCSIZE, sent|wparam, 1 },
3370 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
3373 /* in MDI frame */
3375 { WM_NCCALCSIZE, sent|wparam, 1 },
3377 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3378 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3379 /* Win2k sends wparam set to
3380 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3381 * while Win9x doesn't bother to set child window id according to
3382 * CLIENTCREATESTRUCT.idFirstChild
3383 */
3384 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3385 { WM_SHOWWINDOW, sent|wparam, 1 },
3387 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3389 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
3392
3393 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
3394 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
3395
3397
3398 /* Win9x: message sequence terminates here. */
3399
3401 { HCBT_SETFOCUS, hook },
3402 { WM_KILLFOCUS, sent|defwinproc|optional }, /* in the 1st MDI child */
3403 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
3404 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3405 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3406 { WM_SETFOCUS, sent }, /* in MDI client */
3407 { HCBT_SETFOCUS, hook },
3408 { WM_KILLFOCUS, sent }, /* in MDI client */
3409 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3411 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3413
3415 /* in MDI frame */
3417 { WM_NCCALCSIZE, sent|wparam, 1 },
3419 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3420 { 0 }
3421};
3422/* WM_MDICREATE MDI child window, initially visible and maximized */
3424 { WM_MDICREATE, sent },
3425 { HCBT_CREATEWND, hook },
3426 { WM_NCCREATE, sent },
3427 { WM_NCCALCSIZE, sent|wparam, 0 },
3428 { WM_CREATE, sent },
3429 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
3431 { WM_MOVE, sent },
3435 { WM_NCCALCSIZE, sent|wparam, 1 },
3438
3439 /* in MDI frame */
3441 { WM_NCCALCSIZE, sent|wparam, 1 },
3443 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3444 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3445
3446 /* Win2k sends wparam set to
3447 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3448 * while Win9x doesn't bother to set child window id according to
3449 * CLIENTCREATESTRUCT.idFirstChild
3450 */
3451 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3452 { WM_SHOWWINDOW, sent|wparam, 1 },
3454
3455 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3456
3458 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
3460
3463
3464 /* Win9x: message sequence terminates here. */
3465
3467 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3468 { HCBT_SETFOCUS, hook }, /* in MDI client */
3469 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3471 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
3472 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3474 { WM_KILLFOCUS, sent }, /* in MDI client */
3475 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3477 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3479
3481
3482 /* in MDI child */
3484 { WM_NCCALCSIZE, sent|wparam, 1 },
3486 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
3487
3488 /* in MDI frame */
3490 { WM_NCCALCSIZE, sent|wparam, 1 },
3491 { 0x0093, sent|defwinproc|optional },
3492 { 0x0093, sent|defwinproc|optional },
3493 { 0x0093, sent|defwinproc|optional },
3495 { WM_MOVE, sent|defwinproc },
3497
3498 /* in MDI client */
3500 { WM_NCCALCSIZE, sent|wparam, 1 },
3503
3504 /* in MDI child */
3506 { WM_NCCALCSIZE, sent|wparam, 1 },
3507 { 0x0093, sent|optional },
3510
3511 { 0x0093, sent|optional },
3512 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3513 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client, not sent on Win7. */
3514 { 0x0093, sent|optional }, /* Win8+ sends an extra. */
3515 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */
3516 { 0x0093, sent|defwinproc|optional },
3517 { 0x0093, sent|defwinproc|optional },
3518 { 0x0093, sent|defwinproc|optional },
3519 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3520 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
3521
3522 { 0 }
3523};
3524/* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3526 { HCBT_CREATEWND, hook },
3528 { WM_NCCREATE, sent },
3529 { WM_NCCALCSIZE, sent|wparam, 0 },
3530 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Not sent on Win8+. */
3531 { WM_CREATE, sent },
3532 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
3535 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI frame */
3537 { WM_MOVE, sent },
3542 { WM_NCCALCSIZE, sent|wparam, 1 },
3544 { WM_MOVE, sent|defwinproc },
3546 /* in MDI frame */
3548 { WM_NCCALCSIZE, sent|wparam, 1 },
3550 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3551 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI child */
3552 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3553 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3554 /* Win2k sends wparam set to
3555 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3556 * while Win9x doesn't bother to set child window id according to
3557 * CLIENTCREATESTRUCT.idFirstChild
3558 */
3559 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3560 { 0 }
3561};
3562/* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3565 { HCBT_SYSCOMMAND, hook },
3567 { WM_MDIDESTROY, sent }, /* in MDI client */
3568
3569 /* bring the 1st MDI child to top */
3570 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
3572
3573 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
3574
3575 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
3576 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
3577 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
3578
3579 /* maximize the 1st MDI child */
3587
3588 /* restore the 2nd MDI child */
3593
3594 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3595
3598
3599 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3600
3602 /* in MDI frame */
3604 { WM_NCCALCSIZE, sent|wparam, 1 },
3606 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3607 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3608
3609 /* bring the 1st MDI child to top */
3612 { HCBT_SETFOCUS, hook },
3615 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3616 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3617 { WM_SETFOCUS, sent }, /* in MDI client */
3618 { HCBT_SETFOCUS, hook },
3619 { WM_KILLFOCUS, sent }, /* in MDI client */
3620 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3622 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3626
3627 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3628 { WM_SHOWWINDOW, sent|wparam, 1 },
3630 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3633
3634 { HCBT_DESTROYWND, hook },
3635 /* Win2k sends wparam set to
3636 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3637 * while Win9x doesn't bother to set child window id according to
3638 * CLIENTCREATESTRUCT.idFirstChild
3639 */
3640 { 0x0090, sent|defwinproc|optional },
3641 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
3644 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3647
3648 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
3651 { 0 }
3652};
3653/* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3655 { WM_MDIDESTROY, sent }, /* in MDI client */
3656 { WM_SHOWWINDOW, sent|wparam, 0 },
3658 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3661
3662 { HCBT_SETFOCUS, hook },
3663 { WM_KILLFOCUS, sent },
3665 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3666 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3667 { WM_SETFOCUS, sent }, /* in MDI client */
3668 { HCBT_SETFOCUS, hook },
3669 { WM_KILLFOCUS, sent }, /* in MDI client */
3670 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3672 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3673 { WM_SETFOCUS, sent },
3674
3675 /* in MDI child */
3677 { WM_NCCALCSIZE, sent|wparam, 1 },
3679 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3680
3681 /* in MDI frame */
3683 { WM_NCCALCSIZE, sent|wparam, 1 },
3684 { 0x0093, sent|defwinproc|optional },
3685 { 0x0093, sent|defwinproc|optional },
3687 { WM_MOVE, sent|defwinproc },
3689
3690 /* in MDI client */
3692 { WM_NCCALCSIZE, sent|wparam, 1 },
3695
3696 /* in MDI child */
3698 { WM_NCCALCSIZE, sent|wparam, 1 },
3701
3702 /* in MDI child */
3706 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3707
3708 /* in MDI frame */
3711 { 0x0093, sent|defwinproc|optional },
3712 { 0x0093, sent|defwinproc|optional },
3713 { 0x0093, sent|defwinproc|optional },
3715 { WM_MOVE, sent|defwinproc },
3717
3718 /* in MDI client */
3720 { WM_NCCALCSIZE, sent|wparam, 1 },
3723
3724 /* in MDI child */
3729 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3730 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI client */
3731
3732 { 0x0093, sent|defwinproc|optional },
3733 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */
3734 { 0x0093, sent|defwinproc|optional },
3735 { 0x0093, sent|defwinproc|optional },
3736 { 0x0093, sent|defwinproc|optional },
3737 { 0x0093, sent|optional },
3738
3739 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3740 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3741 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI client */
3742 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame */
3743 { 0x0093, sent|optional }, /* Win8+ sends an extra. */
3744 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
3745
3746 /* in MDI frame */
3749 { 0x0093, sent|defwinproc|optional },
3750 { 0x0093, sent|defwinproc|optional },
3751 { 0x0093, sent|defwinproc|optional },
3753 { 0x0093, sent|optional }, /* Win8+ sends an extra. */
3754 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3755 { 0x0093, sent|optional },
3756
3757 { WM_NCACTIVATE, sent|wparam, 0 },
3758 { WM_MDIACTIVATE, sent },
3759
3762 { WM_NCCALCSIZE, sent|wparam, 1 },
3763
3764 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3765
3769
3770 /* in MDI child */
3774 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3775
3776 /* in MDI frame */
3778 { WM_NCCALCSIZE, sent|wparam, 1 },
3780 { WM_MOVE, sent|defwinproc },
3782
3783 /* in MDI client */
3785 { WM_NCCALCSIZE, sent|wparam, 1 },
3788 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI child */
3789 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
3790 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI client */
3791 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 }, /* MDI frame */
3792 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
3793
3794 { HCBT_SETFOCUS, hook },
3795 { WM_KILLFOCUS, sent },
3797 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3798 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3799 { WM_SETFOCUS, sent }, /* in MDI client */
3800
3801 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
3802
3803 { HCBT_DESTROYWND, hook },
3804 /* Win2k sends wparam set to
3805 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3806 * while Win9x doesn't bother to set child window id according to
3807 * CLIENTCREATESTRUCT.idFirstChild
3808 */
3809 { 0x0090, sent|optional },
3810 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
3811
3812 { WM_SHOWWINDOW, sent|wparam, 0 },
3814 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3817
3818 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
3819 { WM_DESTROY, sent },
3820 { WM_NCDESTROY, sent },
3821 { 0 }
3822};
3823/* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3828 { WM_NCCALCSIZE, sent|wparam, 1 },
3829 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3831
3835 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3836 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3837 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3839 { WM_KILLFOCUS, sent|optional }, /* in MDI client */
3840 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3842 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3847 /* in MDI frame */
3849 { WM_NCCALCSIZE, sent|wparam, 1 },
3851 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3852 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3853 { 0 }
3854};
3855/* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3861 { WM_NCCALCSIZE, sent|wparam, 1 },
3862 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3864
3868 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3869 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3870 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3872 { WM_KILLFOCUS, sent|optional }, /* in MDI client */
3873 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3875 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3879 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child, not sent on Win8+. */
3881 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* w1064v1809. */
3882 { 0 }
3883};
3884/* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3886 { WM_MDIMAXIMIZE, sent }, /* in MDI client */
3891 { WM_NCCALCSIZE, sent|wparam, 1 },
3892 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP doesn't send it */
3895 { WM_MOVE, sent|defwinproc },
3897
3902 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3903 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */
3904 /* in MDI frame */
3906 { WM_NCCALCSIZE, sent|wparam, 1 },
3907 { 0x0093, sent|defwinproc|optional },
3908 { 0x0094, sent|defwinproc|optional },
3909 { 0x0094, sent|defwinproc|optional },
3910 { 0x0094, sent|defwinproc|optional },
3911 { 0x0094, sent|defwinproc|optional },
3912 { 0x0093, sent|defwinproc|optional },
3913 { 0x0093, sent|defwinproc|optional },
3914 { 0x0091, sent|defwinproc|optional },
3915 { 0x0092, sent|defwinproc|optional },
3916 { 0x0092, sent|defwinproc|optional },
3917 { 0x0092, sent|defwinproc|optional },
3918 { 0x0092, sent|defwinproc|optional },
3920 { WM_MOVE, sent|defwinproc },
3922 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame win2000 */
3923 /* in MDI client */
3925 { WM_NCCALCSIZE, sent|wparam, 1 },
3928 /* in MDI child */
3934 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child win2000 */
3936 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3937 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3938 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */
3939 /* in MDI frame */
3940 { 0x0093, sent|optional },
3942 { 0x0093, sent|defwinproc|optional },
3943 { 0x0093, sent|defwinproc|optional },
3944 { 0x0093, sent|defwinproc|optional },
3945 { 0x0091, sent|defwinproc|optional },
3946 { 0x0092, sent|defwinproc|optional },
3947 { 0x0092, sent|defwinproc|optional },
3948 { 0x0092, sent|defwinproc|optional },
3949 { 0x0092, sent|defwinproc|optional },
3950 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */
3951 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */
3952 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3953 { 0 }
3954};
3955/* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3956static const struct message WmMaximizeMDIchildVisibleSeq[] = {
3960 { WM_NCCALCSIZE, sent|wparam, 1 },
3964 /* in MDI frame */
3966 { WM_NCCALCSIZE, sent|wparam, 1 },
3968 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3969 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3970 { 0 }
3971};
3972/* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3973static const struct message WmRestoreMDIchildVisibleSeq[] = {
3976 { WM_NCCALCSIZE, sent|wparam, 1 },
3980 /* in MDI frame */
3982 { WM_NCCALCSIZE, sent|wparam, 1 },
3984 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3985 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3986 { 0 }
3987};
3988/* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3991 { WM_QUERYOPEN, sent|wparam|lparam, 0, 0 },
3993 { WM_NCCALCSIZE, sent|wparam, 1 },
3996 { WM_MOVE, sent|defwinproc },
3998 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3999 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
4000 { HCBT_SETFOCUS, hook },
4003 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
4004 { WM_SETFOCUS, sent },
4005 { 0 }
4006};
4007/* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
4008static const struct message WmMinimizeMDIchildVisibleSeq[] = {
4011 { WM_NCCALCSIZE, sent|wparam, 1 },
4013 { WM_MOVE, sent|defwinproc },
4016 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
4017 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
4018 { 0 }
4019};
4020/* ShowWindow(SW_RESTORE) for a not visible MDI child window */
4024 { WM_NCCALCSIZE, sent|wparam, 1 },
4025 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
4029 /* in MDI frame */
4031 { WM_NCCALCSIZE, sent|wparam, 1 },
4033 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
4034 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
4035 { 0 }
4036};
4037
4040
4042{
4043 struct recvd_message msg;
4044
4045 /* do not log painting messages */
4046 if (message != WM_PAINT &&
4047 message != WM_NCPAINT &&
4048 message != WM_SYNCPAINT &&
4050 message != WM_NCHITTEST &&
4051 message != WM_GETTEXT &&
4054 {
4055 msg.hwnd = hwnd;
4056 msg.message = message;
4057 msg.flags = sent|wparam|lparam;
4058 msg.wParam = wParam;
4059 msg.lParam = lParam;
4060 msg.descr = "mdi client";
4061 add_message(&msg);
4062 }
4063
4065}
4066
4068{
4069 static LONG defwndproc_counter = 0;
4070 LRESULT ret;
4071 struct recvd_message msg;
4072
4073 /* do not log painting messages */
4074 if (message != WM_PAINT &&
4075 message != WM_NCPAINT &&
4076 message != WM_SYNCPAINT &&
4078 message != WM_NCHITTEST &&
4079 message != WM_GETTEXT &&
4081 {
4082 switch (message)
4083 {
4084 case WM_MDIACTIVATE:
4085 {
4086 HWND active, client = GetParent(hwnd);
4087
4088 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
4089
4090 if (hwnd == (HWND)lParam) /* if we are being activated */
4091 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
4092 else
4093 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
4094 break;
4095 }
4096 }
4097
4098 msg.hwnd = hwnd;
4099 msg.message = message;
4100 msg.flags = sent|wparam|lparam;
4101 if (defwndproc_counter) msg.flags |= defwinproc;
4102 msg.wParam = wParam;
4103 msg.lParam = lParam;
4104 msg.descr = "mdi child";
4105 add_message(&msg);
4106 }
4107
4108 defwndproc_counter++;
4110 defwndproc_counter--;
4111
4112 return ret;
4113}
4114
4116{
4117 static LONG defwndproc_counter = 0;
4118 LRESULT ret;
4119 struct recvd_message msg;
4120
4121 /* do not log painting messages */
4122 if (message != WM_PAINT &&
4123 message != WM_NCPAINT &&
4124 message != WM_SYNCPAINT &&
4126 message != WM_NCHITTEST &&
4127 message != WM_GETTEXT &&
4129 {
4130 msg.hwnd = hwnd;
4131 msg.message = message;
4132 msg.flags = sent|wparam|lparam;
4133 if (defwndproc_counter) msg.flags |= defwinproc;
4134 msg.wParam = wParam;
4135 msg.lParam = lParam;
4136 msg.descr = "mdi frame";
4137 add_message(&msg);
4138 }
4139
4140 defwndproc_counter++;
4142 defwndproc_counter--;
4143
4144 return ret;
4145}
4146
4147static void mdi_register_classes(void)
4148{
4149 WNDCLASSA cls;
4150 BOOL ret;
4151
4152 cls.style = 0;
4154 cls.cbClsExtra = 0;
4155 cls.cbWndExtra = 0;
4156 cls.hInstance = GetModuleHandleA(0);
4157 cls.hIcon = 0;
4160 cls.lpszMenuName = NULL;
4161 cls.lpszClassName = "MDI_frame_class";
4162 register_class(&cls);
4163
4165 cls.lpszClassName = "MDI_child_class";
4166 register_class(&cls);
4167
4168 ret = GetClassInfoA(0, "MDIClient", &cls);
4169 ok(ret, "Failed to get class info, error %lu.\n", GetLastError());
4171 cls.hInstance = GetModuleHandleA(0);
4173 cls.lpszClassName = "MDI_client_class";
4174 register_class(&cls);
4175}
4176
4177static void test_mdi_messages(void)
4178{
4179 MDICREATESTRUCTA mdi_cs;
4180 CLIENTCREATESTRUCT client_cs;
4181 HWND mdi_frame, mdi_child, mdi_child2, active_child;
4182 BOOL zoomed;
4183 RECT rc;
4184 HMENU hMenu = CreateMenu();
4185 LONG val;
4186
4188
4190
4191 if (winetest_debug > 1) trace("creating MDI frame window\n");
4192 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
4195 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
4196 GetDesktopWindow(), hMenu,
4198 ok(!!mdi_frame, "Failed to create window, error %lu.\n", GetLastError());
4199 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", FALSE);
4200
4201 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4202 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
4203
4204 if (winetest_debug > 1) trace("creating MDI client window\n");
4205 GetClientRect(mdi_frame, &rc);
4206 client_cs.hWindowMenu = 0;
4207 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
4208 mdi_client = CreateWindowExA(0, "MDI_client_class",
4209 NULL,
4211 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
4212 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
4213 ok(!!mdi_client, "Failed to create window, error %lu.\n", GetLastError());
4214 SetWindowLongA(mdi_client, 0, 0xdeadbeef);
4215
4216 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
4217 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4218 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
4219
4220 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4221 ok(!active_child, "wrong active MDI child %p\n", active_child);
4222 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4223
4224 SetFocus(0);
4226
4227 if (winetest_debug > 1) trace("creating invisible MDI child window\n");
4228 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4229 WS_CHILD,
4232 ok(!!mdi_child, "Failed to create window, error %lu.\n", GetLastError());
4233
4235 ShowWindow(mdi_child, SW_SHOWNORMAL);
4236 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
4237
4238 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
4239 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
4240
4241 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4242 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4243
4244 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4245 ok(!active_child, "wrong active MDI child %p\n", active_child);
4246 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4247
4248 ShowWindow(mdi_child, SW_HIDE);
4249 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
4251
4252 ShowWindow(mdi_child, SW_SHOW);
4253 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
4254
4255 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
4256 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
4257
4258 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4259 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4260
4261 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4262 ok(!active_child, "wrong active MDI child %p\n", active_child);
4263 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4264
4265 DestroyWindow(mdi_child);
4267
4268 if (winetest_debug > 1) trace("creating visible MDI child window\n");
4269 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4273 ok(!!mdi_child, "Failed to create window, error %lu.\n", GetLastError());
4274 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE);
4275
4276 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
4277 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
4278
4279 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4280 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
4281
4282 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4283 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4284 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4286
4287 DestroyWindow(mdi_child);
4288 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
4289
4290 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4291 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4292
4293 /* Win2k: MDI client still returns a just destroyed child as active
4294 * Win9x: MDI client returns 0
4295 */
4296 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4297 ok(active_child == mdi_child || /* win2k */
4298 !active_child, /* win9x */
4299 "wrong active MDI child %p\n", active_child);
4300 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4301
4303
4304 if (winetest_debug > 1) trace("creating invisible MDI child window\n");
4305 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4306 WS_CHILD,
4309 ok(!!mdi_child2, "Failed to create window, error %lu.\n", GetLastError());
4310 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
4311
4312 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
4313 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
4314
4315 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4316 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4317
4318 /* Win2k: MDI client still returns a just destroyed child as active
4319 * Win9x: MDI client returns mdi_child2
4320 */
4321 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4322 ok(active_child == mdi_child || /* win2k */
4323 active_child == mdi_child2, /* win9x */
4324 "wrong active MDI child %p\n", active_child);
4325 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4327
4328 ShowWindow(mdi_child2, SW_MAXIMIZE);
4329 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE);
4330
4331 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
4332 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
4333
4334 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4335 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4336 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4338
4339 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4340 ok(GetFocus() == mdi_child2 || /* win2k */
4341 GetFocus() == 0, /* win9x */
4342 "wrong focus window %p\n", GetFocus());
4343
4344 SetFocus(0);
4346
4347 ShowWindow(mdi_child2, SW_HIDE);
4348 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
4349
4350 ShowWindow(mdi_child2, SW_RESTORE);
4351 ok_sequence(WmRestoreMDIchildInvisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE);
4353
4354 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
4355 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
4356
4357 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4358 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4359 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4361
4362 SetFocus(0);
4364
4365 ShowWindow(mdi_child2, SW_HIDE);
4366 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
4367
4368 ShowWindow(mdi_child2, SW_SHOW);
4369 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
4370
4371 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4372 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4373
4374 ShowWindow(mdi_child2, SW_MAXIMIZE);
4375 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE);
4376
4377 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4378 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4379
4380 ShowWindow(mdi_child2, SW_RESTORE);
4381 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE);
4382
4383 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4384 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4385
4386 ShowWindow(mdi_child2, SW_MINIMIZE);
4387 ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", FALSE);
4388
4389 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4390 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4391
4392 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4393 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4394 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4396
4397 ShowWindow(mdi_child2, SW_RESTORE);
4398 ok_sequence(WmRestoreMDIchildVisibleSeq_2, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE);
4399
4400 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4401 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
4402
4403 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4404 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4405 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4407
4408 SetFocus(0);
4410
4411 ShowWindow(mdi_child2, SW_HIDE);
4412 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
4413
4414 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4415 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4416
4417 DestroyWindow(mdi_child2);
4418 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
4419
4420 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4421 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4422
4423 if (winetest_debug > 1) trace("Testing WM_CHILDACTIVATE\n");
4424
4425 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4429
4430 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4434
4435 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4436 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4437 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4438
4440 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0);
4441 ok_sequence(WmChildActivateDisabledWindowSeq, "WM_CHILDACTIVATE sent to disabled window", FALSE);
4442
4443 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4444 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4445 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4447
4448 EnableWindow(mdi_child, TRUE);
4449
4450 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4451 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4452 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4453
4455 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0);
4456 ok_sequence(WmChildActivateWindowSeq, "WM_CHILDACTIVATE sent to enabled window", FALSE);
4457
4458 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4459 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4460 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4462
4463 DestroyWindow(mdi_child);
4464 DestroyWindow(mdi_child2);
4466
4467 /* test for maximized MDI children */
4468 if (winetest_debug > 1) trace("creating maximized visible MDI child window 1\n");
4469 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4473 ok(!!mdi_child, "Failed to create window, error %lu.\n", GetLastError());
4474 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
4475 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
4476
4477 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4478 ok(GetFocus() == mdi_child || /* win2k */
4479 GetFocus() == 0, /* win9x */
4480 "wrong focus window %p\n", GetFocus());
4481
4482 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4483 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4484 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4486
4487 if (winetest_debug > 1) trace("creating maximized visible MDI child window 2\n");
4488 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4492 ok(!!mdi_child2, "Failed to create window, error %lu.\n", GetLastError());
4493 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
4494 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
4495 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
4496
4497 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4498 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
4499
4500 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4501 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4502 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4504
4505 if (winetest_debug > 1) trace("destroying maximized visible MDI child window 2\n");
4506 DestroyWindow(mdi_child2);
4507 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
4508
4509 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
4510
4511 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4512 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4513
4514 /* Win2k: MDI client still returns a just destroyed child as active
4515 * Win9x: MDI client returns 0
4516 */
4517 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4518 ok(active_child == mdi_child2 || /* win2k */
4519 !active_child, /* win9x */
4520 "wrong active MDI child %p\n", active_child);
4522
4523 ShowWindow(mdi_child, SW_MAXIMIZE);
4524 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
4526
4527 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4528 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
4529
4530 if (winetest_debug > 1) trace("re-creating maximized visible MDI child window 2\n");
4531 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4535 ok(!!mdi_child2, "Failed to create window, error %lu.\n", GetLastError());
4536 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
4537 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
4538 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
4539
4540 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4541 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
4542
4543 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4544 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4545 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4547
4548 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
4549 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
4550 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
4551
4552 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
4553 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4554 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
4555
4556 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4557 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4558 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4560
4561 DestroyWindow(mdi_child);
4562 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
4563
4564 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4565 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4566
4567 /* Win2k: MDI client still returns a just destroyed child as active
4568 * Win9x: MDI client returns 0
4569 */
4570 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4571 ok(active_child == mdi_child || /* win2k */
4572 !active_child, /* win9x */
4573 "wrong active MDI child %p\n", active_child);
4575
4576 if (winetest_debug > 1) trace("creating maximized invisible MDI child window\n");
4577 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4581 ok(!!mdi_child2, "Failed to create window, error %lu.\n", GetLastError());
4582#ifdef __REACTOS__
4584#endif
4585 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", FALSE);
4586 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n");
4587 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n");
4588 ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n");
4589
4590 /* Win2k: MDI client still returns a just destroyed child as active
4591 * Win9x: MDI client returns 0
4592 */
4593 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4594 ok(active_child == mdi_child || /* win2k */
4595 !active_child || active_child == mdi_child2, /* win9x */
4596 "wrong active MDI child %p\n", active_child);
4598
4599 if (winetest_debug > 1) trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4600 ShowWindow(mdi_child2, SW_MAXIMIZE);
4601 ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE);
4602 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n");
4603 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
4604 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
4605
4606 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4607 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4608 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4610
4611 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0);
4613
4614 /* end of test for maximized MDI children */
4615 SetFocus(0);
4617 if (winetest_debug > 1) trace("creating maximized visible MDI child window 1(Switch test)\n");
4618 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4622 ok(!!mdi_child, "Failed to create window, error %lu.\n", GetLastError());
4623 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE);
4624 ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n");
4625
4626 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow());
4627 ok(GetFocus() == mdi_child || /* win2k */
4628 GetFocus() == 0, /* win9x */
4629 "wrong focus window %p(Switch test)\n", GetFocus());
4630
4631 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4632 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child);
4633 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed);
4635
4636 if (winetest_debug > 1) trace("creating maximized visible MDI child window 2(Switch test)\n");
4637 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4641 ok(!!mdi_child2, "Failed to create window, error %lu.\n", GetLastError());
4642 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE);
4643
4644 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n");
4645 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n");
4646
4647 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow());
4648 ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus());
4649
4650 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4651 ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child);
4652 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed);
4654
4655 if (winetest_debug > 1) trace("Switch child window.\n");
4657 ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE);
4658 if (winetest_debug > 1) trace("end of test for switch maximized MDI children\n");
4660
4661 /* Prepare for switching test of not maximized MDI children */
4662 ShowWindow( mdi_child, SW_NORMAL );
4663 ok(!IsZoomed(mdi_child), "wrong zoomed state for %p(Switch test)\n", mdi_child);
4664 ok(!IsZoomed(mdi_child2), "wrong zoomed state for %p(Switch test)\n", mdi_child2);
4665 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
4666 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child);
4668
4669 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child2, 0);
4670 ok_sequence(WmSwitchNotMaximizedChild, "Not maximized child did not switch correctly", FALSE);
4671 if (winetest_debug > 1) trace("end of test for switch not maximized MDI children\n");
4673
4676
4677 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0);
4679
4680 SetFocus(0);
4682 /* end of tests for switch maximized/not maximized MDI children */
4683
4684 mdi_cs.szClass = "MDI_child_Class";
4685 mdi_cs.szTitle = "MDI child";
4686 mdi_cs.hOwner = GetModuleHandleA(0);
4687 mdi_cs.x = 0;
4688 mdi_cs.y = 0;
4689 mdi_cs.cx = CW_USEDEFAULT;
4690 mdi_cs.cy = CW_USEDEFAULT;
4692 mdi_cs.lParam = 0;
4693 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
4694 ok(mdi_child != 0, "MDI child creation failed\n");
4695 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
4696
4697 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
4698
4699 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4700 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4701
4702 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
4703 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4704 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
4705
4706 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4707 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4708 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4710
4712 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
4713
4714 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
4715 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4716 ok(!active_child, "wrong active MDI child %p\n", active_child);
4717
4718 SetFocus(0);
4720
4722 ok(val == 0xdeadbeef || broken(val == 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%lx\n", val);
4724 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
4725
4726 /* test maximization of MDI child with invisible parent */
4727 client_cs.hWindowMenu = 0;
4728 mdi_client = CreateWindowA("MDI_client_class",
4729 NULL,
4731 0, 0, 660, 430,
4732 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
4733 ok_sequence(WmCreateMDIclientSeq, "Create MDI client window", FALSE);
4734
4736 ok_sequence(WmHideMDIclientSeq, "Hide MDI client window", FALSE);
4737
4738 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4740 0, 0, 650, 440,
4742 ok_sequence(WmCreateMDIchildInvisibleParentSeq, "Create MDI child window with invisible parent", FALSE);
4743
4744 SendMessageA(mdi_client, WM_MDIMAXIMIZE, (WPARAM) mdi_child, 0);
4745 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq, "Maximize MDI child window with invisible parent", TRUE);
4746 zoomed = IsZoomed(mdi_child);
4747 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4748
4750 ok_sequence(WmShowMDIclientSeq, "Show MDI client window", FALSE);
4751
4752 DestroyWindow(mdi_child);
4753 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible maximized MDI child window", TRUE);
4754
4755 /* end of test for maximization of MDI child with invisible parent */
4756
4758 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
4759
4760 DestroyWindow(mdi_frame);
4761 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
4762}
4763/************************* End of MDI test **********************************/
4764
4766{
4768
4769 flush_events();
4771
4773 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
4774
4775 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
4776 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
4777
4780 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
4781
4782 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4783 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
4784
4785 /* restore original WS_VISIBLE state */
4787
4788 flush_events();
4790}
4791
4793{
4794 struct recvd_message msg;
4795
4796 if (ignore_message( message )) return 0;
4797
4798 switch (message)
4799 {
4800 /* ignore */
4801 case WM_MOUSEMOVE:
4802 case WM_NCMOUSEMOVE:
4803 case WM_NCMOUSELEAVE:
4804 case WM_SETCURSOR:
4805 return 0;
4806 case WM_NCHITTEST:
4807 return HTCLIENT;
4808 }
4809
4810 msg.hwnd = hwnd;
4811 msg.message = message;
4812 msg.flags = sent|wparam|lparam;
4813 msg.wParam = wParam;
4814 msg.lParam = lParam;
4815 msg.descr = "dialog";
4816 add_message(&msg);
4817
4818 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
4819 if (message == WM_TIMER) EndDialog( hwnd, 0 );
4820 return 0;
4821}
4822
4824{
4825 struct recvd_message msg;
4826
4827 if (ignore_message( message )) return 0;
4828
4829 switch (message)
4830 {
4831 /* ignore */
4832 case WM_MOUSEMOVE:
4833 case WM_NCMOUSEMOVE:
4834 case WM_NCMOUSELEAVE:
4835 case WM_SETCURSOR:
4836 return 0;
4837 case WM_NCHITTEST:
4838 return HTCLIENT;
4839 }
4840
4841 msg.hwnd = hwnd;
4842 msg.message = message;
4843 msg.flags = sent|wparam|lparam;
4844 msg.wParam = wParam;
4845 msg.lParam = lParam;
4846 msg.descr = "dialog";
4847 add_message(&msg);
4848
4849 if (message == WM_INITDIALOG) EndDialog( hwnd, 0 );
4850 return 0;
4851}
4852
4853static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
4854{
4855 DWORD style, exstyle;
4856 INT xmin, xmax;
4857 BOOL ret;
4858
4859 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4861 /* do not be confused by WS_DLGFRAME set */
4862 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
4863
4864 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
4865 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
4866
4867 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
4868 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
4869 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
4870 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
4871 else
4872 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
4873
4875 if (set) ok(style & set, "style %08lx should be set\n", set);
4876 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
4877
4878 /* a subsequent call should do nothing */
4879 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
4880 ok( ret, "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
4881 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
4882
4883 xmin = 0xdeadbeef;
4884 xmax = 0xdeadbeef;
4885 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax);
4886 ok( ret, "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
4887 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
4888 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
4889 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
4890}
4891
4892static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
4893{
4894 DWORD style, exstyle;
4895 SCROLLINFO si;
4896 BOOL ret;
4897
4898 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4900 /* do not be confused by WS_DLGFRAME set */
4901 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
4902
4903 if (clear) ok(style & clear, "style %08lx should be set\n", clear);
4904 if (set) ok(!(style & set), "style %08lx should not be set\n", set);
4905
4906 si.cbSize = sizeof(si);
4907 si.fMask = SIF_RANGE;
4908 si.nMin = min;
4909 si.nMax = max;
4910 SetScrollInfo(hwnd, ctl, &si, TRUE);
4911 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
4912 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
4913 else
4914 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
4915
4917 if (set) ok(style & set, "style %08lx should be set\n", set);
4918 if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
4919
4920 /* a subsequent call should do nothing */
4921 SetScrollInfo(hwnd, ctl, &si, TRUE);
4922 if (style & WS_HSCROLL)
4923 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4924 else if (style & WS_VSCROLL)
4925 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4926 else
4927 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4928
4929 si.fMask = SIF_PAGE;
4930 si.nPage = 5;
4931 SetScrollInfo(hwnd, ctl, &si, FALSE);
4932 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4933
4934 si.fMask = SIF_POS;
4935 si.nPos = max - 1;
4936 SetScrollInfo(hwnd, ctl, &si, FALSE);
4937 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4938
4939 si.fMask = SIF_RANGE;
4940 si.nMin = 0xdeadbeef;
4941 si.nMax = 0xdeadbeef;
4942 ret = GetScrollInfo(hwnd, ctl, &si);
4943 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
4944 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
4945 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
4946 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
4947}
4948
4949/* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4951{
4952 SCROLLINFO si;
4953 INT min, max;
4954 BOOL ret;
4955
4956 flush_events();
4958
4959 min = 0xdeadbeef;
4960 max = 0xdeadbeef;
4962 ok( ret, "GetScrollRange error %ld\n", GetLastError());
4963 if (sequence->message != WmGetScrollRangeSeq[0].message)
4964 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
4965 /* values of min and max are undefined */
4967
4968 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE);
4969 ok( ret, "SetScrollRange error %ld\n", GetLastError());
4970 if (sequence->message != WmSetScrollRangeSeq[0].message)
4971 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
4973
4974 min = 0xdeadbeef;
4975 max = 0xdeadbeef;
4977 ok( ret, "GetScrollRange error %ld\n", GetLastError());
4978 if (sequence->message != WmGetScrollRangeSeq[0].message)
4979 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
4980 /* values of min and max are undefined */
4982
4983 si.cbSize = sizeof(si);
4984 si.fMask = SIF_RANGE;
4985 si.nMin = 20;
4986 si.nMax = 160;
4988 if (sequence->message != WmSetScrollRangeSeq[0].message)
4989 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
4991
4992 si.fMask = SIF_PAGE;
4993 si.nPage = 10;
4995 if (sequence->message != WmSetScrollRangeSeq[0].message)
4996 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
4998
4999 si.fMask = SIF_POS;
5000 si.nPos = 20;
5002 if (sequence->message != WmSetScrollRangeSeq[0].message)
5003 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
5005
5006 si.fMask = SIF_RANGE;
5007 si.nMin = 0xdeadbeef;
5008 si.nMax = 0xdeadbeef;
5010 ok( ret, "GetScrollInfo error %ld\n", GetLastError());
5011 if (sequence->message != WmGetScrollInfoSeq[0].message)
5012 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
5013 /* values of min and max are undefined */
5015
5016 /* set WS_HSCROLL */
5017 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
5018 /* clear WS_HSCROLL */
5020
5021 /* set WS_HSCROLL */
5022 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
5023 /* clear WS_HSCROLL */
5025
5026 /* set WS_VSCROLL */
5027 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
5028 /* clear WS_VSCROLL */
5030
5031 /* set WS_VSCROLL */
5032 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
5033 /* clear WS_VSCROLL */
5035}
5036
5037static void test_showwindow(void)
5038{
5039 HWND hwnd, hwnd2, hchild;
5040 RECT rc;
5041
5042 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
5043 100, 100, 200, 200, 0, 0, 0, NULL);
5044 ok (hwnd != 0, "Failed to create overlapped window\n");
5045 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5046 0, 0, 10, 10, hwnd, 0, 0, NULL);
5047 ok (hchild != 0, "Failed to create child\n");
5049
5050 /* ShowWindow( SW_SHOWNA) for invisible top level window */
5051 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
5052 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
5053 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE);
5054
5055 /* ShowWindow( SW_SHOWNA) for now visible top level window */
5056 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
5057 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
5058 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE);
5059 /* back to invisible */
5060 ShowWindow(hchild, SW_HIDE);
5063 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
5064 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
5065 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
5066 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE);
5067 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
5068 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
5070 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
5071 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
5072 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE);
5073 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
5076 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
5077 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
5078 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE);
5079
5080 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
5081 ShowWindow( hchild, SW_HIDE);
5083 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
5084 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
5085 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE);
5086
5087 SetCapture(hchild);
5088 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture());
5089 DestroyWindow(hchild);
5090 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
5091
5094
5095 /* Popup windows */
5096 /* Test 1:
5097 * 1. Create invisible maximized popup window.
5098 * 2. Move and resize it.
5099 * 3. Show it maximized.
5100 */
5101 if (winetest_debug > 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5102 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
5103 100, 100, 200, 200, 0, 0, 0, NULL);
5104 ok (hwnd != 0, "Failed to create popup window\n");
5105 ok(IsZoomed(hwnd), "window should be maximized\n");
5106 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
5107
5108 GetWindowRect(hwnd, &rc);
5111 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc ));
5112 /* Reset window's size & position */
5113 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
5114 ok(IsZoomed(hwnd), "window should be maximized\n");
5116
5117 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5119 ok(IsZoomed(hwnd), "window should be maximized\n");
5120 ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE);
5121
5122 GetWindowRect(hwnd, &rc);
5125 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc ));
5128
5129 /* Test 2:
5130 * 1. Create invisible maximized popup window.
5131 * 2. Show it maximized.
5132 */
5133 if (winetest_debug > 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5134 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
5135 100, 100, 200, 200, 0, 0, 0, NULL);
5136 ok (hwnd != 0, "Failed to create popup window\n");
5137 ok(IsZoomed(hwnd), "window should be maximized\n");
5138 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
5139
5140 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5142 ok(IsZoomed(hwnd), "window should be maximized\n");
5143 ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE);
5146
5147 /* Test 3:
5148 * 1. Create visible maximized popup window.
5149 */
5150 if (winetest_debug > 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
5151 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
5152 100, 100, 200, 200, 0, 0, 0, NULL);
5153 ok (hwnd != 0, "Failed to create popup window\n");
5154 ok(IsZoomed(hwnd), "window should be maximized\n");
5155 ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
5158
5159 /* Test 4:
5160 * 1. Create visible popup window.
5161 * 2. Maximize it.
5162 */
5163 if (winetest_debug > 1) trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
5164 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE,
5165 100, 100, 200, 200, 0, 0, 0, NULL);
5166 ok (hwnd != 0, "Failed to create popup window\n");
5167 ok(!IsZoomed(hwnd), "window should NOT be maximized\n");
5168 ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", FALSE);
5169
5170 if (winetest_debug > 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
5172 ok(IsZoomed(hwnd), "window should be maximized\n");
5173 ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
5176
5177 /* Test 5:
5178 * 1. Restoring a minimized window.
5179 */
5180 hwnd = CreateWindowA("TestWindowClass", "window1", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0);
5181 ok(hwnd != NULL, "Failed to create window\n");
5182
5183 hwnd2 = CreateWindowA("static", "window2", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0);
5184 ok(hwnd2 != NULL, "Failed to create window\n");
5185
5187 SetActiveWindow(hwnd2);
5188 ok(GetActiveWindow() == hwnd2, "Unexpected active window\n");
5189 flush_events();
5192 flush_events();
5194 "ShowWindow(hwnd, SW_RESTORE): minimized overlapped", TRUE);
5195
5197 SetActiveWindow(hwnd2);
5198 ok(GetActiveWindow() == hwnd2, "Unexpected active window\n");
5199 flush_events();
5202 flush_events();
5203#ifdef __REACTOS__
5205#endif
5207 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): minimized overlapped", TRUE);
5208
5209 DestroyWindow(hwnd2);
5212
5213 /* Test 6:
5214 * 1. Restoring a minimized but active window.
5215 */
5216 hwnd = CreateWindowA("TestWindowClass", "parent", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0);
5217 ok(hwnd != NULL, "Failed to create window\n");
5218
5221 ok(GetActiveWindow() == hwnd, "Unexpected active window\n");
5222 flush_events();
5225 flush_events();
5227 "ShowWindow(hwnd, SW_RESTORE): active minimized overlapped", TRUE);
5228
5231 ok(GetActiveWindow() == hwnd, "Unexpected active window\n");
5232 flush_events();
5235 flush_events();
5236#ifdef __REACTOS__
5238#endif
5240 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): active minimized overlapped", TRUE);
5241
5244}
5245
5246static void test_sys_menu(void)
5247{
5248 HWND hwnd;
5249 HMENU hmenu;
5250 UINT state;
5251
5252 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
5253 100, 100, 200, 200, 0, 0, 0, NULL);
5254 ok (hwnd != 0, "Failed to create overlapped window\n");
5255
5257
5258 /* test existing window without CS_NOCLOSE style */
5260 ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
5261
5263 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
5264 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
5265
5267 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
5268
5270 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
5271 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state);
5272
5274 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
5275
5277 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
5278 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
5279
5280 /* test whether removing WS_SYSMENU destroys a system menu */
5285 ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
5286
5288
5289 /* test new window with CS_NOCLOSE style */
5290 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW,
5291 100, 100, 200, 200, 0, 0, 0, NULL);
5292 ok (hwnd != 0, "Failed to create overlapped window\n");
5293
5295 ok(hmenu != 0, "GetSystemMenu error %ld\n", GetLastError());
5296
5298 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state);
5299
5301
5302 /* test new window without WS_SYSMENU style */
5303 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW & ~WS_SYSMENU,
5304 100, 100, 200, 200, 0, 0, 0, NULL);
5305 ok(hwnd != 0, "Failed to create overlapped window\n");
5306
5308 ok(!hmenu, "GetSystemMenu error %ld\n", GetLastError());
5309
5311}
5312
5313/* For shown WS_OVERLAPPEDWINDOW */
5314static const struct message WmSetIcon_1[] = {
5315 { WM_SETICON, sent },
5316 { 0x00AE, sent|defwinproc|optional }, /* XP */
5318 { WM_GETTEXT, sent|defwinproc|optional }, /* XP sends a duplicate */
5319 { 0 }
5320};
5321
5322/* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
5323static const struct message WmSetIcon_2[] = {
5324 { WM_SETICON, sent },
5325 { 0 }
5326};
5327
5328/* Sending undocumented 0x3B message with wparam = 0x8000000b */
5329static const struct message WmInitEndSession[] = {
5330 { 0x003B, sent },
5331 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF },
5332 { 0 }
5333};
5334
5335/* Sending undocumented 0x3B message with wparam = 0x0000000b */
5336static const struct message WmInitEndSession_2[] = {
5337 { 0x003B, sent },
5339 { 0 }
5340};
5341
5342/* Sending undocumented 0x3B message with wparam = 0x80000008 */
5343static const struct message WmInitEndSession_3[] = {
5344 { 0x003B, sent },
5345 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF },
5346 { 0 }
5347};
5348
5349/* Sending undocumented 0x3B message with wparam = 0x00000008 */
5350static const struct message WmInitEndSession_4[] = {
5351 { 0x003B, sent },
5353 { 0 }
5354};
5355
5356/* Sending undocumented 0x3B message with wparam = 0x80000001 */
5357static const struct message WmInitEndSession_5[] = {
5358 { 0x003B, sent },
5359 { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF },
5360 { 0 }
5361};
5362
5363static const struct message WmOptionalPaint[] = {
5364 { WM_PAINT, sent|optional },
5368 { 0 }
5369};
5370
5371static const struct message WmZOrder[] = {
5372 { WM_WINDOWPOSCHANGING, sent|wparam, 0, 0 },
5374 { HCBT_ACTIVATE, hook },
5375 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
5377 { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 },
5381 { WM_ACTIVATEAPP, sent|wparam, 1, 0 },
5382 { WM_NCACTIVATE, sent|lparam, 1, 0 },
5385 { WM_ACTIVATE, sent|wparam|lparam, 1, 0 },
5386 { HCBT_SETFOCUS, hook },
5389 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5394 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
5395 { 0 }
5396};
5397
5399{
5400 /* nothing */
5401}
5402
5404{
5405 DWORD ret;
5406 MSG msg;
5407
5409 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %lx\n", ret);
5410
5411 PostMessageA(hwnd, WM_USER, 0, 0);
5412
5414 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %lx\n", ret);
5415
5416 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5417 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5418
5420 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %lx\n", ret);
5421
5422 PostMessageA(hwnd, WM_USER, 0, 0);
5423
5425 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %lx\n", ret);
5426
5427 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n");
5428 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5429
5430 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
5432 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %lx\n", ret);
5433
5434 PostMessageA(hwnd, WM_USER, 0, 0);
5435
5436 /* new incoming message causes it to become signaled again */
5438 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %lx\n", ret);
5439
5440 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5441 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5442 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5443 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5444
5445 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
5446 PostMessageA( hwnd, WM_USER, 0, 0 );
5447 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n");
5448 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5449
5451 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %lx\n", ret);
5452
5453 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5454 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5455
5456 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
5458 ok(ret, "QueueUserAPC failed %lu\n", GetLastError());
5459
5461 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjectsEx returned %lx\n", ret);
5462
5463 /* but even with MWMO_ALERTABLE window events are preferred */
5464 PostMessageA( hwnd, WM_USER, 0, 0 );
5465
5467 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %lx\n", ret);
5468
5469 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5470 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5471
5472 /* the APC call is still queued */
5474 ok(ret == WAIT_IO_COMPLETION, "MsgWaitForMultipleObjectsEx returned %lx\n", ret);
5475}
5476
5478{
5479 DWORD ret;
5480 MSG msg;
5481 int i;
5482 static const WPARAM wparams[] = {0,
5489 DBT_CONFIGMGPRIVATE, /* 0x7fff */
5490 DBT_DEVICEARRIVAL, /* 0x8000 */
5497
5498 for (i = 0; i < ARRAY_SIZE(wparams); i++)
5499 {
5500 SetLastError(0xdeadbeef);
5501 ret = PostMessageA(hwnd, WM_DEVICECHANGE, wparams[i], 0);
5502 if (wparams[i] & 0x8000)
5503 {
5504 ok(ret == FALSE, "PostMessage returned %ld\n", ret);
5505 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY, "PostMessage error %08lx\n", GetLastError());
5506 }
5507 else
5508 {
5510 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %lx\n", ret);
5511 memset(&msg, 0, sizeof(msg));
5512 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should succeed\n");
5513 ok(msg.message == WM_DEVICECHANGE, "got %04x instead of WM_DEVICECHANGE\n", msg.message);
5514 }
5515 }
5516}
5517
5519{
5520 HWND hwnd = arg;
5521
5522 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
5523 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n");
5524
5525 return 0;
5526}
5527
5529{
5530 HWND hwnd = arg;
5531
5532 /* function will not return if ShowWindow(SW_SHOW) calls SendMessage() */
5533 ok( ShowWindow( hwnd, SW_SHOW ), "ShowWindow(SW_SHOW) expected TRUE\n" ); /* actually it's 24... */
5534
5535 return 0;
5536}
5537
5538/* Helper function to easier test SetWindowPos messages */
5539#define test_msg_setpos( expected_list, flags, todo ) \
5540 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
5541static void test_msg_setpos_(const struct message *expected_list, UINT flags, BOOL todo, const char *file, int line)
5542{
5543 HWND hwnd;
5544
5545 flush_events();
5547 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP,
5548 10, 10, 100, 100, NULL, 0, 0, NULL );
5549 ok (hwnd != 0, "Failed to create popup window\n");
5550 SetWindowPos(hwnd, NULL, 0, 0, 100, 100, flags);
5551 ok_sequence_(expected_list, "SetWindowPos:show_popup_first_show_window", todo, file, line);
5553}
5554
5555/* test if we receive the right sequence of messages */
5556static void test_messages(void)
5557{
5558 DWORD tid;
5559 HANDLE hthread;
5560 HWND hwnd, hparent, hchild;
5561 HWND hchild2, hbutton;
5562 HMENU hmenu;
5563 MSG msg;
5564 LRESULT res;
5565 POINT pos;
5566 BOOL ret;
5567
5569
5570 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
5571 100, 100, 200, 200, 0, 0, 0, NULL);
5572 ok (hwnd != 0, "Failed to create overlapped window\n");
5573 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
5574
5575 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5576 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
5577 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
5578
5579 /* test WM_SETREDRAW on a not visible top level window */
5581
5583 flush_events();
5584 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
5585 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
5586
5587 ok(GetActiveWindow() == hwnd, "window should be active\n");
5588 ok(GetFocus() == hwnd, "window should have input focus\n");
5590 flush_events();
5591 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5592
5593 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5594 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n");
5595 flush_events();
5596 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5597
5598 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5599 hthread = CreateThread( NULL, 0, hide_window_thread, hwnd, 0, &tid );
5600 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
5601 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5602 CloseHandle(hthread);
5603 flush_events();
5604 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5605
5607 flush_events();
5608 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
5609
5610 /* test ShowWindow(SW_SHOW) on a visible window - multi-threaded */
5611 hthread = CreateThread( NULL, 0, show_window_thread, hwnd, 0, &tid );
5612 ok( hthread != NULL, "CreateThread failed, error %ld\n", GetLastError() );
5613 ok( WaitForSingleObject( hthread, INFINITE ) == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
5614 CloseHandle( hthread );
5615 flush_events();
5616 ok_sequence( WmEmptySeq, "ShowWindow(SW_SHOW):overlapped", FALSE );
5617
5619 flush_events();
5620 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5621
5623 flush_events();
5624 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE);
5626
5628 {
5630 flush_events();
5631 ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE);
5633 }
5634
5636 flush_events();
5637 ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE);
5639
5641 {
5643 flush_events();
5644 ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", FALSE);
5646 }
5647
5649 flush_events();
5650 ok_sequence(WmOptionalPaint, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
5651
5653 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
5654 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
5655 ok(GetActiveWindow() == hwnd, "window should still be active\n");
5656
5657 /* test WM_SETREDRAW on a visible top level window */
5659 flush_events();
5661
5662 if (winetest_debug > 1) trace("testing scroll APIs on a visible top level window %p\n", hwnd);
5664
5665 /* test resizing and moving */
5666 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOACTIVATE );
5667 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE );
5668 flush_events();
5670 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE );
5671 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE );
5672 flush_events();
5674 SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE );
5675 ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE );
5676 flush_events();
5678
5679 /* popups don't get WM_GETMINMAXINFO */
5683 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOACTIVATE );
5684 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
5685
5687 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
5688
5689 /* Test if windows are correctly drawn when first shown */
5690
5691 /* Visible, redraw */
5692 flush_events();
5694 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE,
5695 10, 10, 100, 100, NULL, 0, 0, NULL );
5696 ok (hwnd != 0, "Failed to create popup window\n");
5698 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_visible", FALSE);
5700
5701 /* Invisible, show, message */
5702 flush_events();
5704 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP,
5705 10, 10, 100, 100, NULL, 0, 0, NULL );
5706 ok (hwnd != 0, "Failed to create popup window\n");
5708 SendMessageW(hwnd, WM_PAINT, 0, 0);
5709 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_show", FALSE);
5711
5712 /* Invisible, show maximized, redraw */
5713 flush_events();
5715 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP,
5716 10, 10, 100, 100, NULL, 0, 0, NULL );
5717 ok (hwnd != 0, "Failed to create popup window\n");
5720 ok_sequence(WmShowPopupFirstDrawSeq_2, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE);
5722
5723 /* Test SetWindowPos */
5728
5734
5741
5748
5755
5756 /* Test SetWindowPos with child windows */
5757 flush_events();
5758 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5759 100, 100, 200, 200, 0, 0, 0, NULL);
5760 ok (hparent != 0, "Failed to create parent window\n");
5761
5762 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
5763 0, 0, 10, 10, hparent, 0, 0, NULL);
5764 ok (hchild != 0, "Failed to create child window\n");
5766 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW);
5767 ok_sequence(WmFirstDrawChildSeq1, /* Expect no messages for the child */
5768 "SetWindowPos:show_popup_first_show_window_child1", FALSE);
5769 DestroyWindow(hchild);
5770 DestroyWindow(hparent);
5771
5772 flush_events();
5773 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
5774 100, 100, 200, 200, 0, 0, 0, NULL);
5775 ok (hparent != 0, "Failed to create parent window\n");
5776
5777 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
5778 0, 0, 10, 10, hparent, 0, 0, NULL);
5779 ok (hchild != 0, "Failed to create child window\n");
5781 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW);
5782 ok_sequence(WmFirstDrawChildSeq2, /* Expect child to be redrawn */
5783 "SetWindowPos:show_popup_first_show_window_child2", FALSE);
5784 DestroyWindow(hchild);
5785 DestroyWindow(hparent);
5786
5787 /* Test message sequence for extreme position and size */
5788
5790 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE,
5791 -10, -10, 10000, 10000, NULL, 0, 0, NULL );
5792 ok (hwnd != 0, "Failed to create popup window\n");
5793 ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", FALSE);
5795
5796
5797 /* Test child windows */
5798
5799 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5800 100, 100, 200, 200, 0, 0, 0, NULL);
5801 ok (hparent != 0, "Failed to create parent window\n");
5803
5804 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
5805 0, 0, 10, 10, hparent, 0, 0, NULL);
5806 ok (hchild != 0, "Failed to create child window\n");
5807 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE);
5808 DestroyWindow(hchild);
5810
5811 /* visible child window with a caption */
5812 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
5814 0, 0, 10, 10, hparent, 0, 0, NULL);
5815 ok (hchild != 0, "Failed to create child window\n");
5816#ifdef __REACTOS__
5818#endif
5819 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
5820
5821 if (winetest_debug > 1) trace("testing scroll APIs on a visible child window %p\n", hchild);
5822 test_scroll_messages(hchild);
5823
5825 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
5826
5827 DestroyWindow(hchild);
5829
5830 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5831 0, 0, 10, 10, hparent, 0, 0, NULL);
5832 ok (hchild != 0, "Failed to create child window\n");
5833 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
5834
5835 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
5836 100, 100, 50, 50, hparent, 0, 0, NULL);
5837 ok (hchild2 != 0, "Failed to create child2 window\n");
5839
5840 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
5841 0, 100, 50, 50, hchild, 0, 0, NULL);
5842 ok (hbutton != 0, "Failed to create button window\n");
5843
5844 /* test WM_SETREDRAW on a not visible child window */
5845 test_WM_SETREDRAW(hchild);
5846
5847 ShowWindow(hchild, SW_SHOW);
5848 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
5849
5850 /* check parent messages too */
5852 ShowWindow(hchild, SW_HIDE);
5853 ok_sequence(WmHideChildSeq2, "ShowWindow(SW_HIDE):child", FALSE);
5855
5856 ShowWindow(hchild, SW_SHOW);
5857 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
5858
5859 ShowWindow(hchild, SW_HIDE);
5860 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
5861
5862 ShowWindow(hchild, SW_SHOW);
5863 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
5864
5865 /* test WM_SETREDRAW on a visible child window */
5866 test_WM_SETREDRAW(hchild);
5867
5869 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
5872
5873 ShowWindow(hchild, SW_HIDE);
5876 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
5877
5878 ShowWindow(hchild, SW_HIDE);
5881 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
5882
5883 /* DestroyWindow sequence below expects that a child has focus */
5884 SetFocus(hchild);
5886
5887 DestroyWindow(hchild);
5888 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
5889 DestroyWindow(hchild2);
5890 DestroyWindow(hbutton);
5891
5893 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
5894 0, 0, 100, 100, hparent, 0, 0, NULL);
5895 ok (hchild != 0, "Failed to create child popup window\n");
5896 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
5897 DestroyWindow(hchild);
5898
5899 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5901 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
5902 0, 0, 100, 100, hparent, 0, 0, NULL);
5903 ok (hchild != 0, "Failed to create popup window\n");
5904 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
5905 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5906 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
5908 ShowWindow(hchild, SW_SHOW);
5909 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
5912 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
5915 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
5916 DestroyWindow(hchild);
5917
5918 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5919 * changes nothing in message sequences.
5920 */
5922 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
5923 0, 0, 100, 100, hparent, 0, 0, NULL);
5924 ok (hchild != 0, "Failed to create popup window\n");
5925 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
5926 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5927 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
5929 ShowWindow(hchild, SW_SHOW);
5930 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
5933 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
5934 DestroyWindow(hchild);
5935
5938 0, 0, 100, 100, hparent, 0, 0, NULL);
5939 ok(hwnd != 0, "Failed to create custom dialog window\n");
5940 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
5941
5942 if(0) {
5943 if (winetest_debug > 1) trace("testing scroll APIs on a visible dialog %p\n", hwnd);
5945 }
5946
5948
5949 test_def_id = TRUE;
5950 SendMessageA(hwnd, WM_NULL, 0, 0);
5951
5954 EndDialog( hwnd, 0 );
5955 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
5956
5960
5961 ok(GetCursorPos(&pos), "GetCursorPos failed\n");
5962 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5963
5964 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP|WS_CHILD,
5965 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
5966 ok(hwnd != 0, "Failed to create custom dialog window\n");
5968 if (winetest_debug > 1) trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
5970 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
5971
5972 flush_events();
5974 ret = DrawMenuBar(hwnd);
5975 ok(ret, "DrawMenuBar failed: %ld\n", GetLastError());
5976 flush_events();
5977 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
5978 ok(SetCursorPos(pos.x, pos.y), "SetCursorPos failed\n");
5979
5981
5982 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_CHILD|WS_VISIBLE,
5983 0, 0, 100, 100, hparent, 0, GetModuleHandleA(0), NULL);
5984 ok(hwnd != 0, "Failed to create custom dialog window\n");
5985 flush_events();
5987 ret = DrawMenuBar(hwnd);
5988 ok(ret, "DrawMenuBar failed: %ld\n", GetLastError());
5989 flush_events();
5990 ok_sequence(WmEmptySeq, "DrawMenuBar for a child window", FALSE);
5991
5993
5995 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
5996 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
5997
5998 DestroyWindow(hparent);
6000
6001 /* Message sequence for SetMenu */
6002 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a destroyed window\n");
6003 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "last error is %ld\n", GetLastError());
6004 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
6005
6006 hmenu = CreateMenu();
6007 ok (hmenu != 0, "Failed to create menu\n");
6008 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
6009 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
6010 100, 100, 200, 200, 0, hmenu, 0, NULL);
6011 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
6012 ok (SetMenu(hwnd, 0), "SetMenu\n");
6013 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
6014 ok (SetMenu(hwnd, 0), "SetMenu\n");
6015 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
6017 UpdateWindow( hwnd );
6018 flush_events();
6020 ok (SetMenu(hwnd, 0), "SetMenu\n");
6021 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE);
6022 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
6023 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE);
6024
6025 UpdateWindow( hwnd );
6026 flush_events();
6028 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
6029 flush_events();
6030 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
6031
6034
6035 /* Message sequence for EnableWindow */
6036 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6037 100, 100, 200, 200, 0, 0, 0, NULL);
6038 ok (hparent != 0, "Failed to create parent window\n");
6039 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
6040 0, 0, 10, 10, hparent, 0, 0, NULL);
6041 ok (hchild != 0, "Failed to create child window\n");
6042
6043 SetFocus(hchild);
6044 flush_events();
6046
6047 EnableWindow(hparent, FALSE);
6048 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE);
6049
6050 EnableWindow(hparent, FALSE);
6051 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(FALSE)", FALSE);
6052
6053 EnableWindow(hparent, TRUE);
6054 ok_sequence(WmEnableWindowSeq_3, "EnableWindow(TRUE)", FALSE);
6055
6056 EnableWindow(hparent, TRUE);
6057 ok_sequence(WmEnableWindowSeq_4, "EnableWindow(TRUE)", FALSE);
6058
6059 flush_events();
6061
6063 test_WM_DEVICECHANGE(hparent);
6064
6065 /* the following test causes an exception in user.exe under win9x */
6066 if (!PostMessageW( hparent, WM_USER, 0, 0 ))
6067 {
6068 DestroyWindow(hparent);
6070 return;
6071 }
6072 PostMessageW( hparent, WM_USER+1, 0, 0 );
6073 /* PeekMessage(NULL) fails, but still removes the message */
6074 SetLastError(0xdeadbeef);
6075 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
6076 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */
6077 GetLastError() == 0xdeadbeef, /* NT4 */
6078 "last error is %ld\n", GetLastError() );
6079 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
6080 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
6081
6082 DestroyWindow(hchild);
6083 DestroyWindow(hparent);
6085
6086 /* Message sequences for WM_SETICON */
6087 if (winetest_debug > 1) trace("testing WM_SETICON\n");
6088 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
6089 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
6090 NULL, NULL, 0);
6093 flush_events();
6096 ok_sequence(WmSetIcon_1, "WM_SETICON for shown window with caption", FALSE);
6097
6099 flush_events();
6102 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window with caption", FALSE);
6105
6106 hwnd = CreateWindowExA(0, "TestPopupClass", NULL, WS_POPUP,
6107 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
6108 NULL, NULL, 0);
6111 flush_events();
6114 ok_sequence(WmSetIcon_2, "WM_SETICON for shown window without caption", FALSE);
6115
6117 flush_events();
6120 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window without caption", FALSE);
6121
6123 res = SendMessageA(hwnd, 0x3B, 0x8000000b, 0);
6124 if (!res)
6125 {
6126 todo_wine win_skip( "Message 0x3b not supported\n" );
6127 goto done;
6128 }
6129 ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE);
6130 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %Id\n", res);
6131 res = SendMessageA(hwnd, 0x3B, 0x0000000b, 0);
6132 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE);
6133 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %Id\n", res);
6134 res = SendMessageA(hwnd, 0x3B, 0x0000000f, 0);
6135 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE);
6136 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %Id\n", res);
6137
6139 res = SendMessageA(hwnd, 0x3B, 0x80000008, 0);
6140 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE);
6141 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %Id\n", res);
6142 res = SendMessageA(hwnd, 0x3B, 0x00000008, 0);
6143 ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE);
6144 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %Id\n", res);
6145
6146 res = SendMessageA(hwnd, 0x3B, 0x80000004, 0);
6147 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE);
6148 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %Id\n", res);
6149
6150 res = SendMessageA(hwnd, 0x3B, 0x80000001, 0);
6151 ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE);
6152 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %Id\n", res);
6153
6154done:
6157}
6158
6159static const struct message WmFrameChanged[] = {
6161 { WM_NCCALCSIZE, sent|wparam|lparam, 1, 0xf },
6165 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
6166 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
6167 { 0 }
6168};
6169
6170static const struct message WmFrameChanged_move[] = {
6172 { WM_NCCALCSIZE, sent|wparam|lparam, 1, 0x3 },
6175 { WM_MOVE, sent|defwinproc, 0 },
6177 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
6178 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
6179 { 0 }
6180};
6181
6182static const struct message WmMove_mouse[] = {
6185 { WM_MOVE, sent|defwinproc, 0 },
6187 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
6188 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* Win7 seems to send this twice. */
6189 { WM_SETCURSOR, sent|lparam, 0, HTCLIENT | (WM_MOUSEMOVE << 16) },
6190 { WM_MOUSEMOVE, sent },
6191 /* WM_MOUSEMOVE with accompanying WM_SETCURSOR may sometimes appear a few extra times on Windows 7 with the
6192 * same parameters. */
6203 { 0 }
6204};
6205
6206static const struct message WmMove_mouse2[] = {
6210 { 0 }
6211};
6212
6213static void test_setwindowpos(void)
6214{
6215 HWND hwnd;
6216 RECT rc;
6217 LRESULT res;
6218 const INT X = 50;
6219 const INT Y = 50;
6220 const INT winX = 100;
6221 const INT winY = 100;
6222 const INT sysX = GetSystemMetrics(SM_CXMINTRACK);
6223
6224 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0,
6225 X, Y, winX, winY, 0,
6226 NULL, NULL, 0);
6227
6228 GetWindowRect(hwnd, &rc);
6229 expect(sysX + X, rc.right);
6230 expect(winY + Y, rc.bottom);
6231
6232 flush_events();
6234 res = SetWindowPos(hwnd, HWND_TOPMOST, 50, 50, winX, winY, 0);
6235 ok_sequence(WmZOrder, "Z-Order", TRUE);
6236 ok(res == TRUE, "SetWindowPos expected TRUE, got %Id\n", res);
6237
6238 GetWindowRect(hwnd, &rc);
6239 expect(sysX + X, rc.right);
6240 expect(winY + Y, rc.bottom);
6241
6242 res = SetWindowPos( hwnd, 0, 0, 0, 0, 0,
6244 ok_sequence(WmFrameChanged, "FrameChanged", FALSE);
6245 ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res);
6246
6247 GetWindowRect(hwnd, &rc);
6248 expect(sysX + X, rc.right);
6249 expect(winY + Y, rc.bottom);
6250
6251 GetWindowRect(hwnd, &rc);
6252 res = SetWindowPos( hwnd, 0, 0, 0, 0, 0,
6254 ok_sequence(WmFrameChanged_move, "FrameChanged", FALSE);
6255 ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res);
6256
6257 GetWindowRect(hwnd, &rc);
6258 expect(sysX, rc.right);
6259 expect(winY, rc.bottom);
6260
6261 /* get away from possible menu bar to avoid spurious position changed induced by WM. */
6262 res = SetWindowPos( hwnd, HWND_TOPMOST, 200, 200, 200, 200, SWP_SHOWWINDOW );
6263 ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res);
6266 flush_events();
6267 pump_msg_loop( hwnd, 0 );
6269 GetWindowRect( hwnd, &rc );
6270 SetCursorPos( rc.left + 100, rc.top + 100 );
6271 flush_events();
6272 pump_msg_loop( hwnd, 0 );
6275 res = SetWindowPos( hwnd, 0, 205, 205, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
6276 ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res);
6277 flush_events();
6278 ok_sequence(WmMove_mouse, "MouseMove", FALSE);
6279 /* if the window and client rects were not changed WM_MOUSEMOVE is not sent. */
6280 res = SetWindowPos( hwnd, 0, 205, 205, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE );
6281 ok(res == TRUE, "SetWindowPos expected TRUE, got %Id.\n", res);
6282 flush_events();
6283 ok_sequence(WmMove_mouse2, "MouseMove2", FALSE);
6285
6287}
6288
6289static void invisible_parent_tests(void)
6290{
6291 HWND hparent, hchild;
6292
6293 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
6294 100, 100, 200, 200, 0, 0, 0, NULL);
6295 ok (hparent != 0, "Failed to create parent window\n");
6297
6298 /* test showing child with hidden parent */
6299
6300 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6301 0, 0, 10, 10, hparent, 0, 0, NULL);
6302 ok (hchild != 0, "Failed to create child window\n");
6303 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
6304
6305 ShowWindow( hchild, SW_MINIMIZE );
6306 ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
6307 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6308 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6309
6310 /* repeat */
6311 flush_events();
6313 ShowWindow( hchild, SW_MINIMIZE );
6314 ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
6315
6316 DestroyWindow(hchild);
6317 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6318 0, 0, 10, 10, hparent, 0, 0, NULL);
6320
6321 ShowWindow( hchild, SW_MAXIMIZE );
6322 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
6323 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6324 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6325
6326 /* repeat */
6327 flush_events();
6329 ShowWindow( hchild, SW_MAXIMIZE );
6330 ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
6331
6332 DestroyWindow(hchild);
6333 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6334 0, 0, 10, 10, hparent, 0, 0, NULL);
6336
6337 ShowWindow( hchild, SW_RESTORE );
6338 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE);
6339 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6340 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6341
6342 DestroyWindow(hchild);
6343 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6344 0, 0, 10, 10, hparent, 0, 0, NULL);
6346
6347 ShowWindow( hchild, SW_SHOWMINIMIZED );
6348 ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
6349 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6350 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6351
6352 /* repeat */
6353 flush_events();
6355 ShowWindow( hchild, SW_SHOWMINIMIZED );
6356 ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
6357
6358 DestroyWindow(hchild);
6359 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6360 0, 0, 10, 10, hparent, 0, 0, NULL);
6362
6363 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
6364 ShowWindow( hchild, SW_SHOWMAXIMIZED );
6365 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE);
6366 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6367 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6368
6369 DestroyWindow(hchild);
6370 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6371 0, 0, 10, 10, hparent, 0, 0, NULL);
6373
6374 ShowWindow( hchild, SW_SHOWMINNOACTIVE );
6375 ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
6376 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6377 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6378
6379 /* repeat */
6380 flush_events();
6382 ShowWindow( hchild, SW_SHOWMINNOACTIVE );
6383 ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
6384
6385 DestroyWindow(hchild);
6386 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6387 0, 0, 10, 10, hparent, 0, 0, NULL);
6389
6390 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
6391 ShowWindow( hchild, SW_FORCEMINIMIZE );
6392 ok_sequence(WmEmptySeq, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE);
6393todo_wine {
6394 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
6395}
6396 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6397
6398 DestroyWindow(hchild);
6399 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6400 0, 0, 10, 10, hparent, 0, 0, NULL);
6402
6403 ShowWindow( hchild, SW_SHOWNA );
6404 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE);
6405 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6406 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6407
6408 /* repeat */
6409 flush_events();
6411 ShowWindow( hchild, SW_SHOWNA );
6412 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE);
6413
6414 DestroyWindow(hchild);
6415 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
6416 0, 0, 10, 10, hparent, 0, 0, NULL);
6418
6419 ShowWindow( hchild, SW_SHOW );
6420 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOW) child with invisible parent", FALSE);
6421 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6422 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6423
6424 /* repeat */
6425 flush_events();
6427 ShowWindow( hchild, SW_SHOW );
6428 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW) child with invisible parent", FALSE);
6429
6430 ShowWindow( hchild, SW_HIDE );
6431 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE);
6432 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
6433 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6434
6436 ok_sequence(WmShowChildInvisibleParentSeq_6, "SetWindowPos:show child with invisible parent", FALSE);
6437 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
6438 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6439
6441 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE);
6442 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
6443 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
6444
6447 DestroyWindow(hchild);
6448 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE);
6449
6450 DestroyWindow(hparent);
6452}
6453
6454/****************** button message test *************************/
6455#define ID_BUTTON 0x000e
6456
6457static const struct message WmSetFocusButtonSeq[] =
6458{
6459 { HCBT_SETFOCUS, hook },
6462 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6463 { WM_SETFOCUS, sent|wparam, 0 },
6466 { WM_APP, sent|wparam|lparam, 0, 0 },
6467 { 0 }
6468};
6469static const struct message WmKillFocusButtonSeq[] =
6470{
6471 { HCBT_SETFOCUS, hook },
6472 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
6473 { WM_KILLFOCUS, sent|wparam, 0 },
6478 { WM_APP, sent|wparam|lparam, 0, 0 },
6479 { WM_PAINT, sent },
6481 { 0 }
6482};
6483static const struct message WmSetFocusStaticSeq[] =
6484{
6485 { HCBT_SETFOCUS, hook },
6488 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6489 { WM_SETFOCUS, sent|wparam, 0 },
6493 { WM_APP, sent|wparam|lparam, 0, 0 },
6494 { 0 }
6495};
6496static const struct message WmKillFocusStaticSeq[] =
6497{
6498 { HCBT_SETFOCUS, hook },
6499 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
6500 { WM_KILLFOCUS, sent|wparam, 0 },
6505 { WM_APP, sent|wparam|lparam, 0, 0 },
6506 { WM_PAINT, sent },
6508 { 0 }
6509};
6510static const struct message WmSetFocusOwnerdrawSeq[] =
6511{
6512 { HCBT_SETFOCUS, hook },
6515 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6516 { WM_SETFOCUS, sent|wparam, 0 },
6518 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x001040e4 },
6520 { WM_APP, sent|wparam|lparam, 0, 0 },
6521 { 0 }
6522};
6523static const struct message WmKillFocusOwnerdrawSeq[] =
6524{
6525 { HCBT_SETFOCUS, hook },
6526 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
6527 { WM_KILLFOCUS, sent|wparam, 0 },
6529 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000040e4 },
6533 { WM_APP, sent|wparam|lparam, 0, 0 },
6534 { WM_PAINT, sent },
6536 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 },
6537 { 0 }
6538};
6539static const struct message WmLButtonDownSeq[] =
6540{
6541 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
6542 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6543 { HCBT_SETFOCUS, hook },
6546 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6551 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6552 { 0 }
6553};
6554static const struct message WmLButtonDownStaticSeq[] =
6555{
6556 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
6557 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6558 { HCBT_SETFOCUS, hook },
6561 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6566 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6567 { 0 }
6568};
6569static const struct message WmLButtonUpSeq[] =
6570{
6571 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6574 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6575 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6577 { 0 }
6578};
6579static const struct message WmLButtonUpStaticSeq[] =
6580{
6581 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6584 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6585 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6587 { 0 }
6588};
6589static const struct message WmLButtonUpAutoSeq[] =
6590{
6591 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6594 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6595 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|optional, 0, 0 },
6597 { WM_CTLCOLORSTATIC, sent|defwinproc|optional, 0, 0 }, /* Sent here on Win7. */
6598 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6599 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6600 { WM_CTLCOLORSTATIC, sent|defwinproc|optional, 0, 0 }, /* Sent here on Win8+. */
6602 { 0 }
6603};
6604static const struct message WmLButtonUpBrokenSeq[] =
6605{
6606 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6607 { 0 }
6608};
6609static const struct message WmSetFontButtonSeq[] =
6610{
6611 { WM_SETFONT, sent },
6612 { WM_PAINT, sent },
6615 { 0 }
6616};
6617static const struct message WmSetFontOwnerdrawSeq[] =
6618{
6619 { WM_SETFONT, sent },
6620 { WM_PAINT, sent },
6623 { WM_CTLCOLORBTN, sent|defwinproc|wine_only }, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
6624 { 0 }
6625};
6626static const struct message WmSetFontStaticSeq[] =
6627{
6628 { WM_SETFONT, sent },
6629 { WM_PAINT, sent },
6632 { 0 }
6633};
6634static const struct message WmSetTextButtonSeq[] =
6635{
6636 { WM_SETTEXT, sent },
6637 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
6642 { 0 }
6643};
6644static const struct message WmSetTextStaticSeq[] =
6645{
6646 { WM_SETTEXT, sent },
6647 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
6650 { 0 }
6651};
6652static const struct message WmSetTextGroupSeq[] =
6653{
6654 { WM_SETTEXT, sent },
6656 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
6657 { WM_CTLCOLORSTATIC, sent|parent|msg_todo }, /* FIXME: Missing in Wine */
6658 { WM_CTLCOLORSTATIC, sent|parent|msg_todo }, /* FIXME: Missing in Wine */
6659 { 0 }
6660};
6661static const struct message WmSetTextInvisibleSeq[] =
6662{
6663 { WM_SETTEXT, sent },
6664 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
6665 { 0 }
6666};
6667static const struct message WmSetStyleButtonSeq[] =
6668{
6669 { BM_SETSTYLE, sent },
6670 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6671 { WM_APP, sent|wparam|lparam, 0, 0 },
6672 { WM_PAINT, sent },
6673 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6675 { 0 }
6676};
6677static const struct message WmSetStyleStaticSeq[] =
6678{
6679 { BM_SETSTYLE, sent },
6680 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6681 { WM_APP, sent|wparam|lparam, 0, 0 },
6682 { WM_PAINT, sent },
6683 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6685 { 0 }
6686};
6687static const struct message WmSetStyleUserSeq[] =
6688{
6689 { BM_SETSTYLE, sent },
6690 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6691 { WM_APP, sent|wparam|lparam, 0, 0 },
6692 { WM_PAINT, sent },
6693 { WM_NCPAINT, sent|defwinproc|wine_only }, /* FIXME: Wine sends it */
6694 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6697 { 0 }
6698};
6699static const struct message WmSetStyleOwnerdrawSeq[] =
6700{
6701 { BM_SETSTYLE, sent },
6702 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6703 { WM_APP, sent|wparam|lparam, 0, 0 },
6704 { WM_PAINT, sent },
6705 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6707 { WM_CTLCOLORBTN, sent|parent|optional }, /* Win9x doesn't send it */
6708 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 },
6709 { 0 }
6710};
6711static const struct message WmSetStateButtonSeq[] =
6712{
6713 { BM_SETSTATE, sent },
6715 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6716 { WM_APP, sent|wparam|lparam, 0, 0 },
6717 { 0 }
6718};
6719static const struct message WmSetStateStaticSeq[] =
6720{
6721 { BM_SETSTATE, sent },
6723 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6724 { WM_APP, sent|wparam|lparam, 0, 0 },
6725 { 0 }
6726};
6727static const struct message WmSetStateUserSeq[] =
6728{
6729 { BM_SETSTATE, sent },
6732 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6733 { WM_APP, sent|wparam|lparam, 0, 0 },
6734 { 0 }
6735};
6736static const struct message WmSetStateOwnerdrawSeq[] =
6737{
6738 { BM_SETSTATE, sent },
6740 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000120e4 },
6741 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6742 { WM_APP, sent|wparam|lparam, 0, 0 },
6743 { 0 }
6744};
6745static const struct message WmClearStateButtonSeq[] =
6746{
6747 { BM_SETSTATE, sent },
6750 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6751 { WM_APP, sent|wparam|lparam, 0, 0 },
6752 { 0 }
6753};
6754static const struct message WmDisableButtonSeq[] =
6755{
6756 { WM_LBUTTONDOWN, sent },
6757 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6761 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6762 { WM_LBUTTONUP, sent },
6768 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6769 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6772 { WM_COMMAND, sent },
6773 { 0 }
6774};
6775static const struct message WmClearStateOwnerdrawSeq[] =
6776{
6777 { BM_SETSTATE, sent },
6779 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000020e4 },
6780 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6781 { WM_APP, sent|wparam|lparam, 0, 0 },
6782 { 0 }
6783};
6784static const struct message WmSetCheckIgnoredSeq[] =
6785{
6786 { BM_SETCHECK, sent },
6787 { WM_APP, sent|wparam|lparam, 0, 0 },
6788 { 0 }
6789};
6790static const struct message WmSetCheckStaticSeq[] =
6791{
6792 { BM_SETCHECK, sent },
6794 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
6795 { WM_APP, sent|wparam|lparam, 0, 0 },
6796 { 0 }
6797};
6798
6800
6802{
6803 static LONG defwndproc_counter = 0;
6804 LRESULT ret;
6805 struct recvd_message msg;
6806
6807 if (ignore_message( message )) return 0;
6808
6809 switch (message)
6810 {
6811 case WM_SYNCPAINT:
6812 break;
6813 case BM_SETSTATE:
6814 if (GetCapture())
6815 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
6816
6818 goto log_it;
6819
6820 case WM_GETDLGCODE:
6821 if (lParam)
6822 {
6823 MSG *msg = (MSG *)lParam;
6824 lParam = MAKELPARAM(msg->message, msg->wParam);
6825 }
6827 goto log_it;
6828
6829 case BM_SETCHECK:
6830 case BM_GETCHECK:
6832 /* fall through */
6833log_it:
6834 default:
6835 msg.hwnd = hwnd;
6836 msg.message = message;
6837 msg.flags = sent|wparam|lparam;
6838 if (defwndproc_counter) msg.flags |= defwinproc;
6839 msg.wParam = wParam;
6840 msg.lParam = lParam;
6841 msg.descr = "button";
6842 add_message(&msg);
6843 }
6844
6845 defwndproc_counter++;
6847 defwndproc_counter--;
6848
6849 return ret;
6850}
6851
6852static void subclass_button(void)
6853{
6854 WNDCLASSA cls;
6855 BOOL ret;
6856
6857 ret = GetClassInfoA(0, "button", &cls);
6858 ok(ret, "Failed to get class info, error %lu.\n", GetLastError());
6859
6861
6864 cls.lpszClassName = "my_button_class";
6866 register_class(&cls);
6867}
6868
6869static void test_button_messages(void)
6870{
6871 static const struct
6872 {
6873 DWORD style;
6874 DWORD dlg_code;
6875 const struct message *setfocus;
6876 const struct message *killfocus;
6877 const struct message *setstyle;
6878 const struct message *setstate;
6879 const struct message *clearstate;
6880 const struct message *setcheck;
6881 const struct message *lbuttondown;
6882 const struct message *lbuttonup;
6883 const struct message *setfont;
6884 const struct message *settext;
6885 } button[] = {
6934 NULL /* avoid infinite loop */, WmLButtonUpBrokenSeq, WmSetFontStaticSeq,
6941 };
6942 LOGFONTA logfont = { 0 };
6943 HFONT zfont, hfont2;
6944 unsigned int i;
6945 HWND hwnd, parent;
6946 DWORD dlg_code;
6947
6948 /* selection with VK_SPACE should capture button window */
6949 hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP,
6950 0, 0, 50, 14, 0, 0, 0, NULL);
6951 ok(hwnd != 0, "Failed to create button window\n");
6953 SetFocus(hwnd);
6955 ok(GetCapture() == hwnd, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6958
6960
6961 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6962 100, 100, 200, 200, 0, 0, 0, NULL);
6963 ok(parent != 0, "Failed to create parent window\n");
6964
6965 memset(&logfont, 0, sizeof(logfont));
6966 logfont.lfHeight = -12;
6967 logfont.lfWeight = FW_NORMAL;
6968 strcpy(logfont.lfFaceName, "Tahoma");
6969
6970 hfont2 = CreateFontIndirectA(&logfont);
6971 ok(hfont2 != NULL, "Failed to create Tahoma font\n");
6972
6973 for (i = 0; i < ARRAY_SIZE(button); i++)
6974 {
6975 MSG msg;
6976 DWORD style, state;
6977 HFONT prevfont;
6978 char desc[64];
6979 HDC hdc;
6980
6981 if (winetest_debug > 1) trace("button style %08lx\n", button[i].style);
6982
6983 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY,
6984 0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL);
6985 ok(hwnd != 0, "Failed to create button window\n");
6986
6988 style &= ~(WS_CHILD | BS_NOTIFY);
6989 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6990 if (button[i].style == BS_USERBUTTON)
6991 ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %lx\n", style);
6992 else
6993 ok(style == button[i].style, "expected style %lx got %lx\n", button[i].style, style);
6994
6995 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
6996 ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08lx\n", i, dlg_code);
6997
7000 SetFocus(0);
7001 flush_events();
7002 SetFocus(0);
7004
7006
7007 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
7008 SetFocus(hwnd);
7009 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
7010 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7011 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
7012
7013 SetFocus(0);
7014 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
7015 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7016 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
7017
7018 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
7019
7021 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
7022 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7023 ok_sequence(button[i].setstyle, "BM_SETSTYLE on a button", FALSE);
7024
7027 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
7028 ok(style == button[i].style, "expected style %04lx got %04lx\n", button[i].style, style);
7029
7031 ok(state == 0, "expected state 0, got %04lx\n", state);
7032
7034
7036 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
7037 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7038 ok_sequence(button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE);
7039
7041 ok(state == 0x0004, "expected state 0x0004, got %04lx\n", state);
7042
7045 ok(style == button[i].style, "expected style %04lx got %04lx\n", button[i].style, style);
7046
7048
7050 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
7051 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7052 ok_sequence(button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE);
7053
7055 ok(state == 0, "expected state 0, got %04lx\n", state);
7056
7059 ok(style == button[i].style, "expected style %04lx got %04lx\n", button[i].style, style);
7060
7062 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04lx\n", state);
7063
7065
7067 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
7068 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7069 ok_sequence(WmSetCheckIgnoredSeq, "BM_SETCHECK on a button", FALSE);
7070
7072 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04lx\n", state);
7073
7076 ok(style == button[i].style, "expected style %04lx got %04lx\n", button[i].style, style);
7077
7079
7081 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
7082 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7083 ok_sequence(button[i].setcheck, "BM_SETCHECK on a button", FALSE);
7084
7085 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 1");
7086 sprintf(desc, "button[%i]: WM_SETTEXT on a visible button", i);
7087 ok_sequence(button[i].settext, desc, FALSE);
7088
7090 flush_events();
7092
7093 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 2");
7094 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i);
7096
7099 flush_events();
7101
7102 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 3");
7103 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i);
7105
7107 flush_events();
7108
7110 if (button[i].style == BS_PUSHBUTTON ||
7112 button[i].style == BS_GROUPBOX ||
7115 ok(state == BST_UNCHECKED, "expected check 0, got %04lx\n", state);
7116 else
7117 ok(state == BST_CHECKED, "expected check 1, got %04lx\n", state);
7118
7121 if (button[i].style == BS_RADIOBUTTON ||
7123 ok(style == (button[i].style | WS_TABSTOP), "expected style %04lx | WS_TABSTOP got %04lx\n", button[i].style, style);
7124 else
7125 ok(style == button[i].style, "expected style %04lx got %04lx\n", button[i].style, style);
7126
7128
7130
7131 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE,
7132 0, 0, 50, 14, 0, 0, 0, NULL);
7133 ok(hwnd != 0, "Failed to create button window\n");
7134
7136 flush_events();
7137
7139 SetFocus(0);
7141
7142 if (button[i].lbuttondown)
7143 {
7145 sprintf(desc, "button[%i]: WM_LBUTTONDOWN on a button", i);
7146 ok_sequence(button[i].lbuttondown, desc, FALSE);
7147 }
7148
7150 sprintf(desc, "button[%i]: WM_LBUTTONUP on a button", i);
7151 ok_sequence(button[i].lbuttonup, desc, FALSE);
7152
7157 sprintf(desc, "button[%i]: WM_SETFONT on a button", i);
7158 ok_sequence(button[i].setfont, desc, FALSE);
7159
7160 /* Test that original font is not selected back after painting */
7162
7163 prevfont = SelectObject(hdc, hfont2);
7164 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n");
7166 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i);
7167 SelectObject(hdc, prevfont);
7168
7169 prevfont = SelectObject(hdc, hfont2);
7170 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n");
7172 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PAINT\n", i);
7173 SelectObject(hdc, prevfont);
7174
7175 DeleteDC(hdc);
7176
7178 }
7179
7180 DeleteObject(hfont2);
7182
7183 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
7184
7185 parent = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7186 100, 100, 200, 200, 0, 0, 0, NULL);
7187 ok (hwnd != 0, "Failed to create overlapped window\n");
7188
7189 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
7190 0, 0, 50, 14, parent, 0, 0, NULL);
7191
7196 ok_sequence(WmDisableButtonSeq, "Mouseclick on a disabled button", FALSE);
7197
7200}
7201
7203{
7204 HWND hwnd;
7205 HDC hdc;
7206 HBITMAP hbmp1x1;
7207 HBITMAP hbmp2x2;
7208 HBITMAP hmask2x2;
7209 ICONINFO icon_info2x2;
7210 HICON hicon2x2;
7211 HBITMAP hbmp;
7212 HICON hicon;
7213 ICONINFO icon_info;
7214 BITMAP bm;
7215 DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP | WS_VISIBLE;
7216 LRESULT ret;
7217
7218 hdc = GetDC(0);
7219 hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1);
7220 hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2);
7221 ZeroMemory(&bm, sizeof(bm));
7222 ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW() success\n");
7223 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7224 bm.bmWidth, bm.bmHeight);
7225 ZeroMemory(&bm, sizeof(bm));
7226 ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW() success\n");
7227 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7228 bm.bmWidth, bm.bmHeight);
7229
7230 hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2);
7231 ZeroMemory(&icon_info2x2, sizeof(icon_info2x2));
7232 icon_info2x2.fIcon = TRUE;
7233 icon_info2x2.hbmMask = hmask2x2;
7234 icon_info2x2.hbmColor = hbmp2x2;
7235 hicon2x2 = CreateIconIndirect(&icon_info2x2);
7236
7237 ZeroMemory(&icon_info, sizeof(icon_info));
7238 ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo() success\n");
7239 ZeroMemory(&bm, sizeof(bm));
7240 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
7241 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7242 bm.bmWidth, bm.bmHeight);
7243 DeleteObject(icon_info.hbmColor);
7244 DeleteObject(icon_info.hbmMask);
7245
7246 /* Set bitmap with BS_BITMAP */
7247 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0);
7248 ok(hwnd != NULL, "Expect hwnd not NULL\n");
7251 ok(hbmp != 0, "Expect hbmp not 0\n");
7252 ZeroMemory(&bm, sizeof(bm));
7253 ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
7254 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7255 bm.bmWidth, bm.bmHeight);
7257
7258 /* Set bitmap without BS_BITMAP */
7259 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
7260 ok(hwnd != NULL, "Expect hwnd not NULL\n");
7262 ok(ret == 0, "Expect ret to be 0\n");
7264 ok(hbmp == NULL, "Expect hbmp to be NULL\n");
7266
7267 /* Set icon with BS_ICON */
7268 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0);
7269 ok(hwnd != NULL, "Expect hwnd not NULL\n");
7272 ok(hicon != NULL, "Expect hicon not NULL\n");
7273 ZeroMemory(&icon_info, sizeof(icon_info));
7274 ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
7275 ZeroMemory(&bm, sizeof(bm));
7276 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
7277 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7278 bm.bmWidth, bm.bmHeight);
7279 DeleteObject(icon_info.hbmColor);
7280 DeleteObject(icon_info.hbmMask);
7282
7283 /* Set icon without BS_ICON */
7284 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
7285 ok(hwnd != NULL, "Expect hwnd not NULL\n");
7287 ok(ret == 0, "Expect ret to be 0\n");
7289 ok(hicon == NULL, "Expect hicon to be NULL\n");
7291
7292 /* Set icon with BS_BITMAP */
7293 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0);
7294 ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
7296 ok(ret == 0, "Expect ret to be 0\n");
7298 ok(hicon == NULL, "Expect hicon to be NULL\n");
7300
7301 /* Set bitmap with BS_ICON */
7302 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0);
7303 ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
7305 ok(ret == 0, "Expect ret to be 0\n");
7307 ok(hbmp == NULL, "Expect hbmp to be NULL\n");
7309
7310 DestroyIcon(hicon2x2);
7311 DeleteObject(hmask2x2);
7312 DeleteObject(hbmp2x2);
7313 DeleteObject(hbmp1x1);
7314 ReleaseDC(0, hdc);
7315}
7316
7317#define ID_RADIO1 501
7318#define ID_RADIO2 502
7319#define ID_RADIO3 503
7320#define ID_TEXT 504
7321
7323{
7324 { BM_CLICK, sent|wparam|lparam, 0, 0 },
7326 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
7329 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
7333 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
7339 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
7343 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
7345 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
7348 { WM_NCHITTEST, sent|optional, 0, 0 },
7349 { WM_SETCURSOR, sent|optional, 0, 0 },
7350 { WM_MOUSEMOVE, sent|optional, 0, 0 },
7351 { 0 }
7352};
7353
7355{
7357 { WM_KEYUP, sent|wparam|lparam, VK_UP, 0 },
7358 { 0 }
7359};
7360
7362{
7365 { 0 }
7366};
7367
7369{
7370 { WM_GETDLGCODE, sent|parent, 0, 0 },
7371
7372 /* optional trailer seen on some windows setups */
7373 { WM_CHANGEUISTATE, sent|optional },
7374 { WM_UPDATEUISTATE, sent|optional },
7375 { WM_UPDATEUISTATE, sent|optional },
7376 { WM_UPDATEUISTATE, sent|optional },
7377 { WM_UPDATEUISTATE, sent|optional },
7378 { WM_UPDATEUISTATE, sent|optional },
7379 { WM_UPDATEUISTATE, sent|optional },
7380 { WM_UPDATEUISTATE, sent|optional },
7381 { WM_UPDATEUISTATE, sent|optional },
7382 { WM_UPDATEUISTATE, sent|optional },
7383 { WM_UPDATEUISTATE, sent|optional },
7384 { WM_UPDATEUISTATE, sent|optional },
7385 { WM_UPDATEUISTATE, sent|optional },
7386 { WM_UPDATEUISTATE, sent|optional },
7387 { WM_UPDATEUISTATE, sent|optional },
7388 { WM_UPDATEUISTATE, sent|optional },
7389 { WM_UPDATEUISTATE, sent|optional },
7390 { WM_UPDATEUISTATE, sent|optional },
7391 { WM_UPDATEUISTATE, sent|optional },
7395 { WM_UPDATEUISTATE, sent|optional },
7398 { WM_UPDATEUISTATE, sent|optional },
7401 { WM_UPDATEUISTATE, sent|optional },
7404 { 0 }
7405};
7406
7408{
7409 { WM_GETDLGCODE, sent|parent, 0, 0 },
7412 { HCBT_SETFOCUS, hook },
7413 { WM_KILLFOCUS, sent, 0, 0 },
7416 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
7417 { WM_SETFOCUS, sent, 0, 0 },
7422 { WM_GETDLGCODE, sent|parent, 0, 0 },
7423 { DM_GETDEFID, sent|parent, 0, 0 },
7425 { BM_CLICK, sent|wparam|lparam, 1, 0 },
7427 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
7430 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
7434 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
7438 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
7442 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
7447 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam|msg_todo, OBJID_CLIENT, 0 },
7448 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
7451 { WM_NCHITTEST, sent|optional, 0, 0 },
7452 { WM_SETCURSOR, sent|optional, 0, 0 },
7453 { WM_MOUSEMOVE, sent|optional, 0, 0 },
7454 { WM_PAINT, sent },
7456 { 0 }
7457};
7458
7460{
7464 { WM_GETDLGCODE, sent|parent, 0, 0 },
7469 { WM_USER, sent|parent, 0, 0 },
7471 { 0 }
7472};
7473
7475{
7476 { WM_GETDLGCODE, sent|parent, 0, 0 },
7477 { 0 }
7478};
7479
7481{
7482 ParentMsgCheckProcA(hwnd, msg, wp, lp);
7483 return 1;
7484}
7485
7487{
7488 HWND parent, radio1, radio2, radio3;
7489 RECT rc;
7490 MSG msg;
7491 DWORD ret;
7492
7494
7495 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc, 0);
7496 ok(parent != 0, "failed to create parent window\n");
7497
7498 radio1 = GetDlgItem(parent, ID_RADIO1);
7499 radio2 = GetDlgItem(parent, ID_RADIO2);
7500 radio3 = GetDlgItem(parent, ID_RADIO3);
7501
7502 /* this avoids focus messages in the generated sequence */
7503 SetFocus(radio2);
7504
7505 flush_events();
7507
7508 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
7509 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7510 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
7511 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7512 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
7513 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7514
7516
7517 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
7518 ok(ret == BST_CHECKED, "got %08lx\n", ret);
7519 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
7520 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7521 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
7522 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7523
7525
7526 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
7527 ok(ret == BST_CHECKED, "got %08lx\n", ret);
7528 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
7529 ok(ret == BST_CHECKED, "got %08lx\n", ret);
7530 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
7531 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7532
7534
7535 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
7536 ok(ret == BST_CHECKED, "got %08lx\n", ret);
7537 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
7538 ok(ret == BST_CHECKED, "got %08lx\n", ret);
7539 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
7540 ok(ret == BST_CHECKED, "got %08lx\n", ret);
7541
7542 GetWindowRect(radio2, &rc);
7543 SetCursorPos(rc.left+1, rc.top+1);
7544
7545 flush_events();
7547
7549
7550 SendMessageA(radio2, BM_CLICK, 0, 0);
7551 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7552 ok_sequence(auto_radio_button_BM_CLICK, "BM_CLICK on auto-radio button", FALSE);
7553
7555
7556 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
7557 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7558 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
7559 ok(ret == BST_CHECKED, "got %08lx\n", ret);
7560 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
7561 ok(ret == BST_UNCHECKED, "got %08lx\n", ret);
7562
7564}
7565
7566#define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)
7567static void test_radio_dbg(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3, int line)
7568{
7569 DWORD ret;
7570
7571 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
7572 ok_(__FILE__,line)(ret == state1 ? BST_CHECKED : BST_UNCHECKED, "got %08lx\n", ret);
7573 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
7574 ok_(__FILE__,line)(ret == state2 ? BST_CHECKED : BST_UNCHECKED, "got %08lx\n", ret);
7575 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
7576 ok_(__FILE__,line)(ret == state3 ? BST_CHECKED : BST_UNCHECKED, "got %08lx\n", ret);
7577}
7578
7579static void set_radio(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3)
7580{
7581 SendMessageA(radio1, BM_SETCHECK, state1 ? BST_CHECKED : BST_UNCHECKED, 0);
7582 SendMessageA(radio2, BM_SETCHECK, state2 ? BST_CHECKED : BST_UNCHECKED, 0);
7583 SendMessageA(radio3, BM_SETCHECK, state3 ? BST_CHECKED : BST_UNCHECKED, 0);
7584}
7585
7587{
7588 HWND parent, radio1, radio2, radio3, hwnd;
7589 RECT rc;
7590 MSG msg;
7591 DWORD ret;
7592
7594
7595 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc, 0);
7596 ok(parent != 0, "failed to create parent window\n");
7597
7598 radio1 = GetDlgItem(parent, ID_RADIO1);
7599 radio2 = GetDlgItem(parent, ID_RADIO2);
7600 radio3 = GetDlgItem(parent, ID_RADIO3);
7601
7602 flush_events();
7604
7605 test_radio(radio1, 0, radio2, 0, radio3, 0);
7606 set_radio(radio1, 1, radio2, 1, radio3, 1);
7607 test_radio(radio1, 1, radio2, 1, radio3, 1);
7608
7609 SetFocus(radio3);
7610
7611 flush_events();
7613
7615
7616 SendMessageA(radio3, WM_KEYDOWN, VK_UP, 0);
7617 SendMessageA(radio3, WM_KEYUP, VK_UP, 0);
7618 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7619 ok_sequence(auto_radio_button_VK_UP_child, "press/release VK_UP on auto-radio button", FALSE);
7620
7621 test_radio(radio1, 1, radio2, 1, radio3, 1);
7622
7623 flush_events();
7625
7628 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7629 ok_sequence(auto_radio_button_VK_UP_parent, "press/release VK_UP on dialog", FALSE);
7630
7631 test_radio(radio1, 1, radio2, 1, radio3, 1);
7632
7633 SetFocus(radio3);
7634 GetWindowRect(radio3, &rc);
7635
7636 flush_events();
7638
7639 msg.hwnd = parent;
7640 msg.message = WM_KEYDOWN;
7641 msg.wParam = VK_UP;
7642 msg.lParam = 0;
7643 msg.pt.x = rc.left + 1;
7644 msg.pt.y = rc.top + 1;
7646 ok(ret, "IsDialogMessage should return TRUE\n");
7647 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7648 if (0) /* actual message sequence is different on every run in some Windows setups */
7649 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #1", FALSE);
7650 /* what really matters is that nothing has changed */
7651 test_radio(radio1, 1, radio2, 1, radio3, 1);
7652
7653 set_radio(radio1, 0, radio2, 1, radio3, 1);
7654 test_radio(radio1, 0, radio2, 1, radio3, 1);
7655
7656 flush_events();
7658
7660 ok(ret, "IsDialogMessage should return TRUE\n");
7661 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7662 if (0) /* actual message sequence is different on every run in some Windows setups */
7663 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #2", FALSE);
7664 /* what really matters is that nothing has changed */
7665 test_radio(radio1, 0, radio2, 1, radio3, 1);
7666
7667 /* switch from radio3 ro radio1 */
7668 SetFocus(radio3);
7669 GetWindowRect(radio3, &rc);
7670
7671 flush_events();
7673
7674 msg.hwnd = parent;
7675 msg.message = WM_KEYDOWN;
7676 msg.wParam = VK_DOWN;
7677 msg.lParam = 0;
7678 msg.pt.x = rc.left + 1;
7679 msg.pt.y = rc.top + 1;
7681 ok(ret, "IsDialogMessage should return TRUE\n");
7682 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7683 ok_sequence(auto_radio_button_VK_DOWN_dialog, "IsDialogMessage(VK_DOWN)", TRUE);
7684
7685 test_radio(radio1, 1, radio2, 0, radio3, 0);
7686
7687 hwnd = GetFocus();
7688 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
7689 GetWindowRect(radio1, &rc);
7690
7691 msg.hwnd = parent;
7692 msg.message = WM_KEYDOWN;
7693 msg.wParam = VK_DOWN;
7694 msg.lParam = 0;
7695 msg.pt.x = rc.left + 1;
7696 msg.pt.y = rc.top + 1;
7698 ok(ret, "IsDialogMessage should return TRUE\n");
7699 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7701
7702 test_radio(radio1, 1, radio2, 0, radio3, 0);
7703
7704 hwnd = GetFocus();
7705 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
7706
7707 flush_events();
7709
7710 msg.hwnd = parent;
7711 msg.message = WM_KEYDOWN;
7712 msg.wParam = VK_UP;
7713 msg.lParam = 0;
7714 msg.pt.x = rc.left + 1;
7715 msg.pt.y = rc.top + 1;
7717 ok(ret, "IsDialogMessage should return TRUE\n");
7718 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7720
7721 test_radio(radio1, 1, radio2, 0, radio3, 0);
7722
7723 hwnd = GetFocus();
7724 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
7725
7726 flush_events();
7728
7729 msg.hwnd = parent;
7730 msg.message = WM_KEYDOWN;
7731 msg.wParam = VK_UP;
7732 msg.lParam = 0;
7733 msg.pt.x = rc.left + 1;
7734 msg.pt.y = rc.top + 1;
7736 ok(ret, "IsDialogMessage should return TRUE\n");
7737 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7738 if (0) /* actual message sequence is different on every run in some Windows setups */
7739 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #3", FALSE);
7740 /* what really matters is that nothing has changed */
7741 test_radio(radio1, 1, radio2, 0, radio3, 0);
7742
7744
7746}
7747
7748/****************** static message test *************************/
7749static const struct message WmSetFontStaticSeq2[] =
7750{
7751 { WM_SETFONT, sent },
7755 { 0 }
7756};
7757
7759
7761{
7762 static LONG defwndproc_counter = 0;
7763 LRESULT ret;
7764 struct recvd_message msg;
7765
7766 if (ignore_message( message )) return 0;
7767
7768 msg.hwnd = hwnd;
7769 msg.message = message;
7770 msg.flags = sent|wparam|lparam;
7771 if (defwndproc_counter) msg.flags |= defwinproc;
7772 msg.wParam = wParam;
7773 msg.lParam = lParam;
7774 msg.descr = "static";
7775 add_message(&msg);
7776
7777 defwndproc_counter++;
7779 defwndproc_counter--;
7780
7781 return ret;
7782}
7783
7784static void subclass_static(void)
7785{
7786 WNDCLASSA cls;
7787 BOOL ret;
7788
7789 ret = GetClassInfoA(0, "static", &cls);
7790 ok(ret, "Failed to get class info, error %lu.\n", GetLastError());
7791
7793
7796 cls.lpszClassName = "my_static_class";
7798 register_class(&cls);
7799}
7800
7801static void test_static_messages(void)
7802{
7803 /* FIXME: make as comprehensive as the button message test */
7804 static const struct
7805 {
7806 DWORD style;
7807 DWORD dlg_code;
7808 const struct message *setfont;
7809 } static_ctrl[] = {
7812 };
7813 unsigned int i;
7814 HWND hwnd;
7815 DWORD dlg_code;
7816
7818
7819 for (i = 0; i < ARRAY_SIZE(static_ctrl); i++)
7820 {
7821 hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP,
7822 0, 0, 50, 14, 0, 0, 0, NULL);
7823 ok(hwnd != 0, "Failed to create static window\n");
7824
7825 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
7826 ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08lx\n", i, dlg_code);
7827
7830 SetFocus(0);
7832
7833 if (winetest_debug > 1) trace("static style %08lx\n", static_ctrl[i].style);
7835 ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE);
7836
7838 }
7839}
7840
7841/****************** ComboBox message test *************************/
7842#define ID_COMBOBOX 0x000f
7843
7844static const struct message SetCurSelComboSeq[] =
7845{
7846 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7847 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7848 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 },
7849 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 },
7850 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 },
7851 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */
7852 { LB_GETTEXT, sent|wparam, 0 },
7854 { LB_GETITEMDATA, sent|wparam|lparam, 0, 0 },
7855 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_COMBOBOX, 0x100010f3 },
7856 { 0 }
7857};
7858
7859static const struct message SetCurSelComboSeq2[] =
7860{
7861 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7862 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7863 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 },
7864 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 },
7865 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 },
7866 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */
7867 { LB_GETTEXT, sent|wparam, 0 },
7868 { 0 }
7869};
7870
7871static const struct message SetCurSelComboSeq_edit[] =
7872{
7873 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7874 { WM_SETTEXT, sent|wparam, 0 },
7876 { 0 }
7877};
7878
7879static const struct message WmKeyDownComboSeq[] =
7880{
7887 { 0 }
7888};
7889
7890static const struct message WmSetPosComboSeq[] =
7891{
7896 { WM_MOVE, sent|defwinproc },
7902 { 0 }
7903};
7904
7905static const struct message WMSetFocusComboBoxSeq[] =
7906{
7907 { WM_SETFOCUS, sent },
7909 { WM_SETFOCUS, sent },
7912 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */
7913 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */
7915 { 0 }
7916};
7917
7918static const struct message SetFocusButtonSeq[] =
7919{
7920 { WM_KILLFOCUS, sent },
7921 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */
7922 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */
7926 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */
7927 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */
7930 { 0 }
7931};
7932
7933static const struct message SetFocusComboBoxSeq[] =
7934{
7936 { WM_SETFOCUS, sent },
7938 { EM_GETPASSWORDCHAR, sent|optional }, /* Sent on some Win10 machines */
7939 { WM_SETFOCUS, sent },
7942 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */
7943 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */
7945 { 0 }
7946};
7947
7948static const struct message SetFocusButtonSeq2[] =
7949{
7950 { WM_KILLFOCUS, sent },
7951 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */
7952 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */
7960 { 0 }
7961};
7962
7964
7967{
7968 static LONG defwndproc_counter = 0;
7969 LRESULT ret;
7970 struct recvd_message msg;
7971
7972 /* do not log painting messages */
7973 if (message != WM_PAINT &&
7974 message != WM_NCPAINT &&
7975 message != WM_SYNCPAINT &&
7977 message != WM_NCHITTEST &&
7978 message != WM_GETTEXT &&
7980 {
7981 msg.hwnd = hwnd;
7982 msg.message = message;
7983 msg.flags = sent|wparam|lparam;
7984 if (defwndproc_counter) msg.flags |= defwinproc;
7985 msg.wParam = wParam;
7986 msg.lParam = lParam;
7987 msg.descr = "combo edit";
7988 add_message(&msg);
7989 }
7990
7991 defwndproc_counter++;
7993 defwndproc_counter--;
7994
7995 return ret;
7996}
7997
8000{
8001 static LONG defwndproc_counter = 0;
8002 LRESULT ret;
8003 struct recvd_message msg;
8004
8005 /* do not log painting messages */
8006 if (message != WM_PAINT &&
8007 message != WM_NCPAINT &&
8008 message != WM_SYNCPAINT &&
8010 message != WM_NCHITTEST &&
8012 {
8013 msg.hwnd = hwnd;
8014 msg.message = message;
8015 msg.flags = sent|wparam|lparam;
8016 if (defwndproc_counter) msg.flags |= defwinproc;
8017 msg.wParam = wParam;
8018 msg.lParam = lParam;
8019 msg.descr = "combo lbox";
8020 add_message(&msg);
8021 }
8022
8023 defwndproc_counter++;
8025 defwndproc_counter--;
8026
8027 return ret;
8028}
8029
8031{
8032 static LONG defwndproc_counter = 0;
8033 LRESULT ret;
8034 struct recvd_message msg;
8035
8036 /* do not log painting messages */
8037 if (message != WM_PAINT &&
8038 message != WM_NCPAINT &&
8039 message != WM_SYNCPAINT &&
8041 message != WM_NCHITTEST &&
8042 message != WM_GETTEXT &&
8044 {
8045 msg.hwnd = hwnd;
8046 msg.message = message;
8047 msg.flags = sent|wparam|lparam;
8048 if (defwndproc_counter) msg.flags |= defwinproc;
8049 msg.wParam = wParam;
8050 msg.lParam = lParam;
8051 msg.descr = "combo";
8052 add_message(&msg);
8053 }
8054
8055 defwndproc_counter++;
8057 defwndproc_counter--;
8058
8059 return ret;
8060}
8061
8062static void subclass_combobox(void)
8063{
8064 WNDCLASSA cls;
8065 BOOL ret;
8066
8067 ret = GetClassInfoA(0, "ComboBox", &cls);
8068 ok(ret, "Failed to get class info, error %lu.\n", GetLastError());
8069
8071
8074 cls.lpszClassName = "my_combobox_class";
8076 register_class(&cls);
8077}
8078
8079static void test_combobox_messages(void)
8080{
8081 HWND parent, combo, button, edit, lbox;
8082 LRESULT ret;
8083 COMBOBOXINFO cbInfo;
8084 BOOL res;
8085
8087
8088 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8089 100, 100, 200, 200, 0, 0, 0, NULL);
8090 ok(parent != 0, "Failed to create parent window\n");
8092
8093 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
8094 0, 0, 100, 150, parent, (HMENU)ID_COMBOBOX, 0, NULL);
8095 ok(combo != 0, "Failed to create combobox window\n");
8096
8097 UpdateWindow(combo);
8098
8099 ret = SendMessageA(combo, WM_GETDLGCODE, 0, 0);
8100 ok(ret == (DLGC_WANTCHARS | DLGC_WANTARROWS), "wrong dlg_code %08Ix\n", ret);
8101
8102 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0");
8103 ok(ret == 0, "expected 0, got %Id\n", ret);
8104 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 1");
8105 ok(ret == 1, "expected 1, got %Id\n", ret);
8106 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 2");
8107 ok(ret == 2, "expected 2, got %Id\n", ret);
8108
8109 SendMessageA(combo, CB_SETCURSEL, 0, 0);
8110 SetFocus(combo);
8112
8114 SendMessageA(combo, WM_KEYDOWN, VK_DOWN, 0);
8115 SendMessageA(combo, WM_KEYUP, VK_DOWN, 0);
8117 ok_sequence(WmKeyDownComboSeq, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE);
8118
8120 SetWindowPos(combo, 0, 10, 10, 120, 130, SWP_NOZORDER);
8121 ok_sequence(WmSetPosComboSeq, "repositioning messages on a ComboBox", FALSE);
8122
8123 DestroyWindow(combo);
8125
8126 /* Start again. Test combobox text selection when getting and losing focus */
8127 parent = CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8128 10, 10, 300, 300, NULL, NULL, NULL, NULL);
8129 ok(parent != 0, "Failed to create parent window\n");
8130
8131 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
8132 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL);
8133 ok(combo != 0, "Failed to create combobox window\n");
8134
8135 cbInfo.cbSize = sizeof(COMBOBOXINFO);
8136 SetLastError(0xdeadbeef);
8137 res = GetComboBoxInfo(combo, &cbInfo);
8138 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8139 edit = cbInfo.hwndItem;
8140
8143
8145 5, 50, 100, 20, parent, NULL,
8147 ok(button != 0, "Failed to create button window\n");
8148
8151 SendMessageA(combo, WM_SETFOCUS, 0, (LPARAM)edit);
8153 ok_sequence(WMSetFocusComboBoxSeq, "WM_SETFOCUS on a ComboBox", TRUE);
8154
8159 ok_sequence(SetFocusButtonSeq, "SetFocus on a Button", TRUE);
8160
8161 SendMessageA(combo, WM_SETTEXT, 0, (LPARAM)"Wine Test");
8162
8165 SetFocus(combo);
8167 ok_sequence(SetFocusComboBoxSeq, "SetFocus on a ComboBox", TRUE);
8168
8173 ok_sequence(SetFocusButtonSeq2, "SetFocus on a Button (2)", TRUE);
8174
8175 SetFocus(combo);
8176 SendMessageA(combo, WM_SETREDRAW, FALSE, 0);
8179 SendMessageA(combo, CB_SETCURSEL, 0, 0);
8181 ok_sequence(SetCurSelComboSeq_edit, "CB_SETCURSEL on a ComboBox with edit control", FALSE);
8182
8184 DestroyWindow(combo);
8185
8186 combo = CreateWindowExA(0, "my_combobox_class", "test",
8188 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL);
8189 ok(combo != 0, "Failed to create combobox window\n");
8190
8191 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0");
8192 ok(ret == 0, "expected 0, got %Id\n", ret);
8193
8194 cbInfo.cbSize = sizeof(COMBOBOXINFO);
8195 SetLastError(0xdeadbeef);
8196 res = GetComboBoxInfo(combo, &cbInfo);
8197 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8198 lbox = cbInfo.hwndList;
8202
8204 SendMessageA(combo, CB_SETCURSEL, 0, 0);
8206 ok_sequence(SetCurSelComboSeq, "CB_SETCURSEL on a ComboBox", FALSE);
8207
8208 ShowWindow(combo, SW_HIDE);
8211 SendMessageA(combo, CB_SETCURSEL, 0, 0);
8213 ok_sequence(SetCurSelComboSeq2, "CB_SETCURSEL on a ComboBox", FALSE);
8214
8215 DestroyWindow(combo);
8217}
8218
8219/****************** WM_IME_KEYDOWN message test *******************/
8220
8221static const struct message WmImeKeydownMsgSeq_0[] =
8222{
8224 { WM_CHAR, wparam, 'A' },
8225 { 0 }
8226};
8227
8228static const struct message WmImeKeydownMsgSeq_1[] =
8229{
8232 { 0 }
8233};
8234
8236{
8237 struct recvd_message msg;
8238
8239 msg.hwnd = hwnd;
8240 msg.message = message;
8241 msg.flags = wparam|lparam;
8242 msg.wParam = wParam;
8243 msg.lParam = lParam;
8244 msg.descr = "wmime_keydown";
8245 add_message(&msg);
8246
8248}
8249
8251{
8252 WNDCLASSA cls;
8253
8254 ZeroMemory(&cls, sizeof(WNDCLASSA));
8256 cls.hInstance = GetModuleHandleA(0);
8257 cls.lpszClassName = "wmime_keydown_class";
8258 register_class(&cls);
8259}
8260
8262{
8263 HWND hwnd;
8264 MSG msg;
8265
8266 if (winetest_debug > 1) trace("Message sequences by WM_IME_KEYDOWN\n");
8267
8269 hwnd = CreateWindowExA(0, "wmime_keydown_class", NULL, WS_OVERLAPPEDWINDOW,
8270 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
8271 NULL, NULL, 0);
8272 flush_events();
8274
8276 SendMessageA(hwnd, WM_CHAR, 'A', 1);
8277 ok_sequence(WmImeKeydownMsgSeq_0, "WM_IME_KEYDOWN 0", FALSE);
8278
8279 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) )
8280 {
8283 }
8284 ok_sequence(WmImeKeydownMsgSeq_1, "WM_IME_KEYDOWN 1", FALSE);
8285
8287}
8288
8289/************* painting message test ********************/
8290
8292{
8293 DWORD i, size;
8294 RGNDATA *data = NULL;
8295 RECT *rect;
8296
8297 if (!hrgn)
8298 {
8299 printf( "null region\n" );
8300 return;
8301 }
8302 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
8303 if (!(data = malloc( size ))) return;
8305 printf("%ld rects:", data->rdh.nCount );
8306 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
8307 printf( " %s", wine_dbgstr_rect( rect ));
8308 printf("\n");
8309 free( data );
8310}
8311
8312#define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn )
8313static void check_update_rgn_( int line, HWND hwnd, HRGN hrgn )
8314{
8315 INT ret;
8316 RECT r1, r2;
8317 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
8318 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
8319
8320 ret = GetUpdateRgn( hwnd, update, FALSE );
8321 ok( ret != ERROR, "GetUpdateRgn failed\n" );
8322 if (ret == NULLREGION)
8323 {
8324 ok_(__FILE__,line)( !hrgn, "Update region shouldn't be empty\n" );
8325 }
8326 else
8327 {
8328 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
8329 {
8330 ok_(__FILE__,line)( 0, "Regions are different\n" );
8331 if (winetest_debug > 0)
8332 {
8333 printf( "Update region: " );
8334 dump_region( update );
8335 printf( "Wanted region: " );
8336 dump_region( hrgn );
8337 }
8338 }
8339 }
8340 GetRgnBox( update, &r1 );
8341 GetUpdateRect( hwnd, &r2, FALSE );
8342 ok_(__FILE__,line)( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n",
8344
8345 DeleteObject( tmp );
8346 DeleteObject( update );
8347}
8348
8349static const struct message WmInvalidateRgn[] = {
8350 { WM_NCPAINT, sent },
8352 { 0 }
8353};
8354
8355static const struct message WmGetUpdateRect[] = {
8356 { WM_NCPAINT, sent },
8358 { WM_PAINT, sent },
8359 { 0 }
8360};
8361
8362static const struct message WmInvalidateFull[] = {
8363 { WM_NCPAINT, sent|wparam, 1 },
8365 { 0 }
8366};
8367
8368static const struct message WmInvalidateErase[] = {
8369 { WM_NCPAINT, sent|wparam, 1 },
8371 { WM_ERASEBKGND, sent },
8372 { 0 }
8373};
8374
8375static const struct message WmInvalidatePaint[] = {
8376 { WM_PAINT, sent },
8379 { 0 }
8380};
8381
8382static const struct message WmInvalidateErasePaint[] = {
8383 { WM_PAINT, sent },
8387 { 0 }
8388};
8389
8390static const struct message WmInvalidateErasePaint2[] = {
8391 { WM_PAINT, sent },
8395 { 0 }
8396};
8397
8398static const struct message WmErase[] = {
8399 { WM_ERASEBKGND, sent },
8400 { 0 }
8401};
8402
8403static const struct message WmPaint[] = {
8404 { WM_PAINT, sent },
8405 { 0 }
8406};
8407
8408static const struct message WmParentOnlyPaint[] = {
8409 { WM_PAINT, sent|parent },
8410 { 0 }
8411};
8412
8413static const struct message WmInvalidateParent[] = {
8414 { WM_NCPAINT, sent|parent },
8417 { 0 }
8418};
8419
8420static const struct message WmInvalidateParentChild[] = {
8421 { WM_NCPAINT, sent|parent },
8424 { WM_NCPAINT, sent },
8426 { WM_ERASEBKGND, sent },
8427 { 0 }
8428};
8429
8430static const struct message WmInvalidateParentChild2[] = {
8432 { WM_NCPAINT, sent },
8434 { WM_ERASEBKGND, sent },
8435 { 0 }
8436};
8437
8438static const struct message WmParentPaint[] = {
8439 { WM_PAINT, sent|parent },
8440 { WM_PAINT, sent },
8441 { 0 }
8442};
8443
8444static const struct message WmParentPaintNc[] = {
8445 { WM_PAINT, sent|parent },
8446 { WM_PAINT, sent },
8451 { 0 }
8452};
8453
8454static const struct message WmChildPaintNc[] = {
8455 { WM_PAINT, sent },
8459 { 0 }
8460};
8461
8462static const struct message WmParentErasePaint[] = {
8463 { WM_PAINT, sent|parent },
8467 { WM_PAINT, sent },
8471 { 0 }
8472};
8473
8474static const struct message WmParentOnlyNcPaint[] = {
8475 { WM_PAINT, sent|parent },
8478 { 0 }
8479};
8480
8481static const struct message WmSetParentStyle[] = {
8482 { WM_STYLECHANGING, sent|parent },
8483 { WM_STYLECHANGED, sent|parent },
8484 { 0 }
8485};
8486
8487static void test_paint_messages(void)
8488{
8489 BOOL ret;
8490 RECT rect, rect2;
8491 DWORD style;
8492 POINT pt;
8493 MSG msg;
8494 HWND hparent, hchild;
8495 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
8496 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
8497 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
8498 100, 100, 200, 200, 0, 0, 0, NULL);
8499 ok (hwnd != 0, "Failed to create overlapped window\n");
8500
8502 UpdateWindow( hwnd );
8503 flush_events();
8505
8506 check_update_rgn( hwnd, 0 );
8507 SetRectRgn( hrgn, 10, 10, 20, 20 );
8509 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8511 SetRectRgn( hrgn2, 20, 20, 30, 30 );
8513 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8516 /* validate everything */
8518 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8519 check_update_rgn( hwnd, 0 );
8520
8521 /* test empty region */
8522 SetRectRgn( hrgn, 10, 10, 10, 15 );
8524 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8525 check_update_rgn( hwnd, 0 );
8526 /* test empty rect */
8527 SetRect( &rect, 10, 10, 10, 15 );
8529 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8530 check_update_rgn( hwnd, 0 );
8531
8532 /* test a zeroed rectangle */
8534 SetRect( &rect, 0, 0, 0, 0 );
8536 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8537 check_update_rgn( hwnd, 0 );
8538
8539 /* a well ordered rectangle */
8541 SetRect( &rect, 10, 5, 17, 21 );
8543 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8544 SetRectRgn( hrgn, 10, 5, 17, 21 );
8546
8547 /* empty rectangle, top and bottom are swapped but left and right have
8548 the same value */
8550 SetRect( &rect, 5, 30, 5, 10 );
8552 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8553 check_update_rgn( hwnd, 0 );
8554
8555 /* empty rectangle, left and right are swapped but top and bottom have
8556 the same value */
8558 SetRect( &rect, 17, 10, 5, 10 );
8560 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8561 check_update_rgn( hwnd, 0 );
8562
8563 /* Left and right are swapped */
8565 SetRect( &rect, 21, 12, 7, 30 );
8567 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8568 SetRectRgn( hrgn, 7, 12, 21, 30 );
8570
8571 /* Top and bottom are swapped */
8573 SetRect( &rect, 7, 30, 21, 12 );
8575 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8576 SetRectRgn( hrgn, 7, 12, 21, 30 );
8578
8579 /* both reference points are swapped */
8581 SetRect( &rect, 21, 30, 7, 12 );
8583 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
8584 SetRectRgn( hrgn, 7, 12, 21, 30 );
8586
8587 /* flush pending messages */
8588 flush_events();
8590
8591 GetClientRect( hwnd, &rect );
8593 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
8594 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8595 */
8596 SetRectEmpty( &rect );
8597 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) failed\n");
8599 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8600 flush_events();
8601 ok_sequence( WmPaint, "Paint", FALSE );
8603 check_update_rgn( hwnd, 0 );
8604
8605 SetRectEmpty( &rect );
8607 "RedrawWindow failed\n");
8608 check_update_rgn( hwnd, 0 );
8609
8610 SetRectEmpty( &rect );
8612 "RedrawWindow failed\n");
8613 check_update_rgn( hwnd, 0 );
8614
8615 GetWindowRect( hwnd, &rect );
8617 "RedrawWindow failed\n");
8618 check_update_rgn( hwnd, 0 );
8619
8620 flush_events();
8622 "RedrawWindow failed\n");
8624 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8625 flush_events();
8626 ok_sequence( WmPaint, "Paint", FALSE );
8628 check_update_rgn( hwnd, 0 );
8629
8632 "RedrawWindow failed\n");
8634 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */
8635 "region should be null (%d)\n", ret );
8636 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8638 flush_events();
8639
8642 "RedrawWindow failed\n");
8644 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */
8645 "region should be null (%d)\n", ret );
8646 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8648 flush_events();
8649
8652 "RedrawWindow failed\n");
8654 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8655 flush_events();
8656 ok_sequence( WmPaint, "Paint", FALSE );
8658 check_update_rgn( hwnd, 0 );
8659
8661 "RedrawWindow failed\n");
8662 check_update_rgn( hwnd, 0 );
8663
8665 "RedrawWindow failed\n");
8667 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8668 flush_events();
8669 ok_sequence( WmPaint, "Paint", FALSE );
8671 check_update_rgn( hwnd, 0 );
8672
8673 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
8674 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8675 */
8676 SetRectEmpty( &rect );
8677 if (ValidateRect(0, &rect) && /* not supported on Win9x */
8678 GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */
8679 {
8681 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8682 flush_events();
8683 ok_sequence( WmPaint, "Paint", FALSE );
8685 check_update_rgn( hwnd, 0 );
8686 }
8687
8688 SetLastError(0xdeadbeef);
8689 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n");
8691 "wrong error code %ld\n", GetLastError());
8692 check_update_rgn( hwnd, 0 );
8693 flush_events();
8694 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
8695
8696 SetLastError(0xdeadbeef);
8697 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n");
8699 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8700 "wrong error code %ld\n", GetLastError());
8701 check_update_rgn( hwnd, 0 );
8702 flush_events();
8703 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
8704
8705 SetLastError(0xdeadbeef);
8706 ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n");
8708 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8709 "wrong error code %ld\n", GetLastError());
8710 check_update_rgn( hwnd, 0 );
8711 flush_events();
8712 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
8713
8714 /* now with frame */
8715 SetRectRgn( hrgn, -5, -5, 20, 20 );
8716
8717 /* flush pending messages */
8718 flush_events();
8721 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
8722
8723 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
8725
8728 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
8729
8732 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
8733
8734 GetClientRect( hwnd, &rect );
8737
8740 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8741
8744 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
8745 check_update_rgn( hwnd, 0 );
8746
8749 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
8750 check_update_rgn( hwnd, 0 );
8751
8753 SetRectRgn( hrgn, 0, 0, 100, 100 );
8755 SetRectRgn( hrgn, 0, 0, 50, 100 );
8757 SetRectRgn( hrgn, 50, 0, 100, 100 );
8760 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
8761 check_update_rgn( hwnd, 0 );
8762
8764 SetRectRgn( hrgn, 0, 0, 100, 100 );
8766 SetRectRgn( hrgn, 0, 0, 100, 50 );
8768 ok_sequence( WmErase, "Erase", FALSE );
8769 SetRectRgn( hrgn, 0, 50, 100, 100 );
8771
8773 SetRectRgn( hrgn, 0, 0, 100, 100 );
8775 SetRectRgn( hrgn, 0, 0, 50, 50 );
8777 ok_sequence( WmPaint, "Paint", FALSE );
8778
8780 SetRectRgn( hrgn, -4, -4, -2, -2 );
8782 SetRectRgn( hrgn, -200, -200, -198, -198 );
8784 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
8785
8787 SetRectRgn( hrgn, -4, -4, -2, -2 );
8789 SetRectRgn( hrgn, -4, -4, -3, -3 );
8791 SetRectRgn( hrgn, 0, 0, 1, 1 );
8793 ok_sequence( WmPaint, "Paint", FALSE );
8794
8796 SetRectRgn( hrgn, -4, -4, -1, -1 );
8799 /* make sure no WM_PAINT was generated */
8800 flush_events();
8801 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
8802
8804 SetRectRgn( hrgn, -4, -4, -1, -1 );
8806 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
8807 {
8808 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
8809 {
8810 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
8812 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
8814 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
8815 /* this will send WM_NCPAINT and validate the non client area */
8816 ret = GetUpdateRect( hwnd, &rect, TRUE );
8817 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
8818 }
8820 }
8821 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
8822
8824
8825 /* now test with a child window */
8826
8827 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
8828 100, 100, 200, 200, 0, 0, 0, NULL);
8829 ok (hparent != 0, "Failed to create parent window\n");
8830
8831 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
8832 10, 10, 100, 100, hparent, 0, 0, NULL);
8833 ok (hchild != 0, "Failed to create child window\n");
8834
8835 ShowWindow( hparent, SW_SHOW );
8836 UpdateWindow( hparent );
8837 UpdateWindow( hchild );
8838 flush_events();
8841
8842 SetRect( &rect, 0, 0, 50, 50 );
8843 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8845 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
8846
8847 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8848 pt.x = pt.y = 0;
8849 MapWindowPoints( hchild, hparent, &pt, 1 );
8850 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
8851 check_update_rgn( hchild, hrgn );
8852 SetRectRgn( hrgn, 0, 0, 50, 50 );
8853 check_update_rgn( hparent, hrgn );
8854 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
8855 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
8856 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
8857 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
8858
8859 flush_events();
8860 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
8861
8863 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
8864 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
8865 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
8866 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
8867
8868 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
8870 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
8871
8875 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
8876 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
8877
8878 /* flush all paint messages */
8879 flush_events();
8881
8882 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
8884 SetRectRgn( hrgn, 0, 0, 50, 50 );
8885 check_update_rgn( hparent, hrgn );
8886 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
8887 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8888 SetRectRgn( hrgn, 0, 0, 50, 50 );
8889 check_update_rgn( hparent, hrgn );
8890
8891 /* flush all paint messages */
8892 flush_events();
8895
8896 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
8897 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8898 SetRectRgn( hrgn, 0, 0, 50, 50 );
8899 check_update_rgn( hparent, hrgn );
8900 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
8901 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8902 SetRectRgn( hrgn2, 10, 10, 50, 50 );
8904 check_update_rgn( hparent, hrgn );
8905 /* flush all paint messages */
8906 flush_events();
8908
8909 /* same as above but parent gets completely validated */
8910 SetRect( &rect, 20, 20, 30, 30 );
8911 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8912 SetRectRgn( hrgn, 20, 20, 30, 30 );
8913 check_update_rgn( hparent, hrgn );
8914 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
8915 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8916 check_update_rgn( hparent, 0 ); /* no update region */
8917 flush_events();
8918 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
8919
8920 /* make sure RDW_VALIDATE on child doesn't have the same effect */
8922 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8923 SetRectRgn( hrgn, 20, 20, 30, 30 );
8924 check_update_rgn( hparent, hrgn );
8925 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
8926 SetRectRgn( hrgn, 20, 20, 30, 30 );
8927 check_update_rgn( hparent, hrgn );
8928
8929 /* same as above but normal WM_PAINT doesn't validate parent */
8931 SetRect( &rect, 20, 20, 30, 30 );
8932 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8933 SetRectRgn( hrgn, 20, 20, 30, 30 );
8934 check_update_rgn( hparent, hrgn );
8935 /* no WM_PAINT in child while parent still pending */
8936 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8937 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
8938 while (PeekMessageA( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8939 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
8940
8942 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8943 /* no WM_PAINT in child while parent still pending */
8944 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8945 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
8947 /* now that parent is valid child should get WM_PAINT */
8948 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8949 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8950 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8951 ok_sequence( WmEmptySeq, "No other message", FALSE );
8952
8953 /* same thing with WS_CLIPCHILDREN in parent */
8956 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
8957 /* changing style invalidates non client area, but we need to invalidate something else to see it */
8958 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
8959 ok_sequence( WmEmptySeq, "No message", FALSE );
8960 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
8961 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
8962
8965 SetRectRgn( hrgn, 20, 20, 30, 30 );
8966 check_update_rgn( hparent, hrgn );
8967 /* no WM_PAINT in child while parent still pending */
8968 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8969 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
8970 /* WM_PAINT in parent first */
8971 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8972 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
8973
8974 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
8976 SetRect( &rect, 0, 0, 30, 30 );
8978 SetRectRgn( hrgn, 0, 0, 30, 30 );
8979 check_update_rgn( hparent, hrgn );
8980 flush_events();
8981 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
8982
8983 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8985 SetRect( &rect, -10, 0, 30, 30 );
8987 SetRect( &rect, 0, 0, 20, 20 );
8988 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
8989 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
8990 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
8991
8992 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8994 SetRect( &rect, -10, 0, 30, 30 );
8996 SetRect( &rect, 0, 0, 100, 100 );
8997 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
8998 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
8999 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
9000 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
9001 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
9002
9003 /* WS_CLIPCHILDREN doesn't exclude children from update region */
9006 GetClientRect( hparent, &rect );
9008 check_update_rgn( hparent, hrgn );
9009 flush_events();
9010
9012 GetClientRect( hparent, &rect );
9014 check_update_rgn( hparent, hrgn );
9015 flush_events();
9016
9017 /* test RDW_INTERNALPAINT behavior */
9018
9021 flush_events();
9022 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
9023
9025 flush_events();
9026 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
9027
9028 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
9029 flush_events();
9030 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
9031
9032 style = GetWindowLongA(hparent, GWL_STYLE);
9033 ok(style & WS_CLIPCHILDREN, "Got unexpected style %#lx.\n", style);
9034 UpdateWindow( hparent );
9035 flush_events();
9037 if (winetest_debug > 1) trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
9039 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
9041 flush_events();
9042 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
9043
9044 UpdateWindow( hparent );
9045 flush_events();
9047 if (winetest_debug > 1) trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
9049 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
9051 flush_events();
9052 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
9053
9055 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
9056 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
9057 flush_events();
9058 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
9059
9060 style = GetWindowLongA(hparent, GWL_STYLE);
9061 ok(!(style & WS_CLIPCHILDREN), "Got unexpected style %#lx.\n", style);
9062 UpdateWindow( hparent );
9063 flush_events();
9065 if (winetest_debug > 1) trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
9067 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
9069 flush_events();
9070 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
9071
9072 UpdateWindow( hparent );
9073 flush_events();
9075 if (winetest_debug > 1) trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
9077 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
9079 flush_events();
9080 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
9081
9082 ok(GetWindowLongA( hparent, GWL_STYLE ) & WS_VISIBLE, "parent should be visible\n");
9083 ok(GetWindowLongA( hchild, GWL_STYLE ) & WS_VISIBLE, "child should be visible\n");
9084
9085 UpdateWindow( hparent );
9086 flush_events();
9088 if (winetest_debug > 1) trace("testing SetWindowPos(-10000, -10000) on child\n");
9089 SetWindowPos( hchild, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER );
9090 check_update_rgn( hchild, 0 );
9091 flush_events();
9092
9093#if 0 /* this one doesn't pass under Wine yet */
9094 UpdateWindow( hparent );
9095 flush_events();
9097 if (winetest_debug > 1) trace("testing ShowWindow(SW_MINIMIZE) on child\n");
9098 ShowWindow( hchild, SW_MINIMIZE );
9099 check_update_rgn( hchild, 0 );
9100 flush_events();
9101#endif
9102
9103 UpdateWindow( hparent );
9104 flush_events();
9106 if (winetest_debug > 1) trace("testing SetWindowPos(-10000, -10000) on parent\n");
9107 SetWindowPos( hparent, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER );
9108 check_update_rgn( hparent, 0 );
9109 flush_events();
9110
9112 DestroyWindow( hparent );
9113 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
9114
9115 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
9116
9117 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE,
9118 100, 100, 200, 200, 0, 0, 0, NULL);
9119 ok (hparent != 0, "Failed to create parent window\n");
9120
9121 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
9122 10, 10, 100, 100, hparent, 0, 0, NULL);
9123 ok (hchild != 0, "Failed to create child window\n");
9124
9125 ShowWindow( hparent, SW_SHOW );
9126 UpdateWindow( hparent );
9127 UpdateWindow( hchild );
9128 flush_events();
9130
9131 /* moving child outside of parent boundaries changes update region */
9132 SetRect( &rect, 0, 0, 40, 40 );
9133 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
9134 SetRectRgn( hrgn, 0, 0, 40, 40 );
9135 check_update_rgn( hchild, hrgn );
9136 MoveWindow( hchild, -10, 10, 100, 100, FALSE );
9137 SetRectRgn( hrgn, 10, 0, 40, 40 );
9138 check_update_rgn( hchild, hrgn );
9139 MoveWindow( hchild, -10, -10, 100, 100, FALSE );
9140 SetRectRgn( hrgn, 10, 10, 40, 40 );
9141 check_update_rgn( hchild, hrgn );
9142
9143 /* moving parent off-screen does too */
9144 SetRect( &rect, 0, 0, 100, 100 );
9146 SetRectRgn( hrgn, 0, 0, 100, 100 );
9147 check_update_rgn( hparent, hrgn );
9148 SetRectRgn( hrgn, 10, 10, 40, 40 );
9149 check_update_rgn( hchild, hrgn );
9150 MoveWindow( hparent, -20, -20, 200, 200, FALSE );
9151 GetUpdateRect( hparent, &rect2, FALSE );
9152 if (!EqualRect( &rect2, &rect )) /* Win 8 and later don't crop update to screen */
9153 {
9154 rect.left += 20;
9155 rect.top += 20;
9156 }
9158 check_update_rgn( hparent, hrgn );
9159 SetRectRgn( hrgn, rect.left + 10, rect.top + 10, 40, 40 );
9160 check_update_rgn( hchild, hrgn );
9161
9162 /* invalidated region is cropped by the parent rects */
9163 SetRect( &rect, 0, 0, 50, 50 );
9164 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
9165 SetRectRgn( hrgn, rect2.left + 10, rect2.top + 10, 50, 50 );
9166 check_update_rgn( hchild, hrgn );
9167
9168 DestroyWindow( hparent );
9169 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
9171
9172 DeleteObject( hrgn );
9174}
9175
9176static void visualize_region_differences( HWND hwnd, HWND hother, HRGN hrgn_expect, HRGN hrgn_actual )
9177{
9178 HBRUSH b_expectonly, b_actualonly, b_intersect;
9179 HRGN hrgn_intersect;
9180 HWND hstatic, hshow, hhide;
9181 HDC hdc, hdctmp;
9183 MSG msg;
9184 RECT rect;
9185 DWORD start_time, elapsed, timeout = 60 * 1000;
9186 BOOL toggle = TRUE, stop = FALSE;
9187
9188 start_time = GetTickCount();
9189
9190 b_expectonly = CreateSolidBrush( RGB( 64, 64, 255 ));
9191 b_actualonly = CreateSolidBrush( RGB( 255, 64, 64 ));
9192 b_intersect = CreateSolidBrush( RGB( 159, 64, 159 ));
9193
9194 hrgn_intersect = CreateRectRgn( 0, 0, 0, 0 );
9195 CombineRgn( hrgn_intersect, hrgn_expect, hrgn_actual, RGN_AND );
9196
9197 GetClientRect( hwnd, &rect );
9198 hdc = GetDC( hwnd );
9200 hdctmp = CreateCompatibleDC( hdc );
9201 ReleaseDC( hwnd, hdc );
9202
9203 SelectObject( hdctmp, hbitmap );
9204 FillRgn( hdctmp, hrgn_expect, b_expectonly );
9205 FillRgn( hdctmp, hrgn_actual, b_actualonly );
9206 FillRgn( hdctmp, hrgn_intersect, b_intersect );
9207
9208 DeleteObject( hdctmp );
9209 DeleteObject( hrgn_intersect );
9210 DeleteObject( b_intersect );
9211 DeleteObject( b_actualonly );
9212 DeleteObject( b_expectonly );
9213
9214 hstatic = CreateWindowExA( 0, WC_STATICA, "", WS_CHILD | SS_BITMAP,
9215 0, 0, rect.right, rect.bottom, hwnd, 0, 0, NULL );
9217
9218 hshow = hstatic;
9219 hhide = hother;
9220
9221 for (;;)
9222 {
9223 if (stop) toggle = hshow == hother;
9224 if (toggle)
9225 {
9226 HWND htmp;
9227 HDWP hdwp;
9228
9229 hdwp = BeginDeferWindowPos( !!hhide + !!hshow );
9230 if (hhide)
9231 {
9232 DeferWindowPos( hdwp, hhide, NULL, 0, 0, 0, 0,
9234 }
9235 if (hshow)
9236 {
9237 DeferWindowPos( hdwp, hshow, HWND_TOP, 0, 0, 0, 0,
9239 }
9240 EndDeferWindowPos( hdwp );
9241
9242 htmp = hshow;
9243 hshow = hhide;
9244 hhide = htmp;
9245 toggle = FALSE;
9246 }
9247 if (stop) break;
9248 if ((elapsed = GetTickCount() - start_time) >= timeout)
9249 {
9250 stop = TRUE;
9251 continue;
9252 }
9254 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
9255 {
9258 if (msg.message == WM_MOUSEMOVE)
9259 {
9260 start_time = GetTickCount();
9261 }
9262 else if (msg.message == WM_LBUTTONUP || (msg.message == WM_CHAR && msg.wParam == VK_SPACE))
9263 {
9264 toggle = !toggle;
9265 }
9266 else if (msg.message == WM_RBUTTONUP || (msg.message == WM_CHAR && msg.wParam == VK_RETURN))
9267 {
9268 stop = TRUE;
9269 }
9270 }
9271 }
9272
9273 DestroyWindow( hstatic );
9275}
9276
9277#define subtest_swp_paint_regions(w,p,c) subtest_swp_paint_regions_(__LINE__,w,p,c)
9278
9279static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR parent_class, LPCSTR child_class )
9280{
9281 static const struct exposure_test {
9282 int ex_style, style;
9283 BOOL shuffle_zorder;
9284 } exposure_tests[] = {
9285 { 0, WS_CLIPCHILDREN, FALSE },
9286 { 0, 0, FALSE },
9288 { WS_EX_COMPOSITED, 0, FALSE },
9289 { WS_EX_COMPOSITED, 0, TRUE },
9290 };
9291 size_t i;
9292 HWND htoplevel = NULL, hparent, hchild, hauxchild;
9293 const RECT rect_old = { 10, 10, 100, 100 };
9294 HRGN hrgn_old_vis = CreateRectRgn( 0, 0, 0, 0 );
9295 HRGN hrgn_new_vis = CreateRectRgn( 0, 0, 0, 0 );
9296 HRGN hrgn_expect = CreateRectRgn( 0, 0, 0, 0 );
9297 HRGN hrgn_actual = CreateRectRgn( 0, 0, 0, 0 );
9298 HRGN hrgn_old_vis_child = CreateRectRgn( 0, 0, 0, 0 );
9299 HRGN hrgn_new_vis_child = CreateRectRgn( 0, 0, 0, 0 );
9300 HRGN hrgn_expect_child = CreateRectRgn( 0, 0, 0, 0 );
9301 HRGN hrgn_actual_child = CreateRectRgn( 0, 0, 0, 0 );
9302 int base_style;
9303 BOOL is_composition_possible, has_parentdc_anomaly;
9304 WNDCLASSA parent_wc;
9305
9306 if (wrap_toplevel)
9307 {
9308 htoplevel = CreateWindowExA( 0, "SimpleWindowClass", "Test toplevel", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
9309 100, 100, 400, 400, 0, 0, 0, NULL );
9310 ok( htoplevel != 0, "Failed to create top-level window: %lu\n", GetLastError() );
9311 base_style = WS_CHILD | WS_VISIBLE;
9312 }
9313 else
9314 {
9315 base_style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
9316 }
9317
9318 ok( GetClassInfoA( GetModuleHandleA( NULL ), parent_class, &parent_wc ),
9319 "GetClassInfoA failed\n" );
9320
9321 is_composition_possible = (base_style & (WS_POPUP|WS_CHILD)) != WS_CHILD ||
9322 (parent_wc.style & CS_PARENTDC) == 0;
9323
9324 has_parentdc_anomaly = (base_style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
9325 (parent_wc.style & CS_PARENTDC) != 0;
9326
9327 hparent = CreateWindowExA( 0, parent_class, "Test parent", base_style,
9328 80, 80, 200, 200, htoplevel, 0, 0, NULL );
9329 ok( hparent != 0, "Creating parent window (%s) returned error %lu\n",
9330 debugstr_a( parent_class ), GetLastError() );
9331
9332 hchild = CreateWindowExA( 0, child_class, "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
9333 rect_old.left, rect_old.top,
9334 rect_old.right - rect_old.left, rect_old.bottom - rect_old.top,
9335 hparent, 0, 0, NULL );
9336 ok( hchild != 0, "Creating child window (%s) returned error %lu\n",
9337 debugstr_a( child_class ), GetLastError() );
9338
9339 hauxchild = CreateWindowExA( 0, child_class, "Auxiliary child for z order test", WS_CHILD | WS_VISIBLE,
9340 110, 0, 0, 0, hparent, 0, 0, NULL );
9341 ok( hauxchild != 0, "Creating child window (%s) returned error %lu\n",
9342 debugstr_a( child_class ), GetLastError() );
9343
9344 SetWindowPos( htoplevel ? htoplevel : hparent, NULL, 0, 0, 0, 0,
9346
9347 for (i = 0; i < ARRAY_SIZE(exposure_tests); i++)
9348 {
9349 const struct exposure_test *extest = &exposure_tests[i];
9350 BOOL has_ws_ex_composited = (extest->ex_style & WS_EX_COMPOSITED) != 0;
9351 BOOL is_composited = is_composition_possible && has_ws_ex_composited;
9352 BOOL is_zorder_redraw = is_composited && extest->shuffle_zorder;
9353 int delta;
9354
9355 winetest_push_context( "%d: SetWindowPos redraw #%Id (ex_style = %#x, style = %#x, shuffle_zorder = %d)",
9356 line, i, extest->ex_style, extest->style, extest->shuffle_zorder );
9357
9358 SetWindowLongA( hparent, GWL_EXSTYLE, extest->ex_style );
9359 SetWindowLongA( hparent, GWL_STYLE, base_style | extest->style );
9361
9362 for (delta = -20; delta <= 0; delta += 20)
9363 {
9364 RECT rect_old_vis, rect_new, rect_new_vis;
9365 RECT rect_parent_clip, rect_child_clip;
9366 RECT rect_old_vis_child, rect_new_vis_child;
9367 BOOL rgn_ok;
9368
9369 winetest_push_context( "delta = %+d", delta );
9370
9371 SetWindowPos( hchild, HWND_TOP,
9372 rect_old.left,
9373 rect_old.top,
9374 rect_old.right - rect_old.left,
9375 rect_old.bottom - rect_old.top,
9377
9378 rect_new = rect_old;
9379 OffsetRect( &rect_new, delta, delta );
9380
9381 rect_old_vis_child = rect_old;
9382 MapWindowPoints( hparent, hchild, (POINT *)&rect_old_vis_child, 2 );
9383
9384 SetRectRgn( hrgn_actual, 0, 0, 0, 0 );
9385 SetRectRgn( hrgn_actual_child, 0, 0, 0, 0 );
9386
9387 UpdateWindow( hparent );
9388 flush_events();
9389
9390 if (extest->shuffle_zorder)
9391 {
9392 /* bring sibling to top/bottom first so we can trigger z-order change */
9393 SetWindowPos( hauxchild, HWND_TOP, 0, 0, 0, 0,
9395 }
9396
9397 SetWindowPos( hchild, HWND_TOP,
9398 rect_new.left,
9399 rect_new.top,
9400 rect_new.right - rect_new.left,
9401 rect_new.bottom - rect_new.top,
9403 (extest->shuffle_zorder ? 0 : SWP_NOZORDER) );
9404
9405 ok( GetUpdateRgn( hparent, hrgn_actual, FALSE ) != ERROR,
9406 "GetUpdateRgn on parentshall succeed\n" );
9407 ok( GetUpdateRgn( hchild, hrgn_actual_child, FALSE ) != ERROR,
9408 "GetUpdateRgn on child shall succeed\n" );
9409
9410 /* Compute parent window expose region */
9411 GetClientRect( hparent, &rect_parent_clip );
9412 IntersectRect( &rect_old_vis, &rect_old, &rect_parent_clip );
9413 SetRectRgn( hrgn_old_vis, rect_old_vis.left, rect_old_vis.top, rect_old_vis.right, rect_old_vis.bottom );
9414 IntersectRect( &rect_new_vis, &rect_new, &rect_parent_clip );
9415 SetRectRgn( hrgn_new_vis, rect_new_vis.left, rect_new_vis.top, rect_new_vis.right, rect_new_vis.bottom );
9416
9417 if (!EqualRect( &rect_old, &rect_new ) || is_zorder_redraw)
9418 {
9419 CombineRgn( hrgn_expect, hrgn_old_vis, hrgn_new_vis, is_composited ? RGN_OR : RGN_DIFF );
9420 }
9421 else
9422 {
9423 SetRectRgn( hrgn_expect, 0, 0, 0, 0 );
9424 }
9425
9426 rgn_ok = EqualRgn( hrgn_expect, hrgn_actual );
9427 if (!rgn_ok && broken( has_parentdc_anomaly && is_composited /* Win7 */ ))
9428 {
9429 if (winetest_debug > 1)
9430 {
9431 trace( "Forcing non-composited update region (broken)\n" );
9432 }
9433 rgn_ok = 1;
9434 }
9435 else
9436 {
9437 ok( !!rgn_ok, "Parent update region shall match expected region\n" );
9438 }
9439
9440 if (!rgn_ok)
9441 {
9442 trace( "Expected parent update region: " );
9443 dump_region( hrgn_expect );
9444 trace( "Actual parent update region: " );
9445 dump_region( hrgn_actual );
9446 trace( "Old child window visible area: %s\n", wine_dbgstr_rect( &rect_old_vis ) );
9447 trace( "New child window visible area: %s\n", wine_dbgstr_rect( &rect_new_vis ) );
9448 }
9449
9451 {
9452 if (!rgn_ok)
9453 {
9454 visualize_region_differences( hparent, hchild, hrgn_expect, hrgn_actual );
9455 }
9456
9457 /* Let the position change be visible to the user */
9458 flush_events();
9459 }
9460
9461 rect_new_vis_child = rect_new;
9462 MapWindowPoints( hparent, hchild, (POINT *)&rect_new_vis_child, 2 );
9463
9464 /* Compute child window expose region */
9465 GetClientRect( hchild, &rect_child_clip );
9466 if (is_composited)
9467 {
9468 RECT rect_outer_clip;
9469 GetClientRect( hparent, &rect_outer_clip );
9470 MapWindowPoints( hparent, hchild, (POINT *)&rect_outer_clip, 2 );
9471 IntersectRect( &rect_child_clip, &rect_child_clip, &rect_outer_clip );
9472 }
9473 IntersectRect( &rect_old_vis_child, &rect_old_vis_child, &rect_child_clip );
9474 SetRectRgn( hrgn_old_vis_child, rect_old_vis_child.left, rect_old_vis_child.top, rect_old_vis_child.right, rect_old_vis_child.bottom );
9475 IntersectRect( &rect_new_vis_child, &rect_new_vis_child, &rect_child_clip );
9476 SetRectRgn( hrgn_new_vis_child, rect_new_vis_child.left, rect_new_vis_child.top, rect_new_vis_child.right, rect_new_vis_child.bottom );
9477
9478 if (!EqualRect( &rect_old, &rect_new ) || is_zorder_redraw)
9479 {
9480 CombineRgn( hrgn_expect_child, hrgn_new_vis_child, hrgn_old_vis_child, is_composited ? RGN_OR : RGN_DIFF );
9481 }
9482 else
9483 {
9484 SetRectRgn( hrgn_expect_child, 0, 0, 0, 0 );
9485 }
9486
9487 rgn_ok = EqualRgn( hrgn_expect_child, hrgn_actual_child );
9488 if (!rgn_ok && broken( has_parentdc_anomaly && is_composited /* Win7 */ ))
9489 {
9490 if (winetest_debug > 1)
9491 {
9492 trace( "Forcing non-composited update region (broken)\n" );
9493 }
9494 rgn_ok = 1;
9495 }
9496 else
9497 {
9498 ok( !!rgn_ok, "Child update region shall match expected region\n" );
9499 }
9500
9501 if (!rgn_ok)
9502 {
9503 trace( "Expected child update region: " );
9504 dump_region( hrgn_expect_child );
9505 trace( "Actual child update region: " );
9506 dump_region( hrgn_actual_child );
9507 trace( "Old child window client visible area: %s\n", wine_dbgstr_rect( &rect_old_vis_child ) );
9508 trace( "New child window client visible area: %s\n", wine_dbgstr_rect( &rect_new_vis_child ) );
9509 }
9510
9512 {
9513 if (!rgn_ok)
9514 {
9515 visualize_region_differences( hchild, NULL, hrgn_expect_child, hrgn_actual_child );
9516 }
9517
9518 /* Let the position change be visible to the user */
9519 flush_events();
9520 }
9521
9523 }
9524
9526 }
9527
9528 DestroyWindow( hauxchild );
9529 DestroyWindow( hchild );
9530 DestroyWindow( hparent );
9531 if (htoplevel) DestroyWindow( htoplevel );
9532
9533 DeleteObject( hrgn_actual_child );
9534 DeleteObject( hrgn_expect_child );
9535 DeleteObject( hrgn_new_vis_child );
9536 DeleteObject( hrgn_old_vis_child );
9537 DeleteObject( hrgn_actual );
9538 DeleteObject( hrgn_expect );
9539 DeleteObject( hrgn_new_vis );
9540 DeleteObject( hrgn_old_vis );
9541}
9542
9543static void test_swp_paint_regions(void)
9544{
9545 subtest_swp_paint_regions( 1, "SimpleWindowClass", "SimpleWindowClass" );
9546 subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClass" );
9547 subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClassWithParentDC" );
9548 subtest_swp_paint_regions( 0, "SimpleWindowClassWithParentDC", "SimpleWindowClass" );
9549}
9550
9552{
9553 HRGN hrgn_actual_child = CreateRectRgn( 0, 0, 0, 0 );
9554 HRGN hrgn_actual = CreateRectRgn( 0, 0, 0, 0 );
9555 const RECT rect_1 = { 10, 10, 100, 100 };
9556 const RECT rect_2 = { 20, 20, 120, 120 };
9557 RECT rect_expect_child, rect_expect;
9558 RECT rect_actual_child, rect_actual;
9559 HWND hparent, hchild;
9560 int result;
9561
9562 hparent = CreateWindowExA( 0, "SimpleWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
9563 80, 80, 200, 200, NULL, 0, 0, NULL );
9564 ok( hparent != 0, "Creating parent window returned error %lu\n", GetLastError() );
9565
9566 hchild = CreateWindowExA( 0, "SimpleWindowClass", "Test child", WS_CHILD | WS_BORDER,
9567 0, 0, 100, 100, hparent, 0, 0, NULL );
9568 ok( hchild != 0, "Creating child window returned error %lu\n", GetLastError() );
9569
9570 if (winetest_debug > 1) trace("testing show window (no move / size)\n");
9571
9572 SetWindowPos( hchild, HWND_TOP,
9573 rect_1.left, rect_1.top, rect_1.right - rect_1.left, rect_1.bottom - rect_1.top,
9575
9576 UpdateWindow( hparent );
9577 flush_events();
9578
9579 SetWindowPos( hchild, HWND_TOP, 0, 0, 0, 0,
9581
9582 ok( GetUpdateRgn( hparent, hrgn_actual, FALSE ) != ERROR,
9583 "GetUpdateRgn on parent shall succeed\n" );
9584 ok( GetUpdateRgn( hchild, hrgn_actual_child, FALSE ) != ERROR,
9585 "GetUpdateRgn on child shall succeed\n" );
9586
9587 result = GetRgnBox( hrgn_actual, &rect_actual );
9588 ok( result == SIMPLEREGION, "GetRgnBox (on parent) returned %d\n", result );
9589 if (result == COMPLEXREGION) dump_region( hrgn_actual );
9590
9591 rect_expect = rect_1;
9592 ok( EqualRect( &rect_actual, &rect_expect ), "parent update region: got %s, expected %s\n",
9593 wine_dbgstr_rect( &rect_actual ), wine_dbgstr_rect( &rect_expect ) );
9594
9595 result = GetRgnBox( hrgn_actual_child, &rect_actual_child );
9596 ok( result == SIMPLEREGION, "GetRgnBox (on child) returned %d\n", result );
9597 if (result == COMPLEXREGION) dump_region( hrgn_actual_child );
9598
9599 ok( GetClientRect( hchild, &rect_expect_child ), "GetClientRect failed\n" );
9600 ok( EqualRect( &rect_actual_child, &rect_expect_child ), "child update region: got %s, expected %s\n",
9601 wine_dbgstr_rect( &rect_actual_child ), wine_dbgstr_rect( &rect_expect_child ) );
9602
9603 if (winetest_debug > 1) trace("testing show window (with move / resize)\n");
9604
9605 SetWindowPos( hchild, HWND_TOP,
9606 rect_1.left, rect_1.top, rect_1.right - rect_1.left, rect_1.bottom - rect_1.top,
9608
9609 UpdateWindow( hparent );
9610 flush_events();
9611
9612 SetWindowPos( hchild, HWND_TOP,
9613 rect_2.left,
9614 rect_2.top,
9615 rect_2.right - rect_2.left,
9616 rect_2.bottom - rect_2.top,
9618
9619 ok( GetUpdateRgn( hparent, hrgn_actual, FALSE ) != ERROR,
9620 "GetUpdateRgn on parent shall succeed\n" );
9621 ok( GetUpdateRgn( hchild, hrgn_actual_child, FALSE ) != ERROR,
9622 "GetUpdateRgn on child shall succeed\n" );
9623
9624 result = GetRgnBox( hrgn_actual, &rect_actual );
9625 ok( result == SIMPLEREGION, "GetRgnBox (on parent) returned %d\n", result );
9626 if (result == COMPLEXREGION) dump_region( hrgn_actual );
9627
9628 rect_expect = rect_2;
9629 ok( EqualRect( &rect_actual, &rect_expect ), "parent update region: got %s, expected %s\n",
9630 wine_dbgstr_rect( &rect_actual ), wine_dbgstr_rect( &rect_expect ) );
9631
9632 result = GetRgnBox( hrgn_actual_child, &rect_actual_child );
9633 ok( result == SIMPLEREGION, "GetRgnBox (on child) returned %d\n", result );
9634 if (result == COMPLEXREGION) dump_region( hrgn_actual_child );
9635
9636 ok( GetClientRect( hchild, &rect_expect_child ), "GetClientRect failed\n" );
9637 ok( EqualRect( &rect_actual_child, &rect_expect_child ), "child update region: got %s, expected %s\n",
9638 wine_dbgstr_rect( &rect_actual_child ), wine_dbgstr_rect( &rect_expect_child ) );
9639
9640 DestroyWindow( hchild );
9641 DestroyWindow( hparent );
9642 DeleteObject( hrgn_actual_child );
9643 DeleteObject( hrgn_actual );
9644}
9645
9647{
9648 HRGN hrgn_actual_child = CreateRectRgn( 0, 0, 0, 0 );
9649 HRGN hrgn_actual = CreateRectRgn( 0, 0, 0, 0 );
9650 const RECT rect_1 = { 10, 10, 100, 100 };
9651 RECT rect_expect_child, rect_expect;
9652 RECT rect_actual_child, rect_actual;
9653 HWND hparent, hchild;
9654 int result;
9655
9656 hparent = CreateWindowExA( 0, "SimpleWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
9657 80, 80, 200, 200, NULL, 0, 0, NULL );
9658 ok( hparent != 0, "Creating parent window returned error %lu\n", GetLastError() );
9659
9660 hchild = CreateWindowExA( 0, "SimpleWindowClass", "Test child (no border)", WS_CHILD | WS_VISIBLE,
9661 10, 10, 0, 0, hparent, 0, 0, NULL );
9662 ok( hchild != 0, "Creating child window returned error %lu\n", GetLastError() );
9663
9664 if (winetest_debug > 1) trace("testing extending zero-size window\n");
9665
9666 UpdateWindow( hparent );
9667 flush_events();
9668
9669 SetWindowPos( hchild, HWND_TOP,
9670 rect_1.left,
9671 rect_1.top,
9672 rect_1.right - rect_1.left,
9673 rect_1.bottom - rect_1.top,
9675
9676 ok( GetUpdateRgn( hparent, hrgn_actual, FALSE ) != ERROR,
9677 "GetUpdateRgn on parent shall succeed\n" );
9678 ok( GetUpdateRgn( hchild, hrgn_actual_child, FALSE ) != ERROR,
9679 "GetUpdateRgn on child shall succeed\n" );
9680
9681 result = GetRgnBox( hrgn_actual, &rect_actual );
9682 ok( result == SIMPLEREGION, "GetRgnBox (on parent) returned %d\n", result );
9683 if (result == COMPLEXREGION) dump_region( hrgn_actual );
9684
9685 rect_expect = rect_1;
9686 ok( EqualRect( &rect_actual, &rect_expect ), "parent update region: got %s, expected %s\n",
9687 wine_dbgstr_rect( &rect_actual ), wine_dbgstr_rect( &rect_expect ) );
9688
9689 result = GetRgnBox( hrgn_actual_child, &rect_actual_child );
9690 ok( result == SIMPLEREGION, "GetRgnBox (on child) returned %d\n", result );
9691 if (result == COMPLEXREGION) dump_region( hrgn_actual_child );
9692
9693 ok( GetClientRect( hchild, &rect_expect_child ), "GetClientRect failed\n" );
9694 ok( EqualRect( &rect_actual_child, &rect_expect_child ), "child update region: got %s, expected %s\n",
9695 wine_dbgstr_rect( &rect_actual_child ), wine_dbgstr_rect( &rect_expect_child ) );
9696
9697 DestroyWindow( hchild );
9698 DestroyWindow( hparent );
9699 DeleteObject( hrgn_actual_child );
9700 DeleteObject( hrgn_actual );
9701}
9702
9703static void subtest_hvredraw(HWND hparent, UINT class_style, DWORD style)
9704{
9705 static const struct movesize_test {
9706 int dx, dy, dw, dh;
9707 } movesize_tests[] = {
9708 { 0, 0, 0, 5 },
9709 { 0, 0, 5, 0 },
9710 { 0, 0, 5, 5 },
9711 { 0, 0, -5, -5 },
9712 { -5, -5, 0, 5 },
9713 { -5, -5, 5, 0 },
9714 { -5, -5, 5, 5 },
9715 };
9716 HRGN hrgn_old_vis = CreateRectRgn( 0, 0, 0, 0 );
9717 HRGN hrgn_new_vis = CreateRectRgn( 0, 0, 0, 0 );
9718 HRGN hrgn_expect = CreateRectRgn( 0, 0, 0, 0 );
9719 HRGN hrgn_actual = CreateRectRgn( 0, 0, 0, 0 );
9720 const int x0 = 100, y0 = 100, w0 = 150, h0 = 150;
9721 size_t i;
9722 HWND hwnd;
9723 WNDCLASSA cls = {
9724 .style = class_style,
9725 .lpfnWndProc = DefWindowProcA,
9726 .hInstance = GetModuleHandleA(0),
9727 .hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW),
9728 .hbrBackground = GetStockObject(WHITE_BRUSH),
9729 .lpszClassName = "TestHVRedrawClass"
9730 };
9731
9732 register_class(&cls);
9733
9734 hwnd = CreateWindowExA( 0, cls.lpszClassName, "Test window", style, x0, y0, w0, h0, hparent, 0, 0, NULL );
9735 ok(hwnd != NULL, "Failed to create the window\n");
9736
9738 UpdateWindow( hwnd );
9739
9740 for (i = 0; i < ARRAY_SIZE(movesize_tests); i++)
9741 {
9742 const struct movesize_test *test = &movesize_tests[i];
9743 int is_redraw = (test->dw != 0 && (class_style & CS_HREDRAW)) ||
9744 (test->dh != 0 && (class_style & CS_VREDRAW));
9745 RECT rect_old_vis, rect_new_vis;
9746 BOOL rgn_ok;
9747
9748 winetest_push_context( "%x %08lx SetWindowPos redraw #%Id (%d, %d, %d, %d)",
9749 class_style, style, i, test->dx, test->dy, test->dw, test->dh );
9750
9752
9753 GetClientRect( hwnd, &rect_old_vis );
9754 SetRectRgn( hrgn_old_vis, rect_old_vis.left, rect_old_vis.top, rect_old_vis.right, rect_old_vis.bottom );
9755
9756 UpdateWindow( hparent );
9757 flush_events();
9758
9760 x0 + test->dx, y0 + test->dy,
9761 w0 + test->dw, h0 + test->dh, SWP_NOACTIVATE );
9762 ok( GetUpdateRgn( hwnd, hrgn_actual, FALSE ) != ERROR, "GetUpdateRgn shall succeed\n" );
9763
9764 GetClientRect( hwnd, &rect_new_vis );
9765 SetRectRgn( hrgn_new_vis, rect_new_vis.left, rect_new_vis.top, rect_new_vis.right, rect_new_vis.bottom );
9766 CombineRgn( hrgn_expect, hrgn_new_vis, hrgn_old_vis, is_redraw ? RGN_COPY : RGN_DIFF );
9767
9768 rgn_ok = EqualRgn( hrgn_expect, hrgn_actual );
9769#ifdef __REACTOS__
9770 ok( !!rgn_ok || broken(GetNTVersion() == _WIN32_WINNT_WINBLUE), "Update region shall match expected region\n" );
9771#else
9772 ok( !!rgn_ok, "Update region shall match expected region\n" );
9773#endif
9774
9775 if (!rgn_ok)
9776 {
9777 trace( "Expected update region: " );
9778 dump_region( hrgn_expect );
9779 trace( "Actual update region: " );
9780 dump_region( hrgn_actual );
9781 trace( "Old window visible area: %s\n", wine_dbgstr_rect( &rect_old_vis ) );
9782 trace( "New window visible area: %s\n", wine_dbgstr_rect( &rect_new_vis ) );
9783 }
9784
9786 {
9787 if (!rgn_ok)
9788 {
9789 visualize_region_differences( hwnd, NULL, hrgn_expect, hrgn_actual );
9790 }
9791
9792 /* Let the position change be visible to the user */
9793 flush_events();
9794 }
9795
9797 }
9798
9800 DeleteObject( hrgn_actual );
9801 DeleteObject( hrgn_expect );
9802 DeleteObject( hrgn_new_vis );
9803 DeleteObject( hrgn_old_vis );
9805}
9806
9807
9808static void test_hvredraw(void)
9809{
9810 HWND htoplevel;
9811
9815
9816 htoplevel = CreateWindowExA( 0, "SimpleWindowClass", "Test toplevel",
9818 100, 100, 400, 400, 0, 0, 0, NULL );
9819 ok( htoplevel != 0, "Failed to create top-level window: %lu\n", GetLastError() );
9820
9824
9825 DestroyWindow( htoplevel );
9826}
9827
9829{
9830 const char *file;
9831 int line;
9832 const char *name;
9834};
9835
9837{
9838 HDESK prev_thr_desktop, prev_inp_desktop, post_inp_desktop, temp_desktop;
9839 char temp_desktop_name[1024], curr_desktop_name[1024];
9841 const char *file = args->file;
9842 int line = args->line;
9843 LARGE_INTEGER qpc;
9844 DWORD length;
9845 int result;
9846
9848 ok_(file, line)( result, "QueryPerformanceCounter error %lu\n", GetLastError() );
9849
9850 /*
9851 * Temporary desktops from previous runs may leak due to a Windows bug.
9852 * Generate a unique name that is unlikely to collide with previous runs.
9853 */
9854 result = snprintf( temp_desktop_name, ARRAY_SIZE(temp_desktop_name),
9855 "WineTest-%08lX-%08lX-%08lX%08lX-%s",
9857 qpc.HighPart, qpc.LowPart, args->name );
9858 ok_(file, line)( result > 0 && result < ARRAY_SIZE(temp_desktop_name),
9859 "sprintf returned %d (out of memory, or name too long?)\n", result );
9860
9861 if (winetest_debug > 1)
9862 trace_(file, line)( "creating desktop: %s\n", debugstr_a( temp_desktop_name ) );
9863
9864 temp_desktop = CreateDesktopA( temp_desktop_name, NULL, NULL, 0, GENERIC_ALL, NULL );
9865 ok_(file, line)( temp_desktop != NULL, "CreateDesktopA(%s, ..) error %lu\n",
9866 debugstr_a( temp_desktop_name ), GetLastError() );
9867
9868 prev_inp_desktop = OpenInputDesktop( 0, FALSE, DESKTOP_SWITCHDESKTOP );
9869 ok_(file, line)( prev_inp_desktop != NULL, "OpenInputDesktop [prev] error %lu\n", GetLastError() );
9870
9871 if (winetest_debug > 1)
9872 trace_(file, line)( "sanity check: no concurrent WineTest desktop\n" );
9873
9874 /*
9875 * Check if the desktop has not been properly restored. This is done to
9876 * avoid any possible hard-to-debug failures due to unexpected desktop.
9877 */
9878 result = GetUserObjectInformationA( prev_inp_desktop, UOI_NAME,
9879 curr_desktop_name, sizeof(curr_desktop_name), &length );
9880 ok_(file, line)( result, "GetUserObjectInformationA error %lu [rl = %lu]\n",
9881 GetLastError(), length );
9882 ok_(file, line)( _strnicmp( curr_desktop_name, temp_desktop_name, 8 ) != 0,
9883 "unexpected input desktop name %s (concurrent WineTest run?)\n",
9884 debugstr_a( curr_desktop_name ) );
9885
9886 if (winetest_debug > 1)
9887 trace_(file, line)( "switching desktop to: %s (%p)\n", debugstr_a( temp_desktop_name ), temp_desktop );
9888
9889 result = SwitchDesktop( temp_desktop );
9890 ok_(file, line)( result, "SwitchDesktop(temp_desktop=%p) error %lu\n",
9891 temp_desktop, GetLastError() );
9892
9893 prev_thr_desktop = GetThreadDesktop( GetCurrentThreadId() );
9894 ok_(file, line)( prev_thr_desktop != NULL, "GetThreadDesktop error %lu\n", GetLastError() );
9895
9896 result = SetThreadDesktop( temp_desktop );
9897 ok_(file, line)( result, "SetThreadDesktop(temp_desktop=%p) error %lu\n",
9898 temp_desktop, GetLastError() );
9899
9900 if (winetest_debug > 1)
9901 trace_(file, line)( "running test function %s()\n", args->name );
9902
9903 args->test_func();
9904
9905 if (winetest_debug > 1)
9906 trace_(file, line)( "sanity check: input desktop has not been changed\n" );
9907
9908 /*
9909 * Check if the input desktop has been tampered with. This is done to
9910 * avoid any possible hard-to-debug failures due to unexpected desktop.
9911 */
9912 post_inp_desktop = OpenInputDesktop( 0, FALSE, DESKTOP_ENUMERATE );
9913 ok_(file, line)( post_inp_desktop != NULL, "OpenInputDesktop [post] error %lu\n", GetLastError() );
9914
9915 result = GetUserObjectInformationA( post_inp_desktop, UOI_NAME,
9916 curr_desktop_name, sizeof(curr_desktop_name), &length );
9917 ok_(file, line)( result, "GetUserObjectInformationA(post_inp_desktop=%p) error %lu [rl = %lu]\n",
9918 post_inp_desktop, GetLastError(), length );
9919 ok_(file, line)( strcmp( curr_desktop_name, temp_desktop_name ) == 0,
9920 "different desktop name: %s != %s (no switch or concurrent WineTest run?)\n",
9921 debugstr_a( curr_desktop_name ), debugstr_a( temp_desktop_name ) );
9922
9923 result = CloseDesktop( post_inp_desktop );
9924 ok_(file, line)( result, "CloseDesktop(post_inp_desktop=%p) error %lu\n",
9925 post_inp_desktop, GetLastError() );
9926
9927 if (winetest_debug > 1)
9928 trace_(file, line)( "restoring previous desktop\n" );
9929
9930 result = SetThreadDesktop( prev_thr_desktop );
9931 ok_(file, line)( result || broken( GetLastError() == ERROR_BUSY ) /* == W10 */,
9932 "SetThreadDesktop(prev_thr_desktop=%p) error %lu\n",
9933 prev_thr_desktop, GetLastError() );
9934
9935 result = SwitchDesktop( prev_inp_desktop );
9936 ok_(file, line)( result, "SwitchDesktop(prev_inp_desktop=%p) error %lu\n",
9937 prev_inp_desktop, GetLastError() );
9938
9939 result = CloseDesktop( prev_inp_desktop );
9940 ok_(file, line)( result, "CloseDesktop(prev_inp_desktop=%p) error %lu\n",
9941 prev_inp_desktop, GetLastError() );
9942
9943 if (winetest_debug > 1)
9944 trace_(file, line)( "closing desktop: %s (%p)\n", debugstr_a( temp_desktop_name ), temp_desktop );
9945
9946 result = CloseDesktop( temp_desktop );
9947 ok_(file, line)( result || broken( GetLastError() == ERROR_BUSY ) /* == W10 */,
9948 "CloseDesktop(temp_desktop=%p) error %lu\n",
9949 temp_desktop, GetLastError() );
9950
9951 return 0;
9952}
9953
9954#define run_in_temp_desktop(f) run_in_temp_desktop_(__FILE__, __LINE__, #f, f)
9955static void run_in_temp_desktop_(const char *file, int line, const char *name, void (*test_func)(void))
9956{
9958 HANDLE thread;
9959 DWORD result;
9960
9961 args.file = file;
9962 args.line = line;
9963 args.name = name;
9964 args.test_func = test_func;
9965
9967 ok_(file, line)( thread != NULL, "CreateThread error %lu\n", GetLastError() );
9968
9970 ok_(file, line)( result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu, error %lu\n",
9971 result, GetLastError() );
9972
9974}
9975
9976struct wnd_event
9977{
9978 HWND hwnd;
9983};
9984
9986{
9987 MSG msg;
9988 struct wnd_event *wnd_event = param;
9989
9990 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
9991 100, 100, 200, 200, 0, 0, 0, NULL);
9992 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
9993
9995
9996 while (GetMessageA(&msg, 0, 0, 0))
9997 {
10000 }
10001
10002 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
10003
10004 return 0;
10005}
10006
10008{
10009 struct wnd_event *wnd_event = param;
10010 HWND hchild;
10011 MSG msg;
10012
10013 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
10014 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL);
10015 ok (hchild != 0, "Failed to create child window\n");
10016 flush_events();
10019
10020 for (;;)
10021 {
10023 if (!IsWindow( hchild )) break; /* will be destroyed when parent thread exits */
10024 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
10025 }
10026 return 0;
10027}
10028
10030{
10031 struct wnd_event *wnd_event = param;
10032 struct wnd_event child_event;
10033 DWORD ret, tid;
10034 MSG msg;
10035
10036 child_event.hwnd = CreateWindowExA(0, "TestWindowClass", "Test child",
10037 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL);
10038 ok (child_event.hwnd != 0, "Failed to create child window\n");
10039 SetFocus( child_event.hwnd );
10040 flush_events();
10042 child_event.start_event = wnd_event->start_event;
10044 for (;;)
10045 {
10047 if (ret != 1) break;
10048 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
10049 }
10051 ok( !ret, "WaitForSingleObject failed %lx\n", ret );
10052 return 0;
10053}
10054
10055static const char manifest_dep[] =
10056"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
10057"<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
10058" <file name=\"testdep.dll\" />"
10059"</assembly>";
10060
10061static const char manifest_main[] =
10062"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
10063"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
10064"<dependency>"
10065" <dependentAssembly>"
10066" <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
10067" </dependentAssembly>"
10068"</dependency>"
10069"</assembly>";
10070
10071static void create_manifest_file(const char *filename, const char *manifest)
10072{
10074 HANDLE file;
10075 DWORD size;
10076
10079 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
10082}
10083
10084static HANDLE test_create(const char *file)
10085{
10087 ACTCTXW actctx;
10088 HANDLE handle;
10089
10091 memset(&actctx, 0, sizeof(ACTCTXW));
10092 actctx.cbSize = sizeof(ACTCTXW);
10093 actctx.lpSource = path;
10094
10096 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %lu\n", GetLastError());
10097
10098 ok(actctx.cbSize == sizeof(actctx), "cbSize=%ld\n", actctx.cbSize);
10099 ok(actctx.dwFlags == 0, "dwFlags=%ld\n", actctx.dwFlags);
10100 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
10101 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
10102 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
10103 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
10104 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
10105 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
10106 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
10107
10108 return handle;
10109}
10110
10112{
10115 DWORD tid;
10116 WNDPROC proc;
10117 MSG msg;
10118 char buf[256];
10119 int len, expected_len;
10120 struct wnd_event wnd_event;
10121 BOOL ret;
10122
10125 {
10126 win_skip("skipping interthread message test under win9x\n");
10127 return;
10128 }
10129
10131 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
10132
10133 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10134
10136
10137 SetLastError(0xdeadbeef);
10138 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n");
10139 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef,
10140 "wrong error code %ld\n", GetLastError());
10141
10143 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
10144
10145 expected_len = lstrlenA("window caption text");
10146 memset(buf, 0, sizeof(buf));
10147 SetLastError(0xdeadbeef);
10149 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len, expected_len);
10150 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
10151
10152 msg.hwnd = wnd_event.hwnd;
10153 msg.message = WM_GETTEXT;
10154 msg.wParam = sizeof(buf);
10155 msg.lParam = (LPARAM)buf;
10156 memset(buf, 0, sizeof(buf));
10157 SetLastError(0xdeadbeef);
10159 ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */
10160 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %ld\n", len, GetLastError());
10161
10162 /* the following test causes an exception in user.exe under win9x */
10163 msg.hwnd = wnd_event.hwnd;
10164 msg.message = WM_TIMER;
10165 msg.wParam = 0;
10167 SetLastError(0xdeadbeef);
10169 ok(!len && GetLastError() == 0xdeadbeef,
10170 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len, GetLastError());
10171
10173 ok( ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
10174
10175 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10177
10178 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
10179
10180 wnd_event.hwnd = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
10181 100, 100, 200, 200, 0, 0, 0, NULL);
10182 ok (wnd_event.hwnd != 0, "Failed to create parent window\n");
10183 flush_events();
10189 for (;;)
10190 {
10192 if (ret != 1) break;
10193 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
10194 }
10195 ok( !ret, "MsgWaitForMultipleObjects failed %x\n", ret );
10196 /* now wait for the thread without processing messages; this shouldn't deadlock */
10198 ret = WaitForSingleObject( hThread, 5000 );
10199 ok( !ret, "WaitForSingleObject failed %x\n", ret );
10201
10203 ok( !ret, "WaitForSingleObject failed %x\n", ret );
10205
10208 flush_events();
10209 ok_sequence(WmExitThreadSeq, "destroy child on thread exit", FALSE);
10212
10213 /* Activation context tests */
10214 create_manifest_file("testdep1.manifest", manifest_dep);
10215 create_manifest_file("main.manifest", manifest_main);
10216
10217 context = test_create("main.manifest");
10218 DeleteFileA("testdep1.manifest");
10219 DeleteFileA("main.manifest");
10220
10221 handle = (void*)0xdeadbeef;
10223 ok(ret, "GetCurrentActCtx failed: %lu\n", GetLastError());
10224 ok(handle == 0, "active context %p\n", handle);
10225
10228 ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
10229 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10231
10232 /* context is activated after thread creation, so it doesn't inherit it by default */
10234 ok(ret, "activation failed: %lu\n", GetLastError());
10235
10236 handle = 0;
10238 ok(ret, "GetCurrentActCtx failed: %lu\n", GetLastError());
10239 ok(handle != 0, "active context %p\n", handle);
10241
10242 /* destination window will test for active context */
10243 ret = SendMessageA(wnd_event.hwnd, WM_USER+10, 0, 0);
10244 ok(ret, "thread window returned %d\n", ret);
10245
10246 event = CreateEventW(NULL, 0, 0, NULL);
10248 ok(ret, "thread window returned %d\n", ret);
10249 ok(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10251
10253 ok(ret, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
10254
10255 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10257
10259 ok(ret, "DeactivateActCtx failed: %lu\n", GetLastError());
10261}
10262
10263
10264static const struct message WmVkN[] = {
10265 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
10266 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
10267 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
10268 { WM_CHAR, wparam|lparam, 'n', 1 },
10269 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
10270 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
10271 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
10272 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
10273 { 0 }
10274};
10275static const struct message WmShiftVkN[] = {
10279 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
10280 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
10281 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
10282 { WM_CHAR, wparam|lparam, 'N', 1 },
10283 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
10284 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
10285 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
10286 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
10287 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
10288 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
10289 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
10290 { 0 }
10291};
10292static const struct message WmCtrlVkN[] = {
10296 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
10297 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
10298 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
10299 { WM_CHAR, wparam|lparam, 0x000e, 1 },
10300 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
10301 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
10302 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
10303 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
10304 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
10305 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
10306 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
10307 { 0 }
10308};
10309static const struct message WmCtrlVkN_2[] = {
10313 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
10314 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
10315 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
10316 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
10317 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
10318 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
10319 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
10320 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
10321 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
10322 { 0 }
10323};
10324static const struct message WmAltVkN[] = {
10325 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
10326 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
10327 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
10328 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
10329 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
10330 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
10331 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
10332 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
10334 { HCBT_SYSCOMMAND, hook },
10336 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
10337 { 0x00AE, sent|defwinproc|optional }, /* XP */
10338 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */
10340 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10342 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|wine_only, 0, 0 },
10343 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
10346 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10348 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
10349 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
10350 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
10351 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
10352 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
10353 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
10354 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
10355 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
10356 { 0 }
10357};
10358static const struct message WmAltVkN_2[] = {
10359 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
10360 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
10361 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
10362 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
10363 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
10364 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
10365 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
10366 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
10367 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
10368 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
10369 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
10370 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
10371 { 0 }
10372};
10373static const struct message WmCtrlAltVkN[] = {
10377 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
10378 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
10379 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
10380 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
10381 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
10382 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
10383 { WM_CHAR, optional },
10384 { WM_CHAR, sent|optional },
10385 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
10386 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
10387 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
10388 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
10389 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
10390 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
10391 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
10392 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
10393 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
10394 { 0 }
10395};
10396static const struct message WmCtrlShiftVkN[] = {
10403 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
10404 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
10405 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 },
10406 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
10407 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
10408 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
10409 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
10410 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
10411 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
10412 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
10413 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
10414 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
10415 { 0 }
10416};
10417static const struct message WmCtrlAltShiftVkN[] = {
10421 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
10422 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
10423 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
10424 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0x20000001 }, /* XP */
10425 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 },
10426 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 },
10427 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
10428 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
10429 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 },
10430 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
10431 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
10432 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
10433 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xe0000001 }, /* XP */
10434 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 },
10435 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 },
10436 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
10437 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
10438 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
10439 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
10440 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
10441 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
10442 { 0 }
10443};
10444static const struct message WmAltPressRelease[] = {
10445 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
10446 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
10447 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
10448 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
10449 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
10450 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
10452 { HCBT_SYSCOMMAND, hook },
10454 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
10456 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10458 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 1 },
10459
10460 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x30000001 }, /* XP */
10461
10462 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10463 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0, },
10466 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10468 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
10469 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
10470 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
10471 { 0 }
10472};
10473static const struct message WmShiftMouseButton[] = {
10477 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
10478 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
10481 { WM_LBUTTONUP, wparam|optional, MK_SHIFT, 0 }, /* < w1064v1809 */
10482 { WM_LBUTTONUP, sent|wparam|optional, MK_SHIFT, 0 }, /* < w1064v1809 */
10483 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
10484 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
10485 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
10486 { WM_LBUTTONUP, optional, 0, 0 }, /* >= w1064v1809 */
10487 { WM_LBUTTONUP, sent|optional, 0, 0 }, /* >= w1064v1809 */
10488 { 0 }
10489};
10490static const struct message WmF1Seq[] = {
10491 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 1 }, /* XP */
10492 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 },
10493 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 },
10494 { WM_KEYF1, wparam|lparam, 0, 0 },
10495 { WM_KEYF1, sent|wparam|lparam, 0, 0 },
10496 { WM_HELP, sent|defwinproc },
10497 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 0xc0000001 }, /* XP */
10498 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 },
10499 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 },
10500 { 0 }
10501};
10502static const struct message WmVkAppsSeq[] = {
10505 { WM_KEYDOWN, sent|wparam|lparam, VK_APPS, 0x00000001 },
10506 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 0xc0000001 }, /* XP */
10507 { WM_KEYUP, wparam|lparam, VK_APPS, 0xc0000001 },
10508 { WM_KEYUP, sent|wparam|lparam, VK_APPS, 0xc0000001 },
10509 { WM_CONTEXTMENU, lparam, /*hwnd*/0, -1 },
10510 { WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, -1 },
10511 { 0 }
10512};
10513static const struct message WmVkF10Seq[] = {
10514 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
10516 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 },
10517 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
10518 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
10519 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
10521 { HCBT_SYSCOMMAND, hook },
10523 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
10525 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10527 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 1 },
10528
10529 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0x10000001 }, /* XP */
10530
10531 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
10532 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10533 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0, },
10536 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10538 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
10539 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
10540 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
10541 { 0 }
10542};
10543static const struct message WmShiftF10Seq[] = {
10546 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x00000001 },
10547 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
10549 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 },
10550 { WM_CONTEXTMENU, sent|defwinproc|lparam, /*hwnd*/0, -1 },
10551 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
10552 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
10553 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
10555 { HCBT_SYSCOMMAND, hook },
10557 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
10559 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10561 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 1 },
10562 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xd0000001 }, /* XP */
10563 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0x10000001 }, /* XP */
10564 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10565 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam|msg_todo, 0, 0 },
10567 { WM_MENUSELECT, sent|defwinproc|wparam|lparam, 0xffff0000, 0 },
10568 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam|msg_todo, OBJID_SYSMENU, 0 },
10570 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, /* XP */
10571 { WM_KEYUP, wparam|lparam, VK_ESCAPE, 0xc0000001 },
10572 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 },
10573 { 0 }
10574};
10575
10576static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
10577{
10578 MSG msg;
10579
10580 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
10581 {
10582 struct recvd_message log_msg;
10583
10584 /* ignore some unwanted messages */
10585 if (msg.message == WM_MOUSEMOVE ||
10586 msg.message == WM_TIMER ||
10587 ignore_message( msg.message ))
10588 continue;
10589
10590 log_msg.hwnd = msg.hwnd;
10591 log_msg.message = msg.message;
10592 log_msg.flags = wparam|lparam;
10593 log_msg.wParam = msg.wParam;
10594 log_msg.lParam = msg.lParam;
10595 log_msg.descr = "accel";
10596 add_message(&log_msg);
10597
10599 {
10602 }
10603 }
10604}
10605
10606static void test_accelerators(void)
10607{
10608 RECT rc;
10609 POINT pt;
10610 SHORT state;
10611 HACCEL hAccel;
10612 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
10613 100, 100, 200, 200, 0, 0, 0, NULL);
10614 BOOL us_kbd = (GetKeyboardLayout(0) == (HKL)(ULONG_PTR)0x04090409);
10615 BOOL ret;
10616
10617 ok(!!hwnd, "Failed to create window, error %lu.\n", GetLastError());
10619 flush_events();
10621
10622 SetFocus(hwnd);
10623 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
10624
10626 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
10628 ok(state == 0, "wrong CapsLock state %04x\n", state);
10629
10631 ok(!!hAccel, "Failed to load accelerators, error %lu.\n", GetLastError());
10632
10633 flush_events();
10634 pump_msg_loop(hwnd, 0);
10636
10637 if (!us_kbd)
10638 {
10639 skip("skipping ascii VK events on non-us keyboard\n");
10640 goto done;
10641 }
10642
10643 if (winetest_debug > 1) trace("testing VK_N press/release\n");
10645 keybd_event('N', 0, 0, 0);
10646 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10648 if (!sequence_cnt) /* we didn't get any message */
10649 {
10650 skip( "queuing key events not supported\n" );
10651 goto done;
10652 }
10653 ok_sequence(WmVkN, "VK_N press/release", FALSE);
10654
10655 if (winetest_debug > 1) trace("testing Shift+VK_N press/release\n");
10657 keybd_event(VK_SHIFT, 0, 0, 0);
10658 keybd_event('N', 0, 0, 0);
10659 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10662 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
10663
10664 if (winetest_debug > 1) trace("testing Ctrl+VK_N press/release\n");
10666 keybd_event(VK_CONTROL, 0, 0, 0);
10667 keybd_event('N', 0, 0, 0);
10668 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10671#ifdef __REACTOS__
10672 if (0) // Test failures on WS03-Win10 1607
10673#endif
10674 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
10675
10676 if (winetest_debug > 1) trace("testing Alt+VK_N press/release\n");
10678 keybd_event(VK_MENU, 0, 0, 0);
10679 keybd_event('N', 0, 0, 0);
10680 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10683 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
10684
10685 if (winetest_debug > 1) trace("testing Ctrl+Alt+VK_N press/release 1\n");
10687 keybd_event(VK_CONTROL, 0, 0, 0);
10688 keybd_event(VK_MENU, 0, 0, 0);
10689 keybd_event('N', 0, 0, 0);
10690 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10694 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
10695
10697 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
10698
10700 ok(!!hAccel, "Failed to load accelerators, error %lu.\n", GetLastError());
10701
10702 if (winetest_debug > 1) trace("testing VK_N press/release\n");
10704 keybd_event('N', 0, 0, 0);
10705 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10707 ok_sequence(WmVkN, "VK_N press/release", FALSE);
10708
10709 if (winetest_debug > 1) trace("testing Shift+VK_N press/release\n");
10711 keybd_event(VK_SHIFT, 0, 0, 0);
10712 keybd_event('N', 0, 0, 0);
10713 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10716 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
10717
10718 if (winetest_debug > 1) trace("testing Ctrl+VK_N press/release 2\n");
10720 keybd_event(VK_CONTROL, 0, 0, 0);
10721 keybd_event('N', 0, 0, 0);
10722 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10725 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
10726
10727 if (winetest_debug > 1) trace("testing Alt+VK_N press/release 2\n");
10729 keybd_event(VK_MENU, 0, 0, 0);
10730 keybd_event('N', 0, 0, 0);
10731 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10734 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
10735
10736 if (winetest_debug > 1) trace("testing Ctrl+Alt+VK_N press/release 2\n");
10738 keybd_event(VK_CONTROL, 0, 0, 0);
10739 keybd_event(VK_MENU, 0, 0, 0);
10740 keybd_event('N', 0, 0, 0);
10741 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10745 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
10746
10747 if (winetest_debug > 1) trace("testing Ctrl+Shift+VK_N press/release\n");
10749 keybd_event(VK_CONTROL, 0, 0, 0);
10750 keybd_event(VK_SHIFT, 0, 0, 0);
10751 keybd_event('N', 0, 0, 0);
10752 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10756 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE);
10757
10758 if (winetest_debug > 1) trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
10760 keybd_event(VK_CONTROL, 0, 0, 0);
10761 keybd_event(VK_MENU, 0, 0, 0);
10762 keybd_event(VK_SHIFT, 0, 0, 0);
10763 keybd_event('N', 0, 0, 0);
10764 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
10769 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE);
10770
10772 ok( ret, "DestroyAcceleratorTable error %ld\n", GetLastError());
10773 hAccel = 0;
10774
10775 if (winetest_debug > 1) trace("testing Alt press/release\n");
10777 keybd_event(VK_MENU, 0, 0, 0);
10779 keybd_event(VK_MENU, 0, 0, 0);
10781 pump_msg_loop(hwnd, 0);
10782 /* this test doesn't pass in Wine for managed windows */
10783 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
10784
10785 if (winetest_debug > 1) trace("testing VK_F1 press/release\n");
10786 keybd_event(VK_F1, 0, 0, 0);
10788 pump_msg_loop(hwnd, 0);
10789 ok_sequence(WmF1Seq, "F1 press/release", FALSE);
10790
10791 if (winetest_debug > 1) trace("testing VK_APPS press/release\n");
10792 keybd_event(VK_APPS, 0, 0, 0);
10794 pump_msg_loop(hwnd, 0);
10795 ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE);
10796
10797 if (winetest_debug > 1) trace("testing VK_F10 press/release\n");
10798 keybd_event(VK_F10, 0, 0, 0);
10800 keybd_event(VK_F10, 0, 0, 0);
10802 pump_msg_loop(hwnd, 0);
10803 ok_sequence(WmVkF10Seq, "VK_F10 press/release", TRUE);
10804
10805 if (winetest_debug > 1) trace("testing SHIFT+F10 press/release\n");
10806 keybd_event(VK_SHIFT, 0, 0, 0);
10807 keybd_event(VK_F10, 0, 0, 0);
10810 keybd_event(VK_ESCAPE, 0, 0, 0);
10812 pump_msg_loop(hwnd, 0);
10813 ok_sequence(WmShiftF10Seq, "SHIFT+F10 press/release", TRUE);
10814
10815 if (winetest_debug > 1) trace("testing Shift+MouseButton press/release\n");
10816 /* first, move mouse pointer inside of the window client area */
10817 GetClientRect(hwnd, &rc);
10818 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
10819 rc.left += (rc.right - rc.left)/2;
10820 rc.top += (rc.bottom - rc.top)/2;
10821 SetCursorPos(rc.left, rc.top);
10823
10824 flush_events();
10826 GetCursorPos(&pt);
10827 if (pt.x == rc.left && pt.y == rc.top)
10828 {
10829 int i;
10830 keybd_event(VK_SHIFT, 0, 0, 0);
10831 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
10832 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
10834 pump_msg_loop(hwnd, 0);
10835 for (i = 0; i < sequence_cnt; i++) if (sequence[i].message == WM_LBUTTONDOWN) break;
10836 if (i < sequence_cnt)
10837 ok_sequence(WmShiftMouseButton, "Shift+MouseButton press/release", FALSE);
10838 else
10839 skip( "Shift+MouseButton event didn't get to the window\n" );
10840 }
10841
10842done:
10845}
10846
10847/************* window procedures ********************/
10848
10851{
10852 static LONG defwndproc_counter = 0;
10853 static LONG beginpaint_counter = 0;
10854 LRESULT ret;
10855 struct recvd_message msg;
10856
10857 if (ignore_message( message )) return 0;
10858
10859 switch (message)
10860 {
10861 case WM_ENABLE:
10862 {
10864 ok((BOOL)wParam == !(style & WS_DISABLED),
10865 "wrong WS_DISABLED state: %Id != %d\n", wParam, !(style & WS_DISABLED));
10866 break;
10867 }
10868
10869 case WM_CAPTURECHANGED:
10871 {
10873 if (style & WS_CHILD)
10875 else if (style & WS_POPUP)
10877 else
10879 }
10880 break;
10881
10882 case WM_NCDESTROY:
10883 {
10884 HWND capture;
10885
10886 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
10887 capture = GetCapture();
10888 if (capture)
10889 {
10890 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture);
10891 if (winetest_debug > 1) trace("current capture %p, releasing...\n", capture);
10893 }
10894 }
10895 /* fall through */
10896 case WM_DESTROY:
10897 ok(GetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n");
10899 {
10901 if (style & WS_CHILD)
10903 else if (style & WS_POPUP)
10905 else
10907 }
10908 break;
10909
10910 /* test_accelerators() depends on this */
10911 case WM_NCHITTEST:
10912 return HTCLIENT;
10913
10914 case WM_USER+10:
10915 {
10916 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo;
10917 HANDLE handle, event = (HANDLE)lParam;
10918 BOOL ret;
10919
10920 handle = (void*)0xdeadbeef;
10922 ok(ret, "failed to get current context, %lu\n", GetLastError());
10923 ok(handle == 0, "got active context %p\n", handle);
10924
10925 memset(&basicinfo, 0xff, sizeof(basicinfo));
10926 ret = QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, 0, ActivationContextBasicInformation,
10927 &basicinfo, sizeof(basicinfo), NULL);
10928 ok(ret, "got %d, error %ld\n", ret, GetLastError());
10929 ok(basicinfo.hActCtx == NULL, "got %p\n", basicinfo.hActCtx);
10930 ok(basicinfo.dwFlags == 0, "got %lx\n", basicinfo.dwFlags);
10931
10932 if (event) SetEvent(event);
10933 return 1;
10934 }
10935
10936 /* ignore */
10937 case WM_MOUSEMOVE:
10938 case WM_MOUSEACTIVATE:
10939 case WM_NCMOUSEMOVE:
10940 case WM_SETCURSOR:
10941 case WM_IME_SELECT:
10942 if (ignore_mouse_messages) return 0;
10943 break;
10944 }
10945
10946 msg.hwnd = hwnd;
10947 msg.message = message;
10948 msg.flags = sent|wparam|lparam;
10949 if (defwndproc_counter) msg.flags |= defwinproc;
10950 if (beginpaint_counter) msg.flags |= beginpaint;
10951 msg.wParam = wParam;
10952 msg.lParam = lParam;
10953 msg.descr = "MsgCheckProc";
10954 add_message(&msg);
10955
10957 {
10959 RECT rc;
10960 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
10961
10962 GetClientRect(parent, &rc);
10963 if (winetest_debug > 1)
10964 {
10965 trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
10966 trace("Reserved=%ld,%ld MaxSize=%ld,%ld MaxPos=%ld,%ld MinTrack=%ld,%ld MaxTrack=%ld,%ld\n",
10967 minmax->ptReserved.x, minmax->ptReserved.y,
10968 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
10969 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
10970 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
10971 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
10972 }
10973 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
10974 minmax->ptMaxSize.x, rc.right);
10975 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
10976 minmax->ptMaxSize.y, rc.bottom);
10977 }
10978
10979 if (message == WM_PAINT)
10980 {
10981 PAINTSTRUCT ps;
10982 beginpaint_counter++;
10983 BeginPaint( hwnd, &ps );
10984 beginpaint_counter--;
10985 EndPaint( hwnd, &ps );
10986 return 0;
10987 }
10988
10990 {
10991 /* don't create context menu */
10992 return 0;
10993 }
10994
10995 defwndproc_counter++;
10996 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam)
10998 defwndproc_counter--;
10999
11000 return ret;
11001}
11002
11004{
11006}
11007
11009{
11011}
11012
11014{
11015 static LONG defwndproc_counter = 0;
11016 LRESULT ret;
11017 struct recvd_message msg;
11018
11019 if (ignore_message( message )) return 0;
11020
11021 switch (message)
11022 {
11023 case WM_QUERYENDSESSION:
11024 case WM_ENDSESSION:
11025 lParam &= ~0x01; /* Vista adds a 0x01 flag */
11026 break;
11027 }
11028
11029 msg.hwnd = hwnd;
11030 msg.message = message;
11031 msg.flags = sent|wparam|lparam;
11032 if (defwndproc_counter) msg.flags |= defwinproc;
11033 msg.wParam = wParam;
11034 msg.lParam = lParam;
11035 msg.descr = "popup";
11036 add_message(&msg);
11037
11038 if (message == WM_CREATE)
11039 {
11042 }
11043
11044 defwndproc_counter++;
11046 defwndproc_counter--;
11047
11048 return ret;
11049}
11050
11052{
11053 static LONG defwndproc_counter = 0;
11054 static LONG beginpaint_counter = 0;
11055 LRESULT ret;
11056 struct recvd_message msg;
11057
11058 if (ignore_message( message )) return 0;
11059
11066 {
11067 switch (message)
11068 {
11069 /* ignore */
11070 case WM_NCHITTEST:
11071 return HTCLIENT;
11072 case WM_SETCURSOR:
11073 case WM_MOUSEMOVE:
11074 case WM_NCMOUSEMOVE:
11075 return 0;
11076 }
11077
11078 msg.hwnd = hwnd;
11079 msg.message = message;
11080 msg.flags = sent|parent|wparam|lparam;
11081 if (defwndproc_counter) msg.flags |= defwinproc;
11082 if (beginpaint_counter) msg.flags |= beginpaint;
11083 msg.wParam = wParam;
11084 msg.lParam = lParam;
11085 msg.descr = "parent";
11086 add_message(&msg);
11087 }
11088
11089 if (message == WM_PAINT)
11090 {
11091 PAINTSTRUCT ps;
11092 beginpaint_counter++;
11093 BeginPaint( hwnd, &ps );
11094 beginpaint_counter--;
11095 EndPaint( hwnd, &ps );
11096 return 0;
11097 }
11098
11099 defwndproc_counter++;
11101 defwndproc_counter--;
11102
11103 return message == WM_COMPAREITEM ? -1 : ret;
11104}
11105
11107{
11108 if (message == WM_CREATE)
11109 PostMessageA(hwnd, WM_CLOSE, 0, 0);
11110 else if (message == WM_CLOSE)
11111 {
11112 /* Only the first WM_QUIT will survive the window destruction */
11113 PostMessageA(hwnd, WM_USER, 0x1234, 0x5678);
11114 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678);
11115 PostMessageA(hwnd, WM_QUIT, 0x4321, 0x8765);
11116 }
11117
11118 return DefWindowProcA(hwnd, message, wp, lp);
11119}
11120
11122{
11123 static LONG defwndproc_counter = 0;
11124 LRESULT ret;
11125 struct recvd_message msg;
11126
11127 if (ignore_message( message )) return 0;
11128
11129 if (test_def_id)
11130 {
11132 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
11133 if (after_end_dialog)
11134 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %Ix\n", ret );
11135 else
11136 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %Ix\n", ret);
11137 }
11138
11139 msg.hwnd = hwnd;
11140 msg.message = message;
11141 msg.flags = sent|wparam|lparam;
11142 if (defwndproc_counter) msg.flags |= defwinproc;
11143 msg.wParam = wParam;
11144 msg.lParam = lParam;
11145 msg.descr = "dialog";
11146 add_message(&msg);
11147
11148 defwndproc_counter++;
11150 defwndproc_counter--;
11151
11152 return ret;
11153}
11154
11156{
11157 static LONG defwndproc_counter = 0;
11158 LRESULT ret;
11159 struct recvd_message msg;
11160
11161 /* log only specific messages we are interested in */
11162 switch (message)
11163 {
11164#if 0 /* probably log these as well */
11165 case WM_ACTIVATE:
11166 case WM_SETFOCUS:
11167 case WM_KILLFOCUS:
11168#endif
11169 case WM_SHOWWINDOW:
11170 case WM_SIZE:
11171 case WM_MOVE:
11172 case WM_GETMINMAXINFO:
11175 break;
11176
11177 default: /* ignore */
11178 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
11180 }
11181
11182 msg.hwnd = hwnd;
11183 msg.message = message;
11184 msg.flags = sent|wparam|lparam;
11185 if (defwndproc_counter) msg.flags |= defwinproc;
11186 msg.wParam = wParam;
11187 msg.lParam = lParam;
11188 msg.descr = "show";
11189 add_message(&msg);
11190
11191 defwndproc_counter++;
11193 defwndproc_counter--;
11194
11195 return ret;
11196}
11197
11199{
11200 switch (msg)
11201 {
11202 case WM_CREATE: return 0;
11203 case WM_PAINT:
11204 {
11205 MSG msg2;
11206 static int i = 0;
11207
11208 if (i < 256)
11209 {
11210 i++;
11211 if (PeekMessageA(&msg2, 0, 0, 0, 1))
11212 {
11213 TranslateMessage(&msg2);
11214 DispatchMessageA(&msg2);
11215 }
11216 i--;
11217 }
11218 else ok(broken(1), "infinite loop\n");
11219 if ( i == 0)
11222 }
11223 }
11225}
11226
11228{
11229 static LONG defwndproc_counter = 0;
11230 LRESULT ret;
11231 struct recvd_message msg;
11232 DWORD queue_status;
11233
11234 if (ignore_message( message )) return 0;
11235
11236 if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) ||
11238 {
11239 msg.hwnd = hwnd;
11240 msg.message = message;
11241 msg.flags = sent|wparam|lparam;
11242 if (defwndproc_counter) msg.flags |= defwinproc;
11243 msg.wParam = wParam;
11244 msg.lParam = lParam;
11245 msg.descr = "HotkeyMsgCheckProcA";
11246 add_message(&msg);
11247 }
11248
11249 defwndproc_counter++;
11251 defwndproc_counter--;
11252
11253 if (message == WM_APP)
11254 {
11255 queue_status = GetQueueStatus(QS_HOTKEY);
11256 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status);
11257 queue_status = GetQueueStatus(QS_POSTMESSAGE);
11258 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %lx\n", queue_status);
11259 PostMessageA(hwnd, WM_APP+1, 0, 0);
11260 }
11261 else if (message == WM_APP+1)
11262 {
11263 queue_status = GetQueueStatus(QS_HOTKEY);
11264 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %lx\n", queue_status);
11265 }
11266
11267 return ret;
11268}
11269
11270static void register_classes(void)
11271{
11272 WNDCLASSA cls;
11273 WNDCLASSW clsW;
11274
11275 cls.style = 0;
11277 cls.cbClsExtra = 0;
11278 cls.cbWndExtra = 0;
11279 cls.hInstance = GetModuleHandleA(0);
11280 cls.hIcon = 0;
11283 cls.lpszMenuName = NULL;
11284 cls.lpszClassName = "TestWindowClass";
11285 register_class(&cls);
11286
11288 cls.lpszClassName = "HotkeyWindowClass";
11289 register_class(&cls);
11290
11292 cls.lpszClassName = "ShowWindowClass";
11293 register_class(&cls);
11294
11296 cls.lpszClassName = "TestPopupClass";
11297 register_class(&cls);
11298
11300 cls.lpszClassName = "TestParentClass";
11301 register_class(&cls);
11302
11304 cls.lpszClassName = "StopQuitClass";
11305 register_class(&cls);
11306
11308 cls.lpszClassName = "SimpleWindowClass";
11309 register_class(&cls);
11310
11312 cls.lpszClassName = "PaintLoopWindowClass";
11313 register_class(&cls);
11314
11315 cls.style = CS_NOCLOSE;
11316 cls.lpszClassName = "NoCloseWindowClass";
11317 register_class(&cls);
11318
11319 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
11320 cls.style = 0;
11321 cls.hInstance = GetModuleHandleA(0);
11322 cls.hbrBackground = 0;
11324 cls.lpszClassName = "TestDialogClass";
11325 register_class(&cls);
11326
11328 cls.style = CS_PARENTDC;
11329 cls.lpszClassName = "SimpleWindowClassWithParentDC";
11330 register_class(&cls);
11331
11332 clsW.style = 0;
11334 clsW.cbClsExtra = 0;
11335 clsW.cbWndExtra = 0;
11336 clsW.hInstance = GetModuleHandleW(0);
11337 clsW.hIcon = 0;
11338 clsW.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
11340 clsW.lpszMenuName = NULL;
11342 RegisterClassW(&clsW); /* ignore error, this fails on Win9x */
11343}
11344
11346{
11347 char buf[256];
11348
11349 if (GetClassNameA(hwnd, buf, sizeof(buf)))
11350 {
11351 if (!lstrcmpiA(buf, "TestWindowClass") ||
11352 !lstrcmpiA(buf, "ShowWindowClass") ||
11353 !lstrcmpiA(buf, "TestParentClass") ||
11354 !lstrcmpiA(buf, "TestPopupClass") ||
11355 !lstrcmpiA(buf, "SimpleWindowClass") ||
11356 !lstrcmpiA(buf, "TestDialogClass") ||
11357 !lstrcmpiA(buf, "MDI_frame_class") ||
11358 !lstrcmpiA(buf, "MDI_client_class") ||
11359 !lstrcmpiA(buf, "MDI_child_class") ||
11360 !lstrcmpiA(buf, "my_button_class") ||
11361 !lstrcmpiA(buf, "my_edit_class") ||
11362 !lstrcmpiA(buf, "static") ||
11363 !lstrcmpiA(buf, "ListBox") ||
11364 !lstrcmpiA(buf, "ComboBox") ||
11365 !lstrcmpiA(buf, "MyDialogClass") ||
11366 !lstrcmpiA(buf, "#32770") ||
11367 !lstrcmpiA(buf, "#32768"))
11368 return TRUE;
11369 }
11370 return FALSE;
11371}
11372
11374{
11375 HWND hwnd;
11376
11377 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
11378
11379 if (nCode == HCBT_CLICKSKIPPED)
11380 {
11381 /* ignore this event, XP sends it a lot when switching focus between windows */
11382 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
11383 }
11384
11385 if (nCode == HCBT_SYSCOMMAND || nCode == HCBT_KEYSKIPPED)
11386 {
11387 struct recvd_message msg;
11388
11389 msg.hwnd = 0;
11390 msg.message = nCode;
11391 msg.flags = hook|wparam|lparam;
11392 msg.wParam = wParam;
11393 msg.lParam = lParam;
11394 msg.descr = "CBT";
11395 add_message(&msg);
11396
11397 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
11398 }
11399
11400 if (nCode == HCBT_DESTROYWND)
11401 {
11403 {
11405 if (style & WS_CHILD)
11407 else if (style & WS_POPUP)
11409 else
11411 }
11412 }
11413
11414 /* Log also SetFocus(0) calls */
11415 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
11416
11418 {
11419 struct recvd_message msg;
11420
11421 msg.hwnd = hwnd;
11422 msg.message = nCode;
11423 msg.flags = hook|wparam|lparam;
11424 msg.wParam = wParam;
11425 msg.lParam = lParam;
11426 msg.descr = "CBT";
11427 add_message(&msg);
11428 }
11429 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
11430}
11431
11433 DWORD event,
11434 HWND hwnd,
11435 LONG object_id,
11436 LONG child_id,
11438 DWORD event_time)
11439{
11440 ok(thread_id == winevent_hook_thread_id, "we didn't ask for events from other threads\n");
11441
11442 /* ignore mouse cursor events */
11443 if (object_id == OBJID_CURSOR) return;
11444
11445 if (!hwnd || is_our_logged_class(hwnd))
11446 {
11447 struct recvd_message msg;
11448
11449 msg.hwnd = hwnd;
11450 msg.message = event;
11452 msg.wParam = object_id;
11453 msg.lParam = child_id;
11454 msg.descr = "WEH";
11455 add_message(&msg);
11456 }
11457}
11458
11459static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
11460static const WCHAR wszAnsi[] = {'U',0};
11461
11462static const GUID iface_guid = {0x66666666};
11463
11465{
11466 const DEV_BROADCAST_DEVICEINTERFACE_A *ifaceA = (const void *)lParam;
11467
11468 switch (uMsg)
11469 {
11470 case CB_FINDSTRINGEXACT:
11472 return 1;
11474 return 0;
11475 return -1;
11476
11477 case WM_DEVICECHANGE:
11479 {
11480 DWORD expect_size = offsetof(DEV_BROADCAST_DEVICEINTERFACE_A, dbcc_name[strlen(ifaceA->dbcc_name)]);
11481
11482 ok(ifaceA->dbcc_size == expect_size, "Expected %lu, got %lu.\n", expect_size, ifaceA->dbcc_size);
11484 "Got notification type %#lx.\n", ifaceA->dbcc_devicetype);
11485 ok(!ifaceA->dbcc_reserved, "Got reserved %#lx.\n", ifaceA->dbcc_reserved);
11486 ok(!strcmp(ifaceA->dbcc_name, "test name"), "Got name %s.\n", debugstr_a(ifaceA->dbcc_name));
11487 return 2;
11488 }
11489 }
11490 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
11491}
11492
11493static const struct message WmGetTextLengthAfromW[] = {
11496 { 0 }
11497};
11498
11499static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0};
11500
11501/* dummy window proc for WM_GETTEXTLENGTH test */
11503{
11504 switch(msg)
11505 {
11506 case WM_GETTEXTLENGTH:
11507 return lstrlenW(dummy_window_text) + 37; /* some random length */
11508 case WM_GETTEXT:
11510 return lstrlenW( (LPWSTR)lp );
11511 default:
11512 return DefWindowProcW( hwnd, msg, wp, lp );
11513 }
11514}
11515
11517{
11518 static const WCHAR wszMsgConversionClass[] =
11519 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
11520 char buffer[200];
11521 DEV_BROADCAST_DEVICEINTERFACE_A *dev_interface = (void *)buffer;
11522 WNDCLASSW cls;
11523 LRESULT lRes;
11524 HWND hwnd;
11525 WNDPROC wndproc, newproc;
11526 BOOL ret;
11527
11528 cls.style = 0;
11530 cls.cbClsExtra = 0;
11531 cls.cbWndExtra = 0;
11533 cls.hIcon = NULL;
11535 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
11536 cls.lpszMenuName = NULL;
11537 cls.lpszClassName = wszMsgConversionClass;
11538 /* this call will fail on Win9x, but that doesn't matter as this test is
11539 * meaningless on those platforms */
11540 if(!RegisterClassW(&cls)) return;
11541
11542 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
11543 100, 100, 200, 200, 0, 0, 0, NULL);
11544 ok(hwnd != NULL, "Window creation failed\n");
11545
11546 /* {W, A} -> A */
11547
11550 ok(lRes == 0, "String should have been converted\n");
11552 ok(lRes == 1, "String shouldn't have been converted\n");
11553
11554 /* {W, A} -> W */
11555
11558 ok(lRes == 1, "String shouldn't have been converted\n");
11560 ok(lRes == 1, "String shouldn't have been converted\n");
11561
11562 /* Synchronous messages */
11563
11565 ok(lRes == 0, "String should have been converted\n");
11567 ok(lRes == 1, "String shouldn't have been converted\n");
11568
11569 /* Asynchronous messages */
11570
11571 SetLastError(0);
11574 "PostMessage on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11575 SetLastError(0);
11578 "PostMessage on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11579 SetLastError(0);
11582 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11583 SetLastError(0);
11586 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11587 SetLastError(0);
11590 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11591 SetLastError(0);
11594 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11595 SetLastError(0);
11598 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11599 SetLastError(0);
11602 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes, GetLastError());
11603
11604 /* Test WM_DEVICECHANGE. */
11605
11607 dev_interface->dbcc_reserved = 0;
11608 dev_interface->dbcc_classguid = iface_guid;
11609 strcpy(dev_interface->dbcc_name, "test name");
11611 dbcc_name[strlen(dev_interface->dbcc_name)]);
11612 lRes = SendMessageA(hwnd, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)dev_interface);
11613 ok(lRes == 2, "Got %Id, error %lu.\n", lRes, GetLastError());
11614
11616
11617 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
11618
11621 100, 100, 200, 200, 0, 0, 0, NULL);
11622 ok(!!hwnd, "Failed to create window, error %lu.\n", GetLastError());
11624 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0);
11625 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
11627 "got bad length %Id\n", lRes );
11628
11631 hwnd, WM_GETTEXTLENGTH, 0, 0);
11632 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
11634 "got bad length %Id\n", lRes );
11635
11638 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
11640 NULL, 0, NULL, NULL ) ||
11641 broken(lRes == lstrlenW(dummy_window_text) + 37),
11642 "got bad length %Id\n", lRes );
11643
11644 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */
11645 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
11647 NULL, 0, NULL, NULL ) ||
11648 broken(lRes == lstrlenW(dummy_window_text) + 37),
11649 "got bad length %Id\n", lRes );
11650
11652 ok( ret, "DestroyWindow() error %ld\n", GetLastError());
11653}
11654
11656{
11660};
11661
11663{
11664}
11665
11666#define TIMER_ID 0x19
11667#define TIMER_COUNT 500 /* 499 samples */
11668#define TIMER_DURATION_EXPECTED 10000 /* 10 ms */
11669#define TIMER_DURATION_ALT 15600 /* 15.6 ms */
11670#define TIMER_DURATION_TOLERANCE 1000 /* 1 ms */
11671
11672static int count = 0;
11674static int timer_duration = 0;
11675
11676static int compare_ulonglong(const void *a, const void *b)
11677{
11678 ULONGLONG la, lb;
11679 la = *(ULONGLONG*)a;
11680 lb = *(ULONGLONG*)b;
11681 return (la > lb) - (la < lb);
11682}
11683
11684static void timer_fired(void)
11685{
11686 if (count < TIMER_COUNT)
11687 {
11688 LARGE_INTEGER performance_counter;
11689 BOOL ret;
11690
11691 ret = QueryPerformanceCounter(&performance_counter);
11692 ok(ret, "QueryPerformanceCounter failed\n");
11693
11694 timer_ticks[count] = performance_counter.QuadPart;
11695 }
11696
11697 count++;
11698
11699 if (count == TIMER_COUNT)
11700 {
11701 LARGE_INTEGER performance_frequency;
11702 BOOL ret;
11703
11704 /* calculate durations */
11705 for (int i=0; i < TIMER_COUNT-1; i++)
11707
11709
11710 ret = QueryPerformanceFrequency(&performance_frequency);
11711 ok(ret, "QueryPerformanceFrequency failed\n");
11712
11713 /* median duration, converted to microseconds */
11714 timer_duration = (int)(timer_ticks[(TIMER_COUNT - 1) / 2] * 1000000 / performance_frequency.QuadPart);
11715 }
11716}
11717
11719{
11720 timer_fired();
11721}
11722
11725{
11726 timer_fired();
11728}
11729
11731{
11732 struct timer_info *info = x;
11733 DWORD r;
11734
11735 r = KillTimer(info->hWnd, 0x19);
11736 ok(r,"KillTimer failed in thread\n");
11737 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
11738 ok(r,"SetTimer failed in thread\n");
11739 ok(r==TIMER_ID,"SetTimer id different\n");
11740 r = SetEvent(info->handles[0]);
11741 ok(r,"SetEvent failed in thread\n");
11742 return 0;
11743}
11744
11745static void test_timers(void)
11746{
11747 struct timer_info info;
11748 DWORD id;
11749 MSG msg;
11750
11751 info.hWnd = CreateWindowA("TestWindowClass", NULL,
11753 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
11754 NULL, NULL, 0);
11755
11756 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
11757 ok(info.id, "SetTimer failed\n");
11758 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
11759 info.handles[0] = CreateEventW(NULL,0,0,NULL);
11760 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
11761
11763
11764 WaitForSingleObject(info.handles[1], INFINITE);
11765
11766 CloseHandle(info.handles[0]);
11767 CloseHandle(info.handles[1]);
11768
11769 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
11770
11771 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
11772 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
11773 * 15.6 ms.
11774 */
11775 count = 0;
11776 id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count);
11777 ok(id != 0, "did not get id from SetTimer.\n");
11778 ok(id==TIMER_ID, "SetTimer timer ID different\n");
11779 while (count < TIMER_COUNT && GetMessageA(&msg, info.hWnd, 0, 0))
11783 "did not get expected median timeout (%d != ~%d).\n",
11785 ok(KillTimer(info.hWnd, id), "KillTimer failed\n");
11786 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
11787 if (pSetSystemTimer)
11788 {
11789 count = 0;
11790 id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count);
11791 ok(id != 0, "did not get id from SetSystemTimer.\n");
11792 ok(id==TIMER_ID, "SetTimer timer ID different\n");
11793 while (count < TIMER_COUNT && GetMessageA(&msg, info.hWnd, 0, 0))
11794 {
11795 if (msg.message == WM_SYSTIMER)
11796 timer_fired();
11797 ok(msg.message != WM_TIMER, "unexpected WM_TIMER\n");
11799 }
11802 "did not get expected median timeout (%d != ~%d).\n",
11804 ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n");
11805 }
11806
11807 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
11808}
11809
11810static void test_timers_no_wnd(void)
11811{
11812 static UINT_PTR ids[0xffff];
11813 UINT_PTR id, id2;
11814 DWORD start;
11815 MSG msg;
11816 int i;
11817
11818 count = 0;
11819 id = SetTimer(NULL, 0, 100, callback_count);
11820 ok(id != 0, "did not get id from SetTimer.\n");
11821 id2 = SetTimer(NULL, id, 200, callback_count);
11822 ok(id2 == id, "did not get same id from SetTimer when replacing (%Ii expected %Ii).\n", id2, id);
11823 Sleep(150);
11824 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
11825 ok(count == 0, "did not get zero count as expected (%i).\n", count);
11826 Sleep(150);
11827 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
11828 ok(count == 1, "did not get one count as expected (%i).\n", count);
11829 KillTimer(NULL, id);
11830 Sleep(250);
11831 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
11832 ok(count == 1, "killing replaced timer did not work (%i).\n", count);
11833
11834 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
11835 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
11836 * 15.6 ms.
11837 */
11838 count = 0;
11839 id = SetTimer(NULL, 0, 0, callback_count);
11840 ok(id != 0, "did not get id from SetTimer.\n");
11841 while (count < TIMER_COUNT && GetMessageA(&msg, NULL, 0, 0))
11845 "did not get expected median timeout (%d != ~%d).\n",
11847 KillTimer(NULL, id);
11848 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
11849
11850 if (pSetCoalescableTimer)
11851 {
11852 count = 0;
11853 id = pSetCoalescableTimer(NULL, 0, 0, callback_count, 0);
11854 ok(id != 0, "SetCoalescableTimer failed with %lu.\n", GetLastError());
11855 start = GetTickCount();
11856 while (GetTickCount()-start < 100 && GetMessageA(&msg, NULL, 0, 0))
11858 ok(count > 1, "expected count > 1, got %d.\n", count);
11859 KillTimer(NULL, id);
11860 }
11861 else
11862 win_skip("SetCoalescableTimer not available.\n");
11863
11864 /* Check what happens when we're running out of timers */
11865 for (i = 0; i < ARRAY_SIZE(ids); i++)
11866 {
11867 SetLastError(0xdeadbeef);
11869 if (!ids[i]) break;
11870 }
11871 ok(i != ARRAY_SIZE(ids), "all timers were created successfully\n");
11873 "GetLastError() = %ld\n", GetLastError());
11874 while (i > 0) KillTimer(NULL, ids[--i]);
11875}
11876
11878{
11879 UINT_PTR id;
11880 MSG msg;
11881
11882 exception = code;
11883 id = SetTimer(NULL, 0, 1000, callback_exception);
11884 ok(id != 0, "did not get id from SetTimer.\n");
11885
11886 memset(&msg, 0, sizeof(msg));
11887 msg.message = WM_TIMER;
11888 msg.wParam = id;
11889 msg.lParam = (LPARAM)callback_exception;
11890
11891 count = 0;
11893 ok(count == 1, "did not get one count as expected (%i).\n", count);
11894
11895 KillTimer(NULL, id);
11896}
11897
11898static void test_timers_exceptions(void)
11899{
11909 test_timers_exception(0xE000BEEF); /* customer exception */
11910}
11911
11912/* Various win events with arbitrary parameters */
11913static const struct message WmWinEventsSeq[] = {
11914 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
11915 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
11916 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
11917 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
11918 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
11919 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
11920 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
11921 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
11922 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
11923 /* our win event hook ignores OBJID_CURSOR events */
11924 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
11925 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
11926 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
11927 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
11928 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
11929 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
11930 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
11931 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
11932 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
11933 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
11934 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
11935 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
11936 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
11937 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
11938 { 0 }
11939};
11940static const struct message WmWinEventCaretSeq[] = {
11941 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
11942 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
11943 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */
11944 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
11945 { 0 }
11946};
11947static const struct message WmWinEventCaretSeq_2[] = {
11948 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
11949 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
11950 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
11951 { 0 }
11952};
11953static const struct message WmWinEventAlertSeq[] = {
11954 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 },
11955 { 0 }
11956};
11957static const struct message WmWinEventAlertSeq_2[] = {
11958 /* create window in the thread proc */
11959 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 },
11960 /* our test event */
11961 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 },
11962 { 0 }
11963};
11964static const struct message WmGlobalHookSeq_1[] = {
11965 /* create window in the thread proc */
11966 { HCBT_CREATEWND, hook|lparam, 0, 2 },
11967 /* our test events */
11970 { 0 }
11971};
11972static const struct message WmGlobalHookSeq_2[] = {
11973 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */
11974 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */
11975 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */
11976 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */
11977 { 0 }
11978};
11979
11980static const struct message WmMouseLLHookSeq[] = {
11981 { WM_MOUSEMOVE, hook },
11982 { WM_LBUTTONUP, hook },
11983 { WM_MOUSEMOVE, hook },
11984 { 0 }
11985};
11986
11988 DWORD event,
11989 HWND hwnd,
11990 LONG object_id,
11991 LONG child_id,
11993 DWORD event_time)
11994{
11995 char buf[256];
11996
11997 if (GetClassNameA(hwnd, buf, sizeof(buf)))
11998 {
11999 if (!lstrcmpiA(buf, "TestWindowClass") ||
12000 !lstrcmpiA(buf, "static"))
12001 {
12002 struct recvd_message msg;
12003
12004 msg.hwnd = hwnd;
12005 msg.message = event;
12007 msg.wParam = object_id;
12008 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2);
12009 msg.descr = "WEH_2";
12010 add_message(&msg);
12011 }
12012 }
12013}
12014
12015static HHOOK hCBT_global_hook;
12017
12019{
12020 HWND hwnd;
12021 char buf[256];
12022
12023 if (nCode == HCBT_SYSCOMMAND)
12024 {
12025 struct recvd_message msg;
12026
12027 msg.hwnd = 0;
12028 msg.message = nCode;
12029 msg.flags = hook|wparam|lparam;
12030 msg.wParam = wParam;
12031 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
12032 msg.descr = "CBT_2";
12033 add_message(&msg);
12034
12036 }
12037 /* WH_MOUSE_LL hook */
12038 if (nCode == HC_ACTION)
12039 {
12041
12042 /* we can't test for real mouse events */
12043 if (mhll->flags & LLMHF_INJECTED)
12044 {
12045 struct recvd_message msg;
12046
12047 memset (&msg, 0, sizeof (msg));
12048 msg.message = wParam;
12049 msg.flags = hook;
12050 msg.descr = "CBT_2";
12051 add_message(&msg);
12052 }
12054 }
12055
12056 /* Log also SetFocus(0) calls */
12057 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
12058
12059 if (GetClassNameA(hwnd, buf, sizeof(buf)))
12060 {
12061 if (!lstrcmpiA(buf, "TestWindowClass") ||
12062 !lstrcmpiA(buf, "static"))
12063 {
12064 struct recvd_message msg;
12065
12066 msg.hwnd = hwnd;
12067 msg.message = nCode;
12068 msg.flags = hook|wparam|lparam;
12069 msg.wParam = wParam;
12070 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
12071 msg.descr = "CBT_2";
12072 add_message(&msg);
12073 }
12074 }
12076}
12077
12079{
12080 HWND hwnd;
12081 MSG msg;
12082 HANDLE hevent = *(HANDLE *)param;
12083
12084 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
12085 ok(!!hwnd, "Failed to create window, error %lu.\n", GetLastError());
12086 if (winetest_debug > 1) trace("created thread window %p\n", hwnd);
12087
12088 *(HWND *)param = hwnd;
12089
12091 /* this event should be received only by our new hook proc,
12092 * an old one does not expect an event from another thread.
12093 */
12094 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0);
12096
12097 while (GetMessageA(&msg, 0, 0, 0))
12098 {
12101 }
12102 return 0;
12103}
12104
12106{
12107 HWND hwnd;
12108 MSG msg;
12109 HANDLE hevent = *(HANDLE *)param;
12110
12112 /* these events should be received only by our new hook proc,
12113 * an old one does not expect an event from another thread.
12114 */
12115
12116 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
12117 ok(!!hwnd, "Failed to create window, error %lu.\n", GetLastError());
12118 if (winetest_debug > 1) trace("created thread window %p\n", hwnd);
12119
12120 *(HWND *)param = hwnd;
12121
12122 /* Windows doesn't like when a thread plays games with the focus,
12123 that leads to all kinds of misbehaviours and failures to activate
12124 a window. So, better keep next lines commented out.
12125 SetFocus(0);
12126 SetFocus(hwnd);*/
12127
12130
12132
12133 while (GetMessageA(&msg, 0, 0, 0))
12134 {
12137 }
12138 return 0;
12139}
12140
12142{
12143 HWND hwnd;
12144 MSG msg;
12145 HANDLE hevent = *(HANDLE *)param;
12146
12147 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
12148 ok(!!hwnd, "Failed to create window, error %lu.\n", GetLastError());
12149 if (winetest_debug > 1) trace("created thread window %p\n", hwnd);
12150
12151 *(HWND *)param = hwnd;
12152
12154
12155 /* Windows doesn't like when a thread plays games with the focus,
12156 * that leads to all kinds of misbehaviours and failures to activate
12157 * a window. So, better don't generate a mouse click message below.
12158 */
12159 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
12160 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
12161 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
12162
12164 while (GetMessageA(&msg, 0, 0, 0))
12165 {
12168 }
12169 return 0;
12170}
12171
12172static void test_winevents(void)
12173{
12174 BOOL ret;
12175 MSG msg;
12176 HWND hwnd, hwnd2;
12177 UINT i;
12178 HANDLE hthread, hevent;
12179 DWORD tid;
12181 const struct message *events = WmWinEventsSeq;
12182
12183 hwnd = CreateWindowExA(0, "TestWindowClass", NULL,
12185 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
12186 NULL, NULL, 0);
12187 ok(!!hwnd, "Failed to create window, error %lu.\n", GetLastError());
12188
12189 /****** start of global hook test *************/
12191 if (!hCBT_global_hook)
12192 {
12193 ok(DestroyWindow(hwnd), "failed to destroy window\n");
12194 skip( "cannot set global hook\n" );
12195 return;
12196 }
12197
12198 hevent = CreateEventA(NULL, 0, 0, NULL);
12199 ok(!!hevent, "Failed to create event, error %lu.\n", GetLastError());
12200 hwnd2 = hevent;
12201
12202 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid);
12203 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
12204
12205 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
12206
12207 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
12208
12210 /* this one should be received only by old hook proc */
12212 /* this one should be received only by old hook proc */
12214
12215 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
12216
12218 ok( ret, "UnhookWindowsHookEx error %ld\n", GetLastError());
12219
12221 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
12222 CloseHandle(hthread);
12224 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
12225 /****** end of global hook test *************/
12226
12227 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent)
12228 {
12229 ok(DestroyWindow(hwnd), "failed to destroy window\n");
12230 return;
12231 }
12232
12234
12235 if (0)
12236 {
12237 /* this test doesn't pass under Win9x */
12238 /* win2k ignores events with hwnd == 0 */
12239 SetLastError(0xdeadbeef);
12240 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
12241 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
12242 GetLastError() == 0xdeadbeef, /* Win9x */
12243 "unexpected error %ld\n", GetLastError());
12244 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
12245 }
12246
12247 for (i = 0; i < ARRAY_SIZE(WmWinEventsSeq); i++)
12248 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
12249
12250 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
12251
12252 /****** start of event filtering test *************/
12253 hhook = pSetWinEventHook(
12254 EVENT_OBJECT_SHOW, /* 0x8002 */
12255 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */
12259 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
12260
12261 hevent = CreateEventA(NULL, 0, 0, NULL);
12262 ok(!!hevent, "Failed to create event, error %lu.\n", GetLastError());
12263 hwnd2 = hevent;
12264
12265 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
12266 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
12267
12268 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
12269
12270 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
12271
12273 /* this one should be received only by old hook proc */
12274 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
12275 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
12276 /* this one should be received only by old hook proc */
12277 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
12278
12279 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
12280
12281 ret = pUnhookWinEvent(hhook);
12282 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
12283
12285 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
12286 CloseHandle(hthread);
12288 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
12289 /****** end of event filtering test *************/
12290
12291 /****** start of out of context event test *************/
12292 hhook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0,
12295 ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
12296
12297 hevent = CreateEventA(NULL, 0, 0, NULL);
12298 ok(!!hevent, "Failed to create event, error %lu.\n", GetLastError());
12299 hwnd2 = hevent;
12300
12302
12303 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
12304 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
12305
12306 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
12307
12308 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
12309 /* process pending winevent messages */
12310 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
12311 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
12312
12314 /* this one should be received only by old hook proc */
12315 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
12316 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
12317 /* this one should be received only by old hook proc */
12318 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
12319
12320 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE);
12321 /* process pending winevent messages */
12322 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
12323 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
12324
12325 ret = pUnhookWinEvent(hhook);
12326 ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
12327
12329 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
12330 CloseHandle(hthread);
12332 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
12333 /****** end of out of context event test *************/
12334
12335 /****** start of MOUSE_LL hook test *************/
12337 /* WH_MOUSE_LL is not supported on Win9x platforms */
12338 if (!hCBT_global_hook)
12339 {
12340 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
12341 goto skip_mouse_ll_hook_test;
12342 }
12343
12344 hevent = CreateEventA(NULL, 0, 0, NULL);
12345 ok(!!hevent, "Failed to create event, error %lu.\n", GetLastError());
12346 hwnd2 = hevent;
12347
12348 hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid);
12349 ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
12350
12351 while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT)
12352 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
12353
12354 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE);
12356
12357 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
12358 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
12359 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
12360
12361 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE);
12362
12364 ok( ret, "UnhookWindowsHookEx error %ld\n", GetLastError());
12365
12367 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
12368 CloseHandle(hthread);
12370 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
12371 /****** end of MOUSE_LL hook test *************/
12372skip_mouse_ll_hook_test:
12373
12374 ok(DestroyWindow(hwnd), "failed to destroy window\n");
12375}
12376
12377static char *get_test_dll_path(void)
12378{
12379 static const char *dll_name = "testdll.dll";
12380 static char path[MAX_PATH];
12381 DWORD written;
12382 HANDLE file;
12383 HRSRC res;
12384 void *ptr;
12385
12387 strcat(path, dll_name);
12388
12390 ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s: %lu.\n", debugstr_a(path), GetLastError());
12391