ReactOS 0.4.16-dev-1040-g85afe48
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 <assert.h>
24#include <limits.h>
25#include <stdarg.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
35#include "wine/test.h"
36
37#define MDI_FIRST_CHILD_ID 2004
38
39/* undocumented SWP flags - from SDK 3.1 */
40#define SWP_NOCLIENTSIZE 0x0800
41#define SWP_NOCLIENTMOVE 0x1000
42#define SWP_STATECHANGED 0x8000
43
44#define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
45
46#ifndef WM_KEYF1
47#define WM_KEYF1 0x004d
48#endif
49
50#ifndef WM_SYSTIMER
51#define WM_SYSTIMER 0x0118
52#endif
53
54#define WND_PARENT_ID 1
55#define WND_POPUP_ID 2
56#define WND_CHILD_ID 3
57
58#ifndef WM_LBTRACKPOINT
59#define WM_LBTRACKPOINT 0x0131
60#endif
61
62#ifdef __i386__
63#define ARCH "x86"
64#elif defined __x86_64__
65#define ARCH "amd64"
66#elif defined __arm__
67#define ARCH "arm"
68#elif defined __aarch64__
69#define ARCH "arm64"
70#else
71#define ARCH "none"
72#endif
73
74static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
75static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
76static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
77static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
78static BOOL (WINAPI *pQueryActCtxW)(DWORD,HANDLE,void*,ULONG,void*,SIZE_T,SIZE_T*);
79static void (WINAPI *pReleaseActCtx)(HANDLE);
80
81/* encoded DRAWITEMSTRUCT into an LPARAM */
82typedef struct
83{
84 union
85 {
86 struct
87 {
88 UINT type : 4; /* ODT_* flags */
89 UINT ctl_id : 4; /* Control ID */
90 UINT item_id : 4; /* Menu item ID */
91 UINT action : 4; /* ODA_* flags */
92 UINT state : 16; /* ODS_* flags */
95 } u;
97
98/* encoded MEASUREITEMSTRUCT into a WPARAM */
99typedef struct
100{
101 union
102 {
103 struct
104 {
105 UINT CtlType : 4;
106 UINT CtlID : 4;
107 UINT itemID : 4;
108 UINT wParam : 20;
110 WPARAM wp;
111 } u;
113
117static HHOOK hKBD_hook;
118static HHOOK hCBT_hook;
120
121static const WCHAR testWindowClassW[] =
122{ 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
123
125
126/*
127FIXME: add tests for these
128Window Edge Styles (Win31/Win95/98 look), in order of precedence:
129 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
130 WS_THICKFRAME: thick border
131 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
132 WS_BORDER (default for overlapped windows): single black border
133 none (default for child (and popup?) windows): no border
134*/
135
136typedef enum {
137 sent=0x1,
141 lparam=0x10,
145 hook=0x100,
147 kbd_hook=0x400
149
150struct message {
151 UINT message; /* the WM_* code */
152 msg_flags_t flags; /* message props */
153 WPARAM wParam; /* expected value of wParam */
154 LPARAM lParam; /* expected value of lParam */
155 WPARAM wp_mask; /* mask for wParam checks */
156 LPARAM lp_mask; /* mask for lParam checks */
157};
158
159struct recvd_message {
160 UINT message; /* the WM_* code */
161 msg_flags_t flags; /* message props */
162 HWND hwnd; /* window that received the message */
163 WPARAM wParam; /* expected value of wParam */
164 LPARAM lParam; /* expected value of lParam */
165 int line; /* source line where logged */
166 const char *descr; /* description for trace output */
167 char output[512]; /* trace output */
168};
169
170/* Empty message sequence */
171static const struct message WmEmptySeq[] =
172{
173 { 0 }
174};
175/* CreateWindow (for overlapped window, not initially visible) (16/32) */
176static const struct message WmCreateOverlappedSeq[] = {
177 { HCBT_CREATEWND, hook },
179 { WM_NCCREATE, sent },
180 { WM_NCCALCSIZE, sent|wparam, 0 },
181 { 0x0093, sent|defwinproc|optional },
182 { 0x0094, sent|defwinproc|optional },
183 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
184 { WM_CREATE, sent },
185 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
186 { 0 }
187};
188/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
189 * for a not visible overlapped window.
190 */
191static const struct message WmSWP_ShowOverlappedSeq[] = {
193 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
197 { HCBT_ACTIVATE, hook },
198 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
199 { WM_NOTIFYFORMAT, sent|optional },
200 { WM_QUERYUISTATE, sent|optional },
202 { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */
203 { WM_ACTIVATEAPP, sent|wparam, 1 },
204 { WM_NCACTIVATE, sent },
206 { WM_ACTIVATE, sent|wparam, 1 },
207 { HCBT_SETFOCUS, hook },
210 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
216 /* Win9x adds SWP_NOZORDER below */
222 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
229 { 0 }
230};
231/* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
232 * for a visible overlapped window.
233 */
234static const struct message WmSWP_HideOverlappedSeq[] = {
236 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
243 { 0 }
244};
245
246/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
247 * for a visible overlapped window.
248 */
249static const struct message WmSWP_ResizeSeq[] = {
262 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
263 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
264 { 0 }
265};
266
267/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
268 * for a visible popup window.
269 */
270static const struct message WmSWP_ResizePopupSeq[] = {
272 { WM_GETMINMAXINFO, sent|defwinproc|optional }, /* Win9x */
283 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
284 { 0 }
285};
286
287/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
288 * for a visible overlapped window.
289 */
290static const struct message WmSWP_MoveSeq[] = {
297 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
298 { 0 }
299};
300/* Resize with SetWindowPos(SWP_NOZORDER)
301 * for a visible overlapped window
302 * SWP_NOZORDER is stripped by the logging code
303 */
304static const struct message WmSWP_ResizeNoZOrder[] = {
305 { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE },
311 { WM_WINDOWPOSCHANGED, sent|wparam|optional, /*SWP_NOZORDER|*/SWP_NOACTIVATE, 0,
315 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */
316 { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */
317 { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */
318 { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */
319 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
320 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
321 { 0 }
322};
323
324/* Switch visible mdi children */
325static const struct message WmSwitchChild[] = {
326 /* Switch MDI child */
327 { WM_MDIACTIVATE, sent },/* in the MDI client */
328 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */
329 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
330 { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */
331 /* Deactivate 2nd MDI child */
332 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */
333 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */
335 /* Preparing for maximize and maximize the 1st MDI child */
336 { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */
338 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */
339 { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
341 { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */
342 /* Lock redraw 2nd MDI child */
343 { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */
345 /* Restore 2nd MDI child */
347 { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */
348 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */
350 { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */
351 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */
352 /* Redraw 2nd MDI child */
353 { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */
354 /* Redraw MDI frame */
356 { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */
358 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */
359 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
361 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */
362 { HCBT_SETFOCUS, hook },
363 { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */
364 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },/* in the 1st MDI child */
365 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
366 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
367 { WM_SETFOCUS, sent },/* in the MDI client */
368 { HCBT_SETFOCUS, hook },
369 { WM_KILLFOCUS, sent },/* in the MDI client */
370 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
371 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, /* in the 1st MDI child */
372 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
373 { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */
374 { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */
376 { 0 }
377};
378
379/* Switch visible not maximized mdi children */
380static const struct message WmSwitchNotMaximizedChild[] = {
381 /* Switch not maximized MDI child */
382 { WM_MDIACTIVATE, sent },/* in the MDI client */
383 { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 2nd MDI child */
384 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
385 { WM_CHILDACTIVATE, sent },/* in the 2nd MDI child */
386 /* Deactivate 1st MDI child */
387 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
388 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
389 /* Activate 2nd MDI child */
391 { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 2nd MDI child */
392 { HCBT_SETFOCUS, hook }, /* in the 1st MDI child */
393 { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */
394 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */
395 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */
396 { WM_SETFOCUS, sent, 0 }, /* in the MDI client */
397 { HCBT_SETFOCUS, hook },
398 { WM_KILLFOCUS, sent }, /* in the MDI client */
399 { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */
400 { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */
401 { WM_SETFOCUS, sent|defwinproc }, /* in the 2nd MDI child */
402 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */
404 { 0 }
405};
406
407
408/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
409 SWP_NOZORDER|SWP_FRAMECHANGED)
410 * for a visible overlapped window with WS_CLIPCHILDREN style set.
411 */
412static const struct message WmSWP_FrameChanged_clip[] = {
415 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */
417 { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
418 { WM_NCPAINT, sent }, /* wparam != 1 */
419 { WM_ERASEBKGND, sent },
421 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
422 { WM_PAINT, sent },
423 { 0 }
424};
425/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
426 SWP_NOZORDER|SWP_FRAMECHANGED)
427 * for a visible overlapped window.
428 */
429static const struct message WmSWP_FrameChangedDeferErase[] = {
433 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
435 { WM_NCPAINT, sent|beginpaint|parent|optional }, /* wparam != 1 */
437 { WM_PAINT, sent },
438 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
440 { 0 }
441};
442
443/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
444 SWP_NOZORDER|SWP_FRAMECHANGED)
445 * for a visible overlapped window without WS_CLIPCHILDREN style set.
446 */
447static const struct message WmSWP_FrameChanged_noclip[] = {
450 { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */
454 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
455 { WM_PAINT, sent },
456 { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
458 { 0 }
459};
460
461/* ShowWindow(SW_SHOW) for a not visible overlapped window */
462static const struct message WmShowOverlappedSeq[] = {
463 { WM_SHOWWINDOW, sent|wparam, 1 },
466 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
471 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
482 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
488 /* Win9x adds SWP_NOZORDER below */
495#if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
496 * messages. Does that mean that CreateWindow doesn't set initial
497 * window dimensions for overlapped windows?
498 */
499 { WM_SIZE, sent },
500 { WM_MOVE, sent },
501#endif
504 { 0 }
505};
506/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
507static const struct message WmShowMaxOverlappedSeq[] = {
513 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
515 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
525 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
531 /* Win9x adds SWP_NOZORDER below */
539 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
540 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
546 { 0 }
547};
548/* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
549static const struct message WmShowRestoreMaxOverlappedSeq[] = {
569 { 0 }
570};
571/* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
572static const struct message WmShowRestoreMinOverlappedSeq[] = {
577 { WM_WINDOWPOSCHANGING, sent|optional }, /* SWP_NOSIZE|SWP_NOMOVE */
580 { WM_MOVE, sent|optional },
600 { WM_ERASEBKGND, sent },
611 { WM_ACTIVATE, sent|wparam, 1 },
617 { 0 }
618};
619/* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
620static const struct message WmShowMinOverlappedSeq[] = {
623 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
631 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
638 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
639 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
640 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
645
646 /* Vista sometimes restores the window right away... */
672
676 { 0 }
677};
678/* ShowWindow(SW_HIDE) for a visible overlapped window */
679static const struct message WmHideOverlappedSeq[] = {
680 { WM_SHOWWINDOW, sent|wparam, 0 },
682 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
684 { WM_SIZE, sent|optional }, /* XP doesn't send it */
685 { WM_MOVE, sent|optional }, /* XP doesn't send it */
693 { 0 }
694};
695/* DestroyWindow for a visible overlapped window */
696static const struct message WmDestroyOverlappedSeq[] = {
698 { 0x0090, sent|optional },
700 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
701 { 0x0090, sent|optional },
709 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
710 { WM_DESTROY, sent },
711 { WM_NCDESTROY, sent },
712 { 0 }
713};
714/* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
715static const struct message WmCreateMaxPopupSeq[] = {
716 { HCBT_CREATEWND, hook },
717 { WM_NCCREATE, sent },
718 { WM_NCCALCSIZE, sent|wparam, 0 },
719 { WM_CREATE, sent },
720 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
722 { WM_MOVE, sent },
730 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
731 { WM_SHOWWINDOW, sent|wparam, 1 },
733 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
734 { HCBT_ACTIVATE, hook },
735 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
741 { WM_ACTIVATEAPP, sent|wparam, 1 },
742 { WM_NCACTIVATE, sent },
743 { WM_ACTIVATE, sent|wparam, 1 },
744 { HCBT_SETFOCUS, hook },
747 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
756 { 0 }
757};
758/* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
759static const struct message WmCreateInvisibleMaxPopupSeq[] = {
760 { HCBT_CREATEWND, hook },
761 { WM_NCCREATE, sent },
762 { WM_NCCALCSIZE, sent|wparam, 0 },
763 { WM_CREATE, sent },
764 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
766 { WM_MOVE, sent },
774 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
775 { 0 }
776};
777/* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
778static const struct message WmShowMaxPopupResizedSeq[] = {
783 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
784 { HCBT_ACTIVATE, hook },
785 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
791 { WM_ACTIVATEAPP, sent|wparam, 1 },
792 { WM_NCACTIVATE, sent },
793 { WM_ACTIVATE, sent|wparam, 1 },
794 { HCBT_SETFOCUS, hook },
797 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
803 /* WinNT4.0 sends WM_MOVE */
806 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
807 { 0 }
808};
809/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
810static const struct message WmShowMaxPopupSeq[] = {
815 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
816 { HCBT_ACTIVATE, hook },
817 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
823 { WM_ACTIVATEAPP, sent|wparam, 1 },
824 { WM_NCACTIVATE, sent },
825 { WM_ACTIVATE, sent|wparam, 1 },
826 { HCBT_SETFOCUS, hook },
829 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
838 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
840 { 0 }
841};
842/* CreateWindow(WS_VISIBLE) for popup window */
843static const struct message WmCreatePopupSeq[] = {
844 { HCBT_CREATEWND, hook },
845 { WM_NCCREATE, sent },
846 { WM_NCCALCSIZE, sent|wparam, 0 },
847 { WM_CREATE, sent },
848 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
850 { WM_MOVE, sent },
851 { WM_SHOWWINDOW, sent|wparam, 1 },
853 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
854 { HCBT_ACTIVATE, hook },
855 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
861 { WM_ACTIVATEAPP, sent|wparam, 1 },
862 { WM_NCACTIVATE, sent },
863 { WM_ACTIVATE, sent|wparam, 1 },
864 { HCBT_SETFOCUS, hook },
867 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
874 { 0 }
875};
876/* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
877static const struct message WmShowVisMaxPopupSeq[] = {
890 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
891 { 0 }
892};
893/* CreateWindow (for a child popup window, not initially visible) */
894static const struct message WmCreateChildPopupSeq[] = {
895 { HCBT_CREATEWND, hook },
896 { WM_NCCREATE, sent },
897 { WM_NCCALCSIZE, sent|wparam, 0 },
898 { WM_CREATE, sent },
899 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
901 { WM_MOVE, sent },
902 { 0 }
903};
904/* CreateWindow (for a popup window, not initially visible,
905 * which sets WS_VISIBLE in WM_CREATE handler)
906 */
907static const struct message WmCreateInvisiblePopupSeq[] = {
908 { HCBT_CREATEWND, hook },
909 { WM_NCCREATE, sent },
910 { WM_NCCALCSIZE, sent|wparam, 0 },
911 { WM_CREATE, sent },
912 { WM_STYLECHANGING, sent },
913 { WM_STYLECHANGED, sent },
914 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
916 { WM_MOVE, sent },
917 { 0 }
918};
919/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
920 * for a popup window with WS_VISIBLE style set
921 */
922static const struct message WmShowVisiblePopupSeq_2[] = {
924 { 0 }
925};
926/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
927 * for a popup window with WS_VISIBLE style set
928 */
929static const struct message WmShowVisiblePopupSeq_3[] = {
931 { HCBT_ACTIVATE, hook },
932 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
935 { WM_NCACTIVATE, sent },
936 { WM_ACTIVATE, sent|wparam, 1 },
937 { HCBT_SETFOCUS, hook },
942 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
946 { 0 }
947};
948/* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
949 */
950static const struct message WmShowPopupExtremeLocationSeq[] = {
951 { HCBT_CREATEWND, hook },
952 { WM_NCCREATE, sent },
953 { WM_NCCALCSIZE, sent|wparam, 0 },
954 { WM_CREATE, sent },
955 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
957 { WM_MOVE, sent },
958 { WM_SHOWWINDOW, sent|wparam, 1 },
960 { HCBT_ACTIVATE, hook },
963 { WM_ACTIVATEAPP, sent },
964 { WM_NCACTIVATE, sent },
965 { WM_ACTIVATE, sent },
969 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
970 { HCBT_SETFOCUS, hook },
972 { WM_NCPAINT, sent|wparam, 1 },
973 { WM_ERASEBKGND, sent },
975 /* occasionally received on test machines */
978 { 0 }
979};
980/* CreateWindow (for a popup window with WS_VISIBLE style set)
981 */
982static const struct message WmShowPopupFirstDrawSeq_1[] = {
983 { HCBT_CREATEWND, hook },
984 { WM_NCCREATE, sent },
985 { WM_NCCALCSIZE, sent|wparam, 0 },
986 { WM_CREATE, sent },
987 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
989 { WM_MOVE, sent },
990 { WM_SHOWWINDOW, sent|wparam, 1 },
992 { HCBT_ACTIVATE, hook },
995 { WM_ACTIVATEAPP, sent },
996 { WM_NCACTIVATE, sent },
997 { WM_ACTIVATE, sent },
1001 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1002 { HCBT_SETFOCUS, hook },
1004 { WM_NCPAINT, sent|wparam, 1 },
1005 { WM_ERASEBKGND, sent },
1007 { WM_PAINT, sent },
1008 /* occasionally received on test machines */
1011 { 0 }
1012};
1013/* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1014 */
1015static const struct message WmShowPopupFirstDrawSeq_2[] = {
1016 { HCBT_CREATEWND, hook },
1017 { WM_NCCREATE, sent },
1018 { WM_NCCALCSIZE, sent|wparam, 0 },
1019 { WM_CREATE, sent },
1020 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1022 { WM_MOVE, sent },
1027 { HCBT_ACTIVATE, hook },
1033 { WM_ACTIVATEAPP, sent },
1034 { WM_NCACTIVATE, sent },
1035 { WM_ACTIVATE, sent },
1039 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1040 { HCBT_SETFOCUS, hook },
1042 { WM_NCPAINT, sent|wparam, 1 },
1043 { WM_ERASEBKGND, sent },
1045 { WM_MOVE, sent|defwinproc },
1046 { WM_SIZE, sent|defwinproc, 0 },
1047 { WM_PAINT, sent},
1048 /* occasionally received on test machines */
1051 { 0 }
1052};
1053static const struct message WmFirstDrawSetWindowPosSeq1[] = {
1054 { HCBT_CREATEWND, hook },
1055 { WM_NCCREATE, sent },
1056 { WM_NCCALCSIZE, sent|wparam, 0 },
1057 { WM_CREATE, sent },
1058 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1060 { WM_MOVE, sent },
1062 { HCBT_ACTIVATE, hook },
1065 { WM_ACTIVATEAPP, sent },
1066 { WM_NCACTIVATE, sent },
1067 { WM_ACTIVATE, sent },
1071 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1072 { HCBT_SETFOCUS, hook },
1074 { WM_NCPAINT, sent|wparam, 1 },
1075 { WM_ERASEBKGND, sent },
1077 { WM_MOVE, sent|defwinproc },
1078 { 0 }
1079};
1080static const struct message WmFirstDrawSetWindowPosSeq2[] = {
1081 { HCBT_CREATEWND, hook },
1082 { WM_NCCREATE, sent },
1083 { WM_NCCALCSIZE, sent|wparam, 0 },
1084 { WM_CREATE, sent },
1085 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1087 { WM_MOVE, sent },
1089 { HCBT_ACTIVATE, hook },
1092 { WM_ACTIVATEAPP, sent },
1093 { WM_NCACTIVATE, sent },
1094 { WM_ACTIVATE, sent },
1098 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1099 { HCBT_SETFOCUS, hook },
1102 { WM_MOVE, sent|defwinproc },
1103 { 0 }
1104};
1105static const struct message WmFirstDrawSetWindowPosSeq3[] = {
1106 { HCBT_CREATEWND, hook },
1107 { WM_NCCREATE, sent },
1108 { WM_NCCALCSIZE, sent|wparam, 0 },
1109 { WM_CREATE, sent },
1110 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1112 { WM_MOVE, sent },
1114 /* Probably shouldn't happen, but not part of this test */
1121 { 0 }
1122};
1123static const struct message WmFirstDrawSetWindowPosSeq4[] = {
1124 { HCBT_CREATEWND, hook },
1125 { WM_NCCREATE, sent },
1126 { WM_NCCALCSIZE, sent|wparam, 0 },
1127 { WM_CREATE, sent },
1128 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1130 { WM_MOVE, sent },
1132 { HCBT_ACTIVATE, hook },
1135 { WM_ACTIVATEAPP, sent },
1136 { WM_NCACTIVATE, sent },
1137 { WM_ACTIVATE, sent },
1141 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1142 { HCBT_SETFOCUS, hook },
1144 { WM_NCPAINT, sent|wparam, 1 },
1145 { WM_ERASEBKGND, sent },
1147 { 0 }
1148};
1149static const struct message WmFirstDrawSetWindowPosSeq5[] = {
1150 { HCBT_CREATEWND, hook },
1151 { WM_NCCREATE, sent },
1152 { WM_NCCALCSIZE, sent|wparam, 0 },
1153 { WM_CREATE, sent },
1154 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1156 { WM_MOVE, sent },
1158 { HCBT_ACTIVATE, hook },
1161 { WM_ACTIVATEAPP, sent },
1162 { WM_NCACTIVATE, sent },
1163 { WM_ACTIVATE, sent },
1167 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1168 { HCBT_SETFOCUS, hook },
1171 { 0 }
1172};
1173static const struct message WmFirstDrawChildSeq1[] = {
1174 { 0 }
1175};
1176static const struct message WmFirstDrawChildSeq2[] = {
1177 { WM_NCPAINT, sent|wparam, 1 },
1178 { WM_ERASEBKGND, sent },
1179 /* occasionally received on test machines */
1182 { 0 }
1183};
1184/* CreateWindow (for child window, not initially visible) */
1185static const struct message WmCreateChildSeq[] = {
1186 { HCBT_CREATEWND, hook },
1187 { WM_NCCREATE, sent },
1188 /* child is inserted into parent's child list after WM_NCCREATE returns */
1189 { WM_NCCALCSIZE, sent|wparam, 0 },
1190 { WM_CREATE, sent },
1191 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1193 { WM_MOVE, sent },
1195 { 0 }
1196};
1197/* CreateWindow (for maximized child window, not initially visible) */
1198static const struct message WmCreateMaximizedChildSeq[] = {
1199 { HCBT_CREATEWND, hook },
1200 { WM_NCCREATE, sent },
1201 { WM_NCCALCSIZE, sent|wparam, 0 },
1202 { WM_CREATE, sent },
1203 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1205 { WM_MOVE, sent },
1209 { WM_NCCALCSIZE, sent|wparam, 1 },
1212 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1214 { 0 }
1215};
1216/* CreateWindow (for a child window, initially visible) */
1217static const struct message WmCreateVisibleChildSeq[] = {
1218 { HCBT_CREATEWND, hook },
1219 { WM_NCCREATE, sent },
1220 /* child is inserted into parent's child list after WM_NCCREATE returns */
1221 { WM_NCCALCSIZE, sent|wparam, 0 },
1222 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1223 { WM_CREATE, sent },
1224 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1226 { WM_MOVE, sent },
1228 { WM_SHOWWINDOW, sent|wparam, 1 },
1230 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1233 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */
1234 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1235 { 0 }
1236};
1237/* ShowWindow(SW_SHOW) for a not visible child window */
1238static const struct message WmShowChildSeq[] = {
1239 { WM_SHOWWINDOW, sent|wparam, 1 },
1241 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1244 { 0 }
1245};
1246/* ShowWindow(SW_HIDE) for a visible child window */
1247static const struct message WmHideChildSeq[] = {
1248 { WM_SHOWWINDOW, sent|wparam, 0 },
1250 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1253 { 0 }
1254};
1255/* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1256static const struct message WmHideChildSeq2[] = {
1257 { WM_SHOWWINDOW, sent|wparam, 0 },
1259 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1262 { 0 }
1263};
1264/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1265 * for a not visible child window
1266 */
1267static const struct message WmShowChildSeq_2[] = {
1269 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1272 { 0 }
1273};
1274/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1275 * for a not visible child window
1276 */
1277static const struct message WmShowChildSeq_3[] = {
1279 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1281 { 0 }
1282};
1283/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1284 * for a visible child window with a caption
1285 */
1286static const struct message WmShowChildSeq_4[] = {
1289 { 0 }
1290};
1291/* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1295 { WM_NCCALCSIZE, sent|wparam, 1 },
1296 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1299 { WM_MOVE, sent|defwinproc },
1301 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1302 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
1303 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1306 { 0 }
1307};
1308/* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1311 { 0 }
1312};
1313/* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1318 { WM_NCCALCSIZE, sent|wparam, 1 },
1319 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1323 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1324 { 0 }
1325};
1326/* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1329 { 0 }
1330};
1331/* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1335 { WM_NCCALCSIZE, sent|wparam, 1 },
1336 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1339 { WM_MOVE, sent|defwinproc },
1341 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1342 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
1343 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1346 { 0 }
1347};
1348/* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1351 { 0 }
1352};
1353/* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1357 { WM_NCCALCSIZE, sent|wparam, 1 },
1358 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1360 { WM_MOVE, sent|defwinproc },
1362 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1363 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
1364 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1367 { 0 }
1368};
1369/* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1372 { 0 }
1373};
1374/* ShowWindow(SW_SHOW) for child with invisible parent */
1376 { WM_SHOWWINDOW, sent|wparam, 1 },
1377 { 0 }
1378};
1379/* ShowWindow(SW_HIDE) for child with invisible parent */
1381 { WM_SHOWWINDOW, sent|wparam, 0 },
1382 { 0 }
1383};
1384/* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1387 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1389 { 0 }
1390};
1391/* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1394 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1396 { 0 }
1397};
1398/* DestroyWindow for a visible child window */
1399static const struct message WmDestroyChildSeq[] = {
1400 { HCBT_DESTROYWND, hook },
1401 { 0x0090, sent|optional },
1403 { WM_SHOWWINDOW, sent|wparam, 0 },
1405 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1408 { HCBT_SETFOCUS, hook }, /* set focus to a parent */
1409 { WM_KILLFOCUS, sent },
1412 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1413 { WM_SETFOCUS, sent|parent },
1414 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1415 { WM_DESTROY, sent },
1416 { WM_DESTROY, sent|optional }, /* some other (IME?) window */
1417 { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */
1418 { WM_NCDESTROY, sent },
1419 { 0 }
1420};
1421/* visible child window destroyed by thread exit */
1422static const struct message WmExitThreadSeq[] = {
1423 { WM_NCDESTROY, sent }, /* actually in grandchild */
1424 { WM_PAINT, sent|parent },
1426 { 0 }
1427};
1428/* DestroyWindow for a visible child window with invisible parent */
1429static const struct message WmDestroyInvisibleChildSeq[] = {
1430 { HCBT_DESTROYWND, hook },
1431 { 0x0090, sent|optional },
1433 { WM_SHOWWINDOW, sent|wparam, 0 },
1434 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1435 { WM_DESTROY, sent },
1436 { WM_NCDESTROY, sent },
1437 { 0 }
1438};
1439/* Resizing child window with MoveWindow (32) */
1442 { WM_NCCALCSIZE, sent|wparam, 1 },
1446 { WM_MOVE, sent|defwinproc },
1448 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1449 { 0 }
1450};
1451/* Creation of a custom dialog (32) */
1452static const struct message WmCreateCustomDialogSeq[] = {
1453 { HCBT_CREATEWND, hook },
1455 { WM_NCCREATE, sent },
1456 { WM_NCCALCSIZE, sent|wparam, 0 },
1457 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1458 { WM_CREATE, sent },
1459 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1460 { WM_NOTIFYFORMAT, sent|optional },
1461 { WM_QUERYUISTATE, sent|optional },
1466 { WM_SHOWWINDOW, sent|wparam, 1 },
1468 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1469 { HCBT_ACTIVATE, hook },
1470 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1471
1472
1474
1476
1477 { WM_NCACTIVATE, sent },
1481 { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
1482 { WM_ACTIVATE, sent|wparam, 1 },
1488 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1489 { WM_SETFOCUS, sent },
1491 { WM_NCPAINT, sent|wparam, 1 },
1494 { WM_ERASEBKGND, sent },
1505 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1507 { WM_MOVE, sent },
1508 { 0 }
1509};
1510/* Calling EndDialog for a custom dialog (32) */
1511static const struct message WmEndCustomDialogSeq[] = {
1513 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1516 { HCBT_ACTIVATE, hook },
1517 { WM_NCACTIVATE, sent|wparam, 0 },
1520 { WM_ACTIVATE, sent|wparam, 0 },
1521 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1526 { HCBT_SETFOCUS, hook },
1527 { WM_KILLFOCUS, sent },
1531 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1533 { 0 }
1534};
1535/* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1536static const struct message WmShowCustomDialogSeq[] = {
1537 { WM_SHOWWINDOW, sent|wparam, 1 },
1539 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1540 { HCBT_ACTIVATE, hook },
1541 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1542
1544
1547 { WM_NCACTIVATE, sent },
1548 { WM_ACTIVATE, sent|wparam, 1 },
1550
1555 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1556 { WM_SETFOCUS, sent },
1558 { WM_NCPAINT, sent|wparam, 1 },
1559 { WM_ERASEBKGND, sent },
1562 { 0 }
1563};
1564/* Creation and destruction of a modal dialog (32) */
1565static const struct message WmModalDialogSeq[] = {
1567 { HCBT_SETFOCUS, hook },
1568 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1571 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1572 { WM_ENABLE, sent|parent|wparam, 0 },
1573 { HCBT_CREATEWND, hook },
1574 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1575 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1576 { WM_SETFONT, sent },
1577 { WM_INITDIALOG, sent },
1578 { WM_CHANGEUISTATE, sent|optional },
1579 { WM_UPDATEUISTATE, sent|optional },
1580 { WM_SHOWWINDOW, sent },
1581 { HCBT_ACTIVATE, hook },
1582 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1585 { WM_NCACTIVATE, sent },
1587 { WM_ACTIVATE, sent|wparam, 1 },
1589 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1601 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1602 { WM_PAINT, sent|optional },
1625 { WM_TIMER, sent },
1626 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1627 { WM_ENABLE, sent|parent|wparam, 1 },
1629 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1632 { HCBT_ACTIVATE, hook },
1633 { WM_NCACTIVATE, sent|wparam, 0 },
1635 { WM_ACTIVATE, sent|wparam, 0 },
1636 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
1639 { HCBT_SETFOCUS, hook },
1641 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1643 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 },
1644 { HCBT_DESTROYWND, hook },
1645 { 0x0090, sent|optional },
1646 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1647 { WM_DESTROY, sent },
1648 { WM_NCDESTROY, sent },
1649 { 0 }
1650};
1651static const struct message WmModalDialogSeq_2[] = {
1652 { WM_CANCELMODE, sent },
1653 { HCBT_SETFOCUS, hook },
1654 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
1655 { WM_KILLFOCUS, sent },
1657 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1658 { WM_ENABLE, sent|wparam, 0 },
1659 { HCBT_CREATEWND, hook },
1660 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1661 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
1662 { WM_SETFONT, sent },
1663 { WM_INITDIALOG, sent },
1664 { WM_CHANGEUISTATE, sent|optional },
1665 { WM_UPDATEUISTATE, sent|optional },
1666 { WM_ENABLE, sent|wparam, 1 },
1668 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
1669 { WM_CHANGEUISTATE, sent|optional },
1670 { WM_UPDATEUISTATE, sent|optional },
1671 { HCBT_DESTROYWND, hook },
1672 { 0x0090, sent|optional },
1673 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
1674 { WM_DESTROY, sent },
1675 { WM_NCDESTROY, sent },
1676 { 0 }
1677};
1678/* SetMenu for NonVisible windows with size change*/
1681 { WM_NCCALCSIZE, sent|wparam, 1 },
1682 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1684 { WM_MOVE, sent|defwinproc },
1686 { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */
1687 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1688 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1691 { 0 }
1692};
1693/* SetMenu for NonVisible windows with no size change */
1696 { WM_NCCALCSIZE, sent|wparam, 1 },
1698 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1699 { 0 }
1700};
1701/* SetMenu for Visible windows with size change */
1704 { WM_NCCALCSIZE, sent|wparam, 1 },
1705 { 0x0093, sent|defwinproc|optional },
1706 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1707 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1708 { 0x0093, sent|defwinproc|optional },
1709 { 0x0093, sent|defwinproc|optional },
1710 { 0x0091, sent|defwinproc|optional },
1711 { 0x0092, sent|defwinproc|optional },
1716 { WM_MOVE, sent|defwinproc },
1718 { 0x0093, sent|optional },
1720 { 0x0093, sent|defwinproc|optional },
1721 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1722 { 0x0093, sent|defwinproc|optional },
1723 { 0x0093, sent|defwinproc|optional },
1724 { 0x0091, sent|defwinproc|optional },
1725 { 0x0092, sent|defwinproc|optional },
1727 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1728 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
1729 { 0 }
1730};
1731/* SetMenu for Visible windows with no size change */
1734 { WM_NCCALCSIZE, sent|wparam, 1 },
1735 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1740 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1741 { 0 }
1742};
1743/* DrawMenuBar for a visible window */
1744static const struct message WmDrawMenuBarSeq[] =
1745{
1747 { WM_NCCALCSIZE, sent|wparam, 1 },
1748 { 0x0093, sent|defwinproc|optional },
1749 { WM_NCPAINT, sent|optional }, /* wparam != 1 */
1750 { 0x0093, sent|defwinproc|optional },
1751 { 0x0093, sent|defwinproc|optional },
1752 { 0x0091, sent|defwinproc|optional },
1753 { 0x0092, sent|defwinproc|optional },
1757 { 0x0093, sent|optional },
1758 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1759 { 0 }
1760};
1761
1762static const struct message WmSetRedrawFalseSeq[] =
1763{
1764 { WM_SETREDRAW, sent|wparam, 0 },
1765 { 0 }
1766};
1767
1768static const struct message WmSetRedrawTrueSeq[] =
1769{
1770 { WM_SETREDRAW, sent|wparam, 1 },
1771 { 0 }
1772};
1773
1774static const struct message WmEnableWindowSeq_1[] =
1775{
1776 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 },
1777 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1780 { WM_ENABLE, sent|wparam|lparam, FALSE, 0 },
1781 { 0 }
1782};
1783
1784static const struct message WmEnableWindowSeq_2[] =
1785{
1786 { WM_CANCELMODE, sent|wparam|lparam, 0, 0 },
1787 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1788 { 0 }
1789};
1790
1791static const struct message WmEnableWindowSeq_3[] =
1792{
1793 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1794 { WM_ENABLE, sent|wparam|lparam, TRUE, 0 },
1795 { 0 }
1796};
1797
1798static const struct message WmEnableWindowSeq_4[] =
1799{
1800 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
1801 { 0 }
1802};
1803
1804static const struct message WmGetScrollRangeSeq[] =
1805{
1806 { SBM_GETRANGE, sent },
1807 { 0 }
1808};
1809static const struct message WmGetScrollInfoSeq[] =
1810{
1811 { SBM_GETSCROLLINFO, sent },
1812 { 0 }
1813};
1814static const struct message WmSetScrollRangeSeq[] =
1815{
1816 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1817 sends SBM_SETSCROLLINFO.
1818 */
1819 { SBM_SETSCROLLINFO, sent },
1820 { 0 }
1821};
1822/* SetScrollRange for a window without a non-client area */
1824{
1825 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 },
1826 { 0 }
1827};
1829{
1830 { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 },
1831 { 0 }
1832};
1833static const struct message WmSetScrollRangeHVSeq[] =
1834{
1836 { WM_NCCALCSIZE, sent|wparam, 1 },
1840 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1841 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1842 { 0 }
1843};
1844/* SetScrollRange for a window with a non-client area */
1845static const struct message WmSetScrollRangeHV_NC_Seq[] =
1846{
1848 { WM_NCCALCSIZE, sent|wparam, 1 },
1849 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
1851 { WM_STYLECHANGING, sent|defwinproc|optional },
1852 { WM_STYLECHANGED, sent|defwinproc|optional },
1853 { WM_STYLECHANGING, sent|defwinproc|optional },
1854 { WM_STYLECHANGED, sent|defwinproc|optional },
1855 { WM_STYLECHANGING, sent|defwinproc|optional },
1856 { WM_STYLECHANGED, sent|defwinproc|optional },
1857 { WM_STYLECHANGING, sent|defwinproc|optional },
1858 { WM_STYLECHANGED, sent|defwinproc|optional },
1862 { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
1865 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1866 { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1871 { 0 }
1872};
1873/* test if we receive the right sequence of messages */
1874/* after calling ShowWindow( SW_SHOWNA) */
1875static const struct message WmSHOWNAChildInvisParInvis[] = {
1876 { WM_SHOWWINDOW, sent|wparam, 1 },
1877 { 0 }
1878};
1879static const struct message WmSHOWNAChildVisParInvis[] = {
1880 { WM_SHOWWINDOW, sent|wparam, 1 },
1881 { 0 }
1882};
1883static const struct message WmSHOWNAChildVisParVis[] = {
1884 { WM_SHOWWINDOW, sent|wparam, 1 },
1886 { 0 }
1887};
1888static const struct message WmSHOWNAChildInvisParVis[] = {
1889 { WM_SHOWWINDOW, sent|wparam, 1 },
1891 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1894 { 0 }
1895};
1896static const struct message WmSHOWNATopVisible[] = {
1897 { WM_SHOWWINDOW, sent|wparam, 1 },
1903 { 0 }
1904};
1905static const struct message WmSHOWNATopInvisible[] = {
1906 { WM_NOTIFYFORMAT, sent|optional },
1907 { WM_QUERYUISTATE, sent|optional },
1912 { WM_SHOWWINDOW, sent|wparam, 1 },
1914 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
1922 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
1924 { WM_MOVE, sent },
1925 { 0 }
1926};
1927
1928static const struct message WmTrackPopupMenu[] = {
1929 { HCBT_CREATEWND, hook },
1931 { WM_INITMENU, sent|lparam, 0, 0 },
1932 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
1933 { 0x0093, sent|optional },
1934 { 0x0094, sent|optional },
1935 { 0x0094, sent|optional },
1936 { WM_ENTERIDLE, sent|wparam, 2 },
1938 { HCBT_DESTROYWND, hook },
1939 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
1940 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
1941 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
1942 { 0 }
1943};
1944
1945static const struct message WmTrackPopupMenuEsc[] = {
1946 { 0 }
1947};
1948
1949static const struct message WmTrackPopupMenuCapture[] = {
1950 { HCBT_CREATEWND, hook },
1953 { WM_INITMENU, sent|lparam, 0, 0 },
1954 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
1955 { 0x0093, sent|optional },
1956 { 0x0094, sent|optional },
1957 { 0x0094, sent|optional },
1958 { WM_ENTERIDLE, sent|wparam, 2 },
1960 { HCBT_DESTROYWND, hook },
1961 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
1962 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
1963 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
1964 { 0 }
1965};
1966
1967static const struct message WmTrackPopupMenuEmpty[] = {
1968 { HCBT_CREATEWND, hook },
1970 { WM_INITMENU, sent|lparam, 0, 0 },
1971 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
1972 { 0x0093, sent|optional },
1973 { 0x0094, sent|optional },
1974 { 0x0094, sent|optional },
1976 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
1977 { HCBT_DESTROYWND, hook },
1978 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
1979 { 0 }
1980};
1981
1982static const struct message WmTrackPopupMenuAbort[] = {
1983 { HCBT_CREATEWND, hook },
1985 { WM_INITMENU, sent|lparam, 0, 0 },
1986 { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
1987 { 0x0093, sent|optional },
1988 { 0x0094, sent|optional },
1989 { 0x0094, sent|optional },
1991 { HCBT_DESTROYWND, hook },
1992 { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
1993 { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
1994 { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
1995 { 0 }
1996};
1997
2003
2004/* user32 functions */
2005static HWND (WINAPI *pGetAncestor)(HWND,UINT);
2006static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);
2007static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG);
2008static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);
2010static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*);
2011static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK);
2012static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
2013static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
2014static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
2015static UINT_PTR (WINAPI *pSetSystemTimer)(HWND, UINT_PTR, UINT, TIMERPROC);
2016static UINT_PTR (WINAPI *pKillSystemTimer)(HWND, UINT_PTR);
2017static UINT_PTR (WINAPI *pSetCoalescableTimer)(HWND, UINT_PTR, UINT, TIMERPROC, ULONG);
2018/* kernel32 functions */
2019static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
2020
2021static void init_procs(void)
2022{
2023 HMODULE user32 = GetModuleHandleA("user32.dll");
2024 HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
2025
2026#define GET_PROC(dll, func) \
2027 p ## func = (void*)GetProcAddress(dll, #func); \
2028 if(!p ## func) { \
2029 trace("GetProcAddress(%s) failed\n", #func); \
2030 }
2031
2032 GET_PROC(user32, GetAncestor)
2033 GET_PROC(user32, GetMenuInfo)
2034 GET_PROC(user32, NotifyWinEvent)
2035 GET_PROC(user32, SetMenuInfo)
2036 GET_PROC(user32, SetWinEventHook)
2037 GET_PROC(user32, TrackMouseEvent)
2038 GET_PROC(user32, UnhookWinEvent)
2039 GET_PROC(user32, GetMonitorInfoA)
2040 GET_PROC(user32, MonitorFromPoint)
2042 GET_PROC(user32, SetSystemTimer)
2043 GET_PROC(user32, KillSystemTimer)
2044 GET_PROC(user32, SetCoalescableTimer)
2045
2046 GET_PROC(kernel32, GetCPInfoExA)
2047
2048#undef GET_PROC
2049}
2050
2051static const char *get_winpos_flags(UINT flags)
2052{
2053 static char buffer[300];
2054
2055 buffer[0] = 0;
2056#define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2066 DUMP( SWP_NOZORDER );
2067 DUMP( SWP_NOREDRAW );
2068 DUMP( SWP_NOSIZE );
2069 DUMP( SWP_NOMOVE );
2072 if (flags) sprintf(buffer + strlen(buffer),"|0x%04x", flags);
2073 return buffer + 1;
2074#undef DUMP
2075}
2076
2078{
2079 /* these are always ignored */
2080 return (message >= 0xc000 ||
2081 message == WM_GETICON ||
2082 message == WM_GETOBJECT ||
2084 message == WM_DISPLAYCHANGE ||
2087}
2088
2089static unsigned hash_Ly_W(const WCHAR *str)
2090{
2091 unsigned hash = 0;
2092
2093 for (; *str; str++)
2094 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
2095
2096 return hash;
2097}
2098
2099static unsigned hash_Ly(const char *str)
2100{
2101 unsigned hash = 0;
2102
2103 for (; *str; str++)
2104 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
2105
2106 return hash;
2107}
2108
2109#define add_message(msg) add_message_(__LINE__,msg);
2110static void add_message_(int line, const struct recvd_message *msg)
2111{
2112 struct recvd_message *seq;
2113
2115 if (!sequence)
2116 {
2117 sequence_size = 10;
2119 }
2121 {
2122 sequence_size *= 2;
2124 }
2126
2127 seq = &sequence[sequence_cnt++];
2128 seq->hwnd = msg->hwnd;
2129 seq->message = msg->message;
2130 seq->flags = msg->flags;
2131 seq->wParam = msg->wParam;
2132 seq->lParam = msg->lParam;
2133 seq->line = line;
2134 seq->descr = msg->descr;
2135 seq->output[0] = 0;
2137
2138 if (msg->descr)
2139 {
2140 if (msg->flags & hook)
2141 {
2142 static const char * const CBT_code_name[10] =
2143 {
2144 "HCBT_MOVESIZE",
2145 "HCBT_MINMAX",
2146 "HCBT_QS",
2147 "HCBT_CREATEWND",
2148 "HCBT_DESTROYWND",
2149 "HCBT_ACTIVATE",
2150 "HCBT_CLICKSKIPPED",
2151 "HCBT_KEYSKIPPED",
2152 "HCBT_SYSCOMMAND",
2153 "HCBT_SETFOCUS"
2154 };
2155 const char *code_name = (msg->message <= HCBT_SETFOCUS) ? CBT_code_name[msg->message] : "Unknown";
2156
2157 sprintf( seq->output, "%s: hook %d (%s) wp %08lx lp %08lx",
2158 msg->descr, msg->message, code_name, msg->wParam, msg->lParam );
2159 }
2160 else if (msg->flags & winevent_hook)
2161 {
2162 sprintf( seq->output, "%s: winevent %p %08x %08lx %08lx",
2163 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam );
2164 }
2165 else
2166 {
2167 switch (msg->message)
2168 {
2171 {
2172 WINDOWPOS *winpos = (WINDOWPOS *)msg->lParam;
2173
2174 sprintf( seq->output, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s",
2175 msg->descr, msg->hwnd,
2176 (msg->message == WM_WINDOWPOSCHANGING) ? "CHANGING" : "CHANGED",
2177 msg->wParam, msg->lParam, winpos->hwndInsertAfter,
2178 winpos->x, winpos->y, winpos->cx, winpos->cy,
2179 get_winpos_flags(winpos->flags) );
2180
2181 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2182 * in the high word for internal purposes
2183 */
2184 seq->wParam = winpos->flags & 0xffff;
2185 /* We are not interested in the flags that don't match under XP and Win9x */
2186 seq->wParam &= ~SWP_NOZORDER;
2187 break;
2188 }
2189
2190 case WM_DRAWITEM:
2191 {
2193 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)msg->lParam;
2194
2195 sprintf( seq->output, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2196 msg->descr, msg->hwnd, dis->CtlType, dis->CtlID,
2197 dis->itemID, dis->itemAction, dis->itemState);
2198
2199 di.u.lp = 0;
2200 di.u.item.type = dis->CtlType;
2201 di.u.item.ctl_id = dis->CtlID;
2202 if (dis->CtlType == ODT_LISTBOX ||
2203 dis->CtlType == ODT_COMBOBOX ||
2204 dis->CtlType == ODT_MENU)
2205 di.u.item.item_id = dis->itemID;
2206 di.u.item.action = dis->itemAction;
2207 di.u.item.state = dis->itemState;
2208
2209 seq->lParam = di.u.lp;
2210 break;
2211 }
2212
2213 case WM_MEASUREITEM:
2214 {
2216 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam;
2217 BOOL is_unicode_data = TRUE;
2218
2219 sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx",
2220 msg->descr, msg->hwnd, mis->CtlType, mis->CtlID,
2221 mis->itemID, mis->itemData);
2222
2223 if (mis->CtlType == ODT_LISTBOX)
2224 {
2225 HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID);
2226 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
2227 }
2228
2229 mi.u.wp = 0;
2230 mi.u.item.CtlType = mis->CtlType;
2231 mi.u.item.CtlID = mis->CtlID;
2232 mi.u.item.itemID = mis->itemID;
2233 mi.u.item.wParam = msg->wParam;
2234 seq->wParam = mi.u.wp;
2235 if (is_unicode_data)
2236 seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0;
2237 else
2238 seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0;
2239 break;
2240 }
2241
2242 case WM_COMPAREITEM:
2243 {
2244 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam;
2245 HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID);
2246 BOOL is_unicode_data = TRUE;
2247
2248 ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam);
2249 ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem);
2250 ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1);
2251 ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
2252
2253 sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx",
2254 msg->descr, msg->hwnd, cis->CtlType, cis->CtlID,
2255 cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2);
2256
2257 if (cis->CtlType == ODT_LISTBOX)
2258 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
2259
2260 if (is_unicode_data)
2261 {
2262 seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0;
2263 seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0;
2264 }
2265 else
2266 {
2267 seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0;
2268 seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0;
2269 }
2270 break;
2271 }
2272
2273 default:
2274 if (msg->message >= 0xc000) return; /* ignore registered messages */
2275 sprintf( seq->output, "%s: %p %04x wp %08lx lp %08lx",
2276 msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam );
2277 }
2278 if (msg->flags & (sent|posted|parent|defwinproc|beginpaint))
2279 sprintf( seq->output + strlen(seq->output), " (flags %x)", msg->flags );
2280 }
2281 }
2282}
2283
2284/* try to make sure pending X events have been processed before continuing */
2285static void flush_events(void)
2286{
2287 MSG msg;
2288 int diff = 200;
2289 int min_timeout = 100;
2290 DWORD time = GetTickCount() + diff;
2291
2292 while (diff > 0)
2293 {
2294 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
2295 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
2296 diff = time - GetTickCount();
2297 }
2298}
2299
2300static void flush_sequence(void)
2301{
2304 sequence = 0;
2307}
2308
2309static void dump_sequence(const struct message *expected, const char *context, const char *file, int line)
2310{
2311 const struct recvd_message *actual = sequence;
2312 unsigned int count = 0;
2313
2314 trace_(file, line)("Failed sequence %s:\n", context );
2315 while (expected->message && actual->message)
2316 {
2317 if (actual->output[0])
2318 {
2319 if (expected->flags & hook)
2320 {
2321 trace_(file, line)( " %u: expected: hook %04x - actual: %s\n",
2322 count, expected->message, actual->output );
2323 }
2324 else if (expected->flags & winevent_hook)
2325 {
2326 trace_(file, line)( " %u: expected: winevent %04x - actual: %s\n",
2327 count, expected->message, actual->output );
2328 }
2329 else if (expected->flags & kbd_hook)
2330 {
2331 trace_(file, line)( " %u: expected: kbd %04x - actual: %s\n",
2332 count, expected->message, actual->output );
2333 }
2334 else
2335 {
2336 trace_(file, line)( " %u: expected: msg %04x - actual: %s\n",
2337 count, expected->message, actual->output );
2338 }
2339 }
2340
2341 if (expected->message == actual->message)
2342 {
2343 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) &&
2344 (expected->flags & optional))
2345 {
2346 /* don't match messages if their defwinproc status differs */
2347 expected++;
2348 }
2349 else
2350 {
2351 expected++;
2352 actual++;
2353 }
2354 }
2355 /* silently drop winevent messages if there is no support for them */
2356 else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))
2357 expected++;
2358 else
2359 {
2360 expected++;
2361 actual++;
2362 }
2363 count++;
2364 }
2365
2366 /* optional trailing messages */
2367 while (expected->message && ((expected->flags & optional) ||
2368 ((expected->flags & winevent_hook) && !hEvent_hook)))
2369 {
2370 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message );
2371 expected++;
2372 count++;
2373 }
2374
2375 if (expected->message)
2376 {
2377 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message );
2378 return;
2379 }
2380
2381 while (actual->message && actual->output[0])
2382 {
2383 trace_(file, line)( " %u: expected: nothing - actual: %s\n", count, actual->output );
2384 actual++;
2385 count++;
2386 }
2387}
2388
2389#define ok_sequence( exp, contx, todo) \
2390 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2391
2392
2393static void ok_sequence_(const struct message *expected_list, const char *context, BOOL todo,
2394 const char *file, int line)
2395{
2396 static const struct recvd_message end_of_sequence;
2397 const struct message *expected = expected_list;
2398 const struct recvd_message *actual;
2399 int failcount = 0, dump = 0;
2400 unsigned int count = 0;
2401
2402 add_message(&end_of_sequence);
2403
2404 actual = sequence;
2405
2406 while (expected->message && actual->message)
2407 {
2408 if (expected->message == actual->message &&
2409 !((expected->flags ^ actual->flags) & (hook|winevent_hook|kbd_hook)))
2410 {
2411 if (expected->flags & wparam)
2412 {
2413 if (((expected->wParam ^ actual->wParam) & ~expected->wp_mask) && todo)
2414 {
2415 todo_wine {
2416 failcount ++;
2417 if (strcmp(winetest_platform, "wine")) dump++;
2418 ok_( file, line) (FALSE,
2419 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2420 context, count, expected->message, expected->wParam, actual->wParam);
2421 }
2422 }
2423 else
2424 {
2425 ok_( file, line)( ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) == 0,
2426 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2427 context, count, expected->message, expected->wParam, actual->wParam);
2428 if ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) dump++;
2429 }
2430
2431 }
2432 if (expected->flags & lparam)
2433 {
2434 if (((expected->lParam ^ actual->lParam) & ~expected->lp_mask) && todo)
2435 {
2436 todo_wine {
2437 failcount ++;
2438 if (strcmp(winetest_platform, "wine")) dump++;
2439 ok_( file, line) (FALSE,
2440 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2441 context, count, expected->message, expected->lParam, actual->lParam);
2442 }
2443 }
2444 else
2445 {
2446 ok_( file, line)(((expected->lParam ^ actual->lParam) & ~expected->lp_mask) == 0,
2447 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2448 context, count, expected->message, expected->lParam, actual->lParam);
2449 if ((expected->lParam ^ actual->lParam) & ~expected->lp_mask) dump++;
2450 }
2451 }
2452 if ((expected->flags & optional) &&
2453 ((expected->flags ^ actual->flags) & (defwinproc|parent)))
2454 {
2455 /* don't match optional messages if their defwinproc or parent status differs */
2456 expected++;
2457 count++;
2458 continue;
2459 }
2460 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo)
2461 {
2462 todo_wine {
2463 failcount ++;
2464 if (strcmp(winetest_platform, "wine")) dump++;
2465 ok_( file, line) (FALSE,
2466 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2467 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
2468 }
2469 }
2470 else
2471 {
2472 ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
2473 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2474 context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
2475 if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++;
2476 }
2477
2478 ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
2479 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n",
2480 context, count, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
2481 if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++;
2482
2483 ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
2484 "%s: %u: the msg 0x%04x should have been %s\n",
2485 context, count, expected->message, (expected->flags & posted) ? "posted" : "sent");
2486 if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++;
2487
2488 ok_( file, line) ((expected->flags & parent) == (actual->flags & parent),
2489 "%s: %u: the msg 0x%04x was expected in %s\n",
2490 context, count, expected->message, (expected->flags & parent) ? "parent" : "child");
2491 if ((expected->flags & parent) != (actual->flags & parent)) dump++;
2492
2493 ok_( file, line) ((expected->flags & hook) == (actual->flags & hook),
2494 "%s: %u: the msg 0x%04x should have been sent by a hook\n",
2495 context, count, expected->message);
2496 if ((expected->flags & hook) != (actual->flags & hook)) dump++;
2497
2498 ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
2499 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n",
2500 context, count, expected->message);
2501 if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++;
2502
2503 ok_( file, line) ((expected->flags & kbd_hook) == (actual->flags & kbd_hook),
2504 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n",
2505 context, count, expected->message);
2506 if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++;
2507
2508 expected++;
2509 actual++;
2510 }
2511 /* silently drop hook messages if there is no support for them */
2512 else if ((expected->flags & optional) ||
2513 ((expected->flags & hook) && !hCBT_hook) ||
2514 ((expected->flags & winevent_hook) && !hEvent_hook) ||
2515 ((expected->flags & kbd_hook) && !hKBD_hook))
2516 expected++;
2517 else if (todo)
2518 {
2519 failcount++;
2520 todo_wine {
2521 if (strcmp(winetest_platform, "wine")) dump++;
2522 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2523 context, count, expected->message, actual->message);
2524 }
2525 goto done;
2526 }
2527 else
2528 {
2529 ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2530 context, count, expected->message, actual->message);
2531 dump++;
2532 expected++;
2533 actual++;
2534 }
2535 count++;
2536 }
2537
2538 /* skip all optional trailing messages */
2539 while (expected->message && ((expected->flags & optional) ||
2540 ((expected->flags & hook) && !hCBT_hook) ||
2541 ((expected->flags & winevent_hook) && !hEvent_hook)))
2542 expected++;
2543
2544 if (todo)
2545 {
2546 todo_wine {
2547 if (expected->message || actual->message) {
2548 failcount++;
2549 if (strcmp(winetest_platform, "wine")) dump++;
2550 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2551 context, count, expected->message, actual->message);
2552 }
2553 }
2554 }
2555 else
2556 {
2557 if (expected->message || actual->message)
2558 {
2559 dump++;
2560 ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2561 context, count, expected->message, actual->message);
2562 }
2563 }
2564 if( todo && !failcount) /* succeeded yet marked todo */
2565 todo_wine {
2566 if (!strcmp(winetest_platform, "wine")) dump++;
2567 ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
2568 }
2569
2570done:
2571 if (dump) dump_sequence(expected_list, context, file, line);
2573}
2574
2575#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
2576
2577/******************************** MDI test **********************************/
2578
2579/* CreateWindow for MDI frame window, initially visible */
2580static const struct message WmCreateMDIframeSeq[] = {
2581 { HCBT_CREATEWND, hook },
2583 { WM_NCCREATE, sent },
2584 { WM_NCCALCSIZE, sent|wparam, 0 },
2585 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
2586 { WM_CREATE, sent },
2587 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2588 { WM_NOTIFYFORMAT, sent|optional },
2589 { WM_QUERYUISTATE, sent|optional },
2594 { WM_SHOWWINDOW, sent|wparam, 1 },
2596 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2597 { HCBT_ACTIVATE, hook },
2598 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
2601 { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, /* Win9x doesn't send it */
2602 { WM_NCACTIVATE, sent },
2604 { WM_ACTIVATE, sent|wparam, 1 },
2606 { HCBT_SETFOCUS, hook },
2609 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2611 /* Win9x adds SWP_NOZORDER below */
2613 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
2614 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
2616 { WM_MOVE, sent },
2617 { 0 }
2618};
2619/* DestroyWindow for MDI frame window, initially visible */
2620static const struct message WmDestroyMDIframeSeq[] = {
2621 { HCBT_DESTROYWND, hook },
2622 { 0x0090, sent|optional },
2624 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2625 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
2627 { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */
2628 { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
2629 { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
2630 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
2631 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
2632 { WM_DESTROY, sent },
2633 { WM_NCDESTROY, sent },
2634 { 0 }
2635};
2636/* CreateWindow for MDI client window, initially visible */
2637static const struct message WmCreateMDIclientSeq[] = {
2638 { HCBT_CREATEWND, hook },
2639 { WM_NCCREATE, sent },
2640 { WM_NCCALCSIZE, sent|wparam, 0 },
2641 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
2642 { WM_CREATE, sent },
2643 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
2644 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2646 { WM_MOVE, sent },
2647 { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
2648 { WM_SHOWWINDOW, sent|wparam, 1 },
2650 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2652 { 0 }
2653};
2654/* ShowWindow(SW_SHOW) for MDI client window */
2655static const struct message WmShowMDIclientSeq[] = {
2656 { WM_SHOWWINDOW, sent|wparam, 1 },
2658 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2660 { 0 }
2661};
2662/* ShowWindow(SW_HIDE) for MDI client window */
2663static const struct message WmHideMDIclientSeq[] = {
2664 { WM_SHOWWINDOW, sent|wparam, 0 },
2666 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */
2667 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */
2669 { 0 }
2670};
2671/* DestroyWindow for MDI client window, initially visible */
2672static const struct message WmDestroyMDIclientSeq[] = {
2673 { HCBT_DESTROYWND, hook },
2674 { 0x0090, sent|optional },
2675 { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
2676 { WM_SHOWWINDOW, sent|wparam, 0 },
2678 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2680 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
2681 { WM_DESTROY, sent },
2682 { WM_NCDESTROY, sent },
2683 { 0 }
2684};
2685/* CreateWindow for MDI child window, initially visible */
2686static const struct message WmCreateMDIchildVisibleSeq[] = {
2687 { HCBT_CREATEWND, hook },
2688 { WM_NCCREATE, sent },
2689 { WM_NCCALCSIZE, sent|wparam, 0 },
2690 { WM_CREATE, sent },
2691 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2693 { WM_MOVE, sent },
2694 /* Win2k sends wparam set to
2695 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2696 * while Win9x doesn't bother to set child window id according to
2697 * CLIENTCREATESTRUCT.idFirstChild
2698 */
2699 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2700 { WM_SHOWWINDOW, sent|wparam, 1 },
2702 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2704 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
2708
2709 /* Win9x: message sequence terminates here. */
2710
2712 { HCBT_SETFOCUS, hook }, /* in MDI client */
2713 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2714 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
2715 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2716 { WM_SETFOCUS, sent }, /* in MDI client */
2717 { HCBT_SETFOCUS, hook },
2718 { WM_KILLFOCUS, sent }, /* in MDI client */
2719 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2721 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2724 { 0 }
2725};
2726/* WM_CHILDACTIVATE sent to disabled window */
2729 { 0 }
2730};
2731/* WM_CHILDACTIVATE sent to enabled window */
2732static const struct message WmChildActivateWindowSeq[] = {
2739 { HCBT_SETFOCUS, hook },
2741 { WM_SETFOCUS, sent },
2742 { HCBT_SETFOCUS, hook },
2743 { WM_KILLFOCUS, sent },
2746 { 0 }
2747};
2748/* CreateWindow for MDI child window with invisible parent */
2750 { HCBT_CREATEWND, hook },
2752 { WM_NCCREATE, sent },
2753 { WM_NCCALCSIZE, sent|wparam, 0 },
2754 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 },
2755 { WM_CREATE, sent },
2756 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2758 { WM_MOVE, sent },
2759 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2760 { WM_SHOWWINDOW, sent|wparam, 1 },
2761 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
2765
2766 /* Win9x: message sequence terminates here. */
2767
2769 { HCBT_SETFOCUS, hook }, /* in MDI client */
2770 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2771 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
2772 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2773 { WM_SETFOCUS, sent }, /* in MDI client */
2774 { HCBT_SETFOCUS, hook },
2775 { WM_KILLFOCUS, sent }, /* in MDI client */
2776 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2778 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2781 { 0 }
2782};
2783/* DestroyWindow for MDI child window, initially visible */
2784static const struct message WmDestroyMDIchildVisibleSeq[] = {
2785 { HCBT_DESTROYWND, hook },
2786 /* Win2k sends wparam set to
2787 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2788 * while Win9x doesn't bother to set child window id according to
2789 * CLIENTCREATESTRUCT.idFirstChild
2790 */
2791 { 0x0090, sent|optional },
2792 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
2793 { WM_SHOWWINDOW, sent|wparam, 0 },
2795 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
2798
2799 /* { WM_DESTROY, sent }
2800 * Win9x: message sequence terminates here.
2801 */
2802
2803 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
2804 { WM_KILLFOCUS, sent },
2806 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2807 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2808 { WM_SETFOCUS, sent }, /* in MDI client */
2809
2810 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
2811 { WM_KILLFOCUS, sent }, /* in MDI client */
2812 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2814 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2815 { WM_SETFOCUS, sent }, /* in MDI client */
2816
2817 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
2818
2819 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
2820 { WM_KILLFOCUS, sent },
2822 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2823 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2824 { WM_SETFOCUS, sent }, /* in MDI client */
2825
2826 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
2827 { WM_KILLFOCUS, sent }, /* in MDI client */
2828 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2830 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2831 { WM_SETFOCUS, sent }, /* in MDI client */
2832
2833 { WM_DESTROY, sent },
2834
2835 { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
2836 { WM_KILLFOCUS, sent },
2838 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2839 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2840 { WM_SETFOCUS, sent }, /* in MDI client */
2841
2842 { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
2843 { WM_KILLFOCUS, sent }, /* in MDI client */
2844 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2846 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2847 { WM_SETFOCUS, sent }, /* in MDI client */
2848
2849 { WM_NCDESTROY, sent },
2850 { 0 }
2851};
2852/* CreateWindow for MDI child window, initially invisible */
2853static const struct message WmCreateMDIchildInvisibleSeq[] = {
2854 { HCBT_CREATEWND, hook },
2855 { WM_NCCREATE, sent },
2856 { WM_NCCALCSIZE, sent|wparam, 0 },
2857 { WM_CREATE, sent },
2858 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2860 { WM_MOVE, sent },
2861 /* Win2k sends wparam set to
2862 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2863 * while Win9x doesn't bother to set child window id according to
2864 * CLIENTCREATESTRUCT.idFirstChild
2865 */
2866 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2867 { 0 }
2868};
2869/* DestroyWindow for MDI child window, initially invisible */
2871 { HCBT_DESTROYWND, hook },
2872 /* Win2k sends wparam set to
2873 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2874 * while Win9x doesn't bother to set child window id according to
2875 * CLIENTCREATESTRUCT.idFirstChild
2876 */
2877 { 0x0090, sent|optional },
2878 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
2879 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
2880 { WM_DESTROY, sent },
2881 { WM_NCDESTROY, sent },
2882 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
2883 { WM_PARENTNOTIFY, sent|wparam|optional, WM_DESTROY }, /* MDI client */
2884 { 0 }
2885};
2886/* CreateWindow for the 1st MDI child window, initially visible and maximized */
2888 { HCBT_CREATEWND, hook },
2889 { WM_NCCREATE, sent },
2890 { WM_NCCALCSIZE, sent|wparam, 0 },
2891 { WM_CREATE, sent },
2892 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2894 { WM_MOVE, sent },
2898 { WM_NCCALCSIZE, sent|wparam, 1 },
2901 /* in MDI frame */
2903 { WM_NCCALCSIZE, sent|wparam, 1 },
2905 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2906 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2907 /* Win2k sends wparam set to
2908 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2909 * while Win9x doesn't bother to set child window id according to
2910 * CLIENTCREATESTRUCT.idFirstChild
2911 */
2912 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2913 { WM_SHOWWINDOW, sent|wparam, 1 },
2915 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2917 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
2921
2922 /* Win9x: message sequence terminates here. */
2923
2925 { HCBT_SETFOCUS, hook|optional }, /* in MDI client */
2926 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
2927 { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */
2928 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2929 { WM_SETFOCUS, sent|optional }, /* in MDI client */
2931 { WM_KILLFOCUS, sent|optional }, /* in MDI client */
2932 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
2934 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2937 /* in MDI frame */
2939 { WM_NCCALCSIZE, sent|wparam, 1 },
2941 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2942 { 0 }
2943};
2944/* CreateWindow for the 2nd MDI child window, initially visible and maximized */
2946 /* restore the 1st MDI child */
2947 { WM_SETREDRAW, sent|wparam, 0 },
2950 { WM_NCCALCSIZE, sent|wparam, 1 },
2954 /* in MDI frame */
2956 { WM_NCCALCSIZE, sent|wparam, 1 },
2958 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2959 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2960 { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */
2961 /* create the 2nd MDI child */
2962 { HCBT_CREATEWND, hook },
2963 { WM_NCCREATE, sent },
2964 { WM_NCCALCSIZE, sent|wparam, 0 },
2965 { WM_CREATE, sent },
2966 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
2968 { WM_MOVE, sent },
2972 { WM_NCCALCSIZE, sent|wparam, 1 },
2973 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
2976 /* in MDI frame */
2978 { WM_NCCALCSIZE, sent|wparam, 1 },
2980 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
2981 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
2982 /* Win2k sends wparam set to
2983 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2984 * while Win9x doesn't bother to set child window id according to
2985 * CLIENTCREATESTRUCT.idFirstChild
2986 */
2987 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
2988 { WM_SHOWWINDOW, sent|wparam, 1 },
2990 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
2992 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
2995
2996 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
2997 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
2998
3000
3001 /* Win9x: message sequence terminates here. */
3002
3004 { HCBT_SETFOCUS, hook },
3005 { WM_KILLFOCUS, sent|defwinproc|optional }, /* in the 1st MDI child */
3006 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */
3007 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3008 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3009 { WM_SETFOCUS, sent }, /* in MDI client */
3010 { HCBT_SETFOCUS, hook },
3011 { WM_KILLFOCUS, sent }, /* in MDI client */
3012 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3014 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3016
3018 /* in MDI frame */
3020 { WM_NCCALCSIZE, sent|wparam, 1 },
3022 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3023 { 0 }
3024};
3025/* WM_MDICREATE MDI child window, initially visible and maximized */
3027 { WM_MDICREATE, sent },
3028 { HCBT_CREATEWND, hook },
3029 { WM_NCCREATE, sent },
3030 { WM_NCCALCSIZE, sent|wparam, 0 },
3031 { WM_CREATE, sent },
3032 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
3034 { WM_MOVE, sent },
3038 { WM_NCCALCSIZE, sent|wparam, 1 },
3041
3042 /* in MDI frame */
3044 { WM_NCCALCSIZE, sent|wparam, 1 },
3046 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3047 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3048
3049 /* Win2k sends wparam set to
3050 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3051 * while Win9x doesn't bother to set child window id according to
3052 * CLIENTCREATESTRUCT.idFirstChild
3053 */
3054 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3055 { WM_SHOWWINDOW, sent|wparam, 1 },
3057
3058 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3059
3061 { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
3063
3066
3067 /* Win9x: message sequence terminates here. */
3068
3070 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3071 { HCBT_SETFOCUS, hook }, /* in MDI client */
3072 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3074 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
3075 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3077 { WM_KILLFOCUS, sent }, /* in MDI client */
3078 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3080 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3082
3084
3085 /* in MDI child */
3087 { WM_NCCALCSIZE, sent|wparam, 1 },
3089 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
3090
3091 /* in MDI frame */
3093 { WM_NCCALCSIZE, sent|wparam, 1 },
3094 { 0x0093, sent|defwinproc|optional },
3095 { 0x0093, sent|defwinproc|optional },
3096 { 0x0093, sent|defwinproc|optional },
3098 { WM_MOVE, sent|defwinproc },
3100
3101 /* in MDI client */
3103 { WM_NCCALCSIZE, sent|wparam, 1 },
3106
3107 /* in MDI child */
3109 { WM_NCCALCSIZE, sent|wparam, 1 },
3110 { 0x0093, sent|optional },
3113
3114 { 0x0093, sent|optional },
3115 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3116 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
3117 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */
3118 { 0x0093, sent|defwinproc|optional },
3119 { 0x0093, sent|defwinproc|optional },
3120 { 0x0093, sent|defwinproc|optional },
3121 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3122 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
3123
3124 { 0 }
3125};
3126/* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3128 { HCBT_CREATEWND, hook },
3130 { WM_NCCREATE, sent },
3131 { WM_NCCALCSIZE, sent|wparam, 0 },
3132 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
3133 { WM_CREATE, sent },
3134 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 },
3137 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI frame */
3139 { WM_MOVE, sent },
3144 { WM_NCCALCSIZE, sent|wparam, 1 },
3146 { WM_MOVE, sent|defwinproc },
3148 /* in MDI frame */
3150 { WM_NCCALCSIZE, sent|wparam, 1 },
3152 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3153 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI child */
3154 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3155 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3156 /* Win2k sends wparam set to
3157 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3158 * while Win9x doesn't bother to set child window id according to
3159 * CLIENTCREATESTRUCT.idFirstChild
3160 */
3161 { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
3162 { 0 }
3163};
3164/* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3167 { HCBT_SYSCOMMAND, hook },
3169 { WM_MDIDESTROY, sent }, /* in MDI client */
3170
3171 /* bring the 1st MDI child to top */
3172 { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */
3174
3175 { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3176
3177 { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */
3178 { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */
3179 { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
3180
3181 /* maximize the 1st MDI child */
3189
3190 /* restore the 2nd MDI child */
3195
3196 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3197
3200
3201 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3202
3204 /* in MDI frame */
3206 { WM_NCCALCSIZE, sent|wparam, 1 },
3208 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3209 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3210
3211 /* bring the 1st MDI child to top */
3214 { HCBT_SETFOCUS, hook },
3217 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3218 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3219 { WM_SETFOCUS, sent }, /* in MDI client */
3220 { HCBT_SETFOCUS, hook },
3221 { WM_KILLFOCUS, sent }, /* in MDI client */
3222 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3224 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3228
3229 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3230 { WM_SHOWWINDOW, sent|wparam, 1 },
3232 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3235
3236 { HCBT_DESTROYWND, hook },
3237 /* Win2k sends wparam set to
3238 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3239 * while Win9x doesn't bother to set child window id according to
3240 * CLIENTCREATESTRUCT.idFirstChild
3241 */
3242 { 0x0090, sent|defwinproc|optional },
3243 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
3246 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3249
3250 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
3253 { 0 }
3254};
3255/* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3257 { WM_MDIDESTROY, sent }, /* in MDI client */
3258 { WM_SHOWWINDOW, sent|wparam, 0 },
3260 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3263
3264 { HCBT_SETFOCUS, hook },
3265 { WM_KILLFOCUS, sent },
3267 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3268 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3269 { WM_SETFOCUS, sent }, /* in MDI client */
3270 { HCBT_SETFOCUS, hook },
3271 { WM_KILLFOCUS, sent }, /* in MDI client */
3272 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3274 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3275 { WM_SETFOCUS, sent },
3276
3277 /* in MDI child */
3279 { WM_NCCALCSIZE, sent|wparam, 1 },
3281 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3282
3283 /* in MDI frame */
3285 { WM_NCCALCSIZE, sent|wparam, 1 },
3286 { 0x0093, sent|defwinproc|optional },
3287 { 0x0093, sent|defwinproc|optional },
3289 { WM_MOVE, sent|defwinproc },
3291
3292 /* in MDI client */
3294 { WM_NCCALCSIZE, sent|wparam, 1 },
3297
3298 /* in MDI child */
3300 { WM_NCCALCSIZE, sent|wparam, 1 },
3303
3304 /* in MDI child */
3308 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3309
3310 /* in MDI frame */
3313 { 0x0093, sent|defwinproc|optional },
3314 { 0x0093, sent|defwinproc|optional },
3315 { 0x0093, sent|defwinproc|optional },
3317 { WM_MOVE, sent|defwinproc },
3319
3320 /* in MDI client */
3322 { WM_NCCALCSIZE, sent|wparam, 1 },
3325
3326 /* in MDI child */
3331 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3332 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
3333
3334 { 0x0093, sent|defwinproc|optional },
3335 { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */
3336 { 0x0093, sent|defwinproc|optional },
3337 { 0x0093, sent|defwinproc|optional },
3338 { 0x0093, sent|defwinproc|optional },
3339 { 0x0093, sent|optional },
3340
3341 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3342 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3343 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
3344 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3345 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
3346
3347 /* in MDI frame */
3350 { 0x0093, sent|defwinproc|optional },
3351 { 0x0093, sent|defwinproc|optional },
3352 { 0x0093, sent|defwinproc|optional },
3354 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3355 { 0x0093, sent|optional },
3356
3357 { WM_NCACTIVATE, sent|wparam, 0 },
3358 { WM_MDIACTIVATE, sent },
3359
3362 { WM_NCCALCSIZE, sent|wparam, 1 },
3363
3364 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3365
3369
3370 /* in MDI child */
3374 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3375
3376 /* in MDI frame */
3378 { WM_NCCALCSIZE, sent|wparam, 1 },
3380 { WM_MOVE, sent|defwinproc },
3382
3383 /* in MDI client */
3385 { WM_NCCALCSIZE, sent|wparam, 1 },
3388 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3389 { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
3390 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
3391 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3392 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
3393
3394 { HCBT_SETFOCUS, hook },
3395 { WM_KILLFOCUS, sent },
3397 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3398 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3399 { WM_SETFOCUS, sent }, /* in MDI client */
3400
3401 { WM_MDIREFRESHMENU, sent }, /* in MDI client */
3402
3403 { HCBT_DESTROYWND, hook },
3404 /* Win2k sends wparam set to
3405 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3406 * while Win9x doesn't bother to set child window id according to
3407 * CLIENTCREATESTRUCT.idFirstChild
3408 */
3409 { 0x0090, sent|optional },
3410 { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
3411
3412 { WM_SHOWWINDOW, sent|wparam, 0 },
3414 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
3417
3418 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
3419 { WM_DESTROY, sent },
3420 { WM_NCDESTROY, sent },
3421 { 0 }
3422};
3423/* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3428 { WM_NCCALCSIZE, sent|wparam, 1 },
3429 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3431
3435 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3436 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3437 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3439 { WM_KILLFOCUS, sent|optional }, /* in MDI client */
3440 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3442 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3447 /* in MDI frame */
3449 { WM_NCCALCSIZE, sent|wparam, 1 },
3451 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3452 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3453 { 0 }
3454};
3455/* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3461 { WM_NCCALCSIZE, sent|wparam, 1 },
3462 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3464
3468 { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
3469 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3470 { WM_SETFOCUS, sent|optional }, /* in MDI client */
3472 { WM_KILLFOCUS, sent|optional }, /* in MDI client */
3473 { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
3475 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3479 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3481 { 0 }
3482};
3483/* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3485 { WM_MDIMAXIMIZE, sent }, /* in MDI client */
3490 { WM_NCCALCSIZE, sent|wparam, 1 },
3491 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP doesn't send it */
3494 { WM_MOVE, sent|defwinproc },
3496
3501 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3502 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */
3503 /* in MDI frame */
3505 { WM_NCCALCSIZE, sent|wparam, 1 },
3506 { 0x0093, sent|defwinproc|optional },
3507 { 0x0094, sent|defwinproc|optional },
3508 { 0x0094, sent|defwinproc|optional },
3509 { 0x0094, sent|defwinproc|optional },
3510 { 0x0094, sent|defwinproc|optional },
3511 { 0x0093, sent|defwinproc|optional },
3512 { 0x0093, sent|defwinproc|optional },
3513 { 0x0091, sent|defwinproc|optional },
3514 { 0x0092, sent|defwinproc|optional },
3515 { 0x0092, sent|defwinproc|optional },
3516 { 0x0092, sent|defwinproc|optional },
3517 { 0x0092, sent|defwinproc|optional },
3519 { WM_MOVE, sent|defwinproc },
3521 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame win2000 */
3522 /* in MDI client */
3524 { WM_NCCALCSIZE, sent|wparam, 1 },
3527 /* in MDI child */
3533 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child win2000 */
3535 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3536 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3537 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */
3538 /* in MDI frame */
3539 { 0x0093, sent|optional },
3541 { 0x0093, sent|defwinproc|optional },
3542 { 0x0093, sent|defwinproc|optional },
3543 { 0x0093, sent|defwinproc|optional },
3544 { 0x0091, sent|defwinproc|optional },
3545 { 0x0092, sent|defwinproc|optional },
3546 { 0x0092, sent|defwinproc|optional },
3547 { 0x0092, sent|defwinproc|optional },
3548 { 0x0092, sent|defwinproc|optional },
3549 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */
3550 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */
3551 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */
3552 { 0 }
3553};
3554/* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3555static const struct message WmMaximizeMDIchildVisibleSeq[] = {
3559 { WM_NCCALCSIZE, sent|wparam, 1 },
3563 /* in MDI frame */
3565 { WM_NCCALCSIZE, sent|wparam, 1 },
3567 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3568 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3569 { 0 }
3570};
3571/* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3572static const struct message WmRestoreMDIchildVisibleSeq[] = {
3575 { WM_NCCALCSIZE, sent|wparam, 1 },
3579 /* in MDI frame */
3581 { WM_NCCALCSIZE, sent|wparam, 1 },
3583 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3584 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3585 { 0 }
3586};
3587/* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3590 { WM_QUERYOPEN, sent|wparam|lparam, 0, 0 },
3592 { WM_NCCALCSIZE, sent|wparam, 1 },
3595 { WM_MOVE, sent|defwinproc },
3597 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3598 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3599 { HCBT_SETFOCUS, hook },
3602 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
3603 { WM_SETFOCUS, sent },
3604 { 0 }
3605};
3606/* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3607static const struct message WmMinimizeMDIchildVisibleSeq[] = {
3610 { WM_NCCALCSIZE, sent|wparam, 1 },
3612 { WM_MOVE, sent|defwinproc },
3615 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3616 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3617 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3618 { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, /* MDI client */
3619 { 0 }
3620};
3621/* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3625 { WM_NCCALCSIZE, sent|wparam, 1 },
3626 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
3630 /* in MDI frame */
3632 { WM_NCCALCSIZE, sent|wparam, 1 },
3634 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
3635 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
3636 { 0 }
3637};
3638
3641
3643{
3644 struct recvd_message msg;
3645
3646 /* do not log painting messages */
3647 if (message != WM_PAINT &&
3648 message != WM_NCPAINT &&
3649 message != WM_SYNCPAINT &&
3651 message != WM_NCHITTEST &&
3652 message != WM_GETTEXT &&
3655 {
3656 msg.hwnd = hwnd;
3657 msg.message = message;
3658 msg.flags = sent|wparam|lparam;
3659 msg.wParam = wParam;
3660 msg.lParam = lParam;
3661 msg.descr = "mdi client";
3662 add_message(&msg);
3663 }
3664
3666}
3667
3669{
3670 static LONG defwndproc_counter = 0;
3671 LRESULT ret;
3672 struct recvd_message msg;
3673
3674 /* do not log painting messages */
3675 if (message != WM_PAINT &&
3676 message != WM_NCPAINT &&
3677 message != WM_SYNCPAINT &&
3679 message != WM_NCHITTEST &&
3680 message != WM_GETTEXT &&
3682 {
3683 switch (message)
3684 {
3685 case WM_MDIACTIVATE:
3686 {
3687 HWND active, client = GetParent(hwnd);
3688
3689 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
3690
3691 if (hwnd == (HWND)lParam) /* if we are being activated */
3692 ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active);
3693 else
3694 ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active);
3695 break;
3696 }
3697 }
3698
3699 msg.hwnd = hwnd;
3700 msg.message = message;
3701 msg.flags = sent|wparam|lparam;
3702 if (defwndproc_counter) msg.flags |= defwinproc;
3703 msg.wParam = wParam;
3704 msg.lParam = lParam;
3705 msg.descr = "mdi child";
3706 add_message(&msg);
3707 }
3708
3709 defwndproc_counter++;
3711 defwndproc_counter--;
3712
3713 return ret;
3714}
3715
3717{
3718 static LONG defwndproc_counter = 0;
3719 LRESULT ret;
3720 struct recvd_message msg;
3721
3722 /* do not log painting messages */
3723 if (message != WM_PAINT &&
3724 message != WM_NCPAINT &&
3725 message != WM_SYNCPAINT &&
3727 message != WM_NCHITTEST &&
3728 message != WM_GETTEXT &&
3730 {
3731 msg.hwnd = hwnd;
3732 msg.message = message;
3733 msg.flags = sent|wparam|lparam;
3734 if (defwndproc_counter) msg.flags |= defwinproc;
3735 msg.wParam = wParam;
3736 msg.lParam = lParam;
3737 msg.descr = "mdi frame";
3738 add_message(&msg);
3739 }
3740
3741 defwndproc_counter++;
3743 defwndproc_counter--;
3744
3745 return ret;
3746}
3747
3749{
3750 WNDCLASSA cls;
3751
3752 cls.style = 0;
3754 cls.cbClsExtra = 0;
3755 cls.cbWndExtra = 0;
3756 cls.hInstance = GetModuleHandleA(0);
3757 cls.hIcon = 0;
3760 cls.lpszMenuName = NULL;
3761 cls.lpszClassName = "MDI_frame_class";
3762 if (!RegisterClassA(&cls)) return FALSE;
3763
3765 cls.lpszClassName = "MDI_child_class";
3766 if (!RegisterClassA(&cls)) return FALSE;
3767
3768 if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
3770 cls.hInstance = GetModuleHandleA(0);
3772 cls.lpszClassName = "MDI_client_class";
3773 if (!RegisterClassA(&cls)) assert(0);
3774
3775 return TRUE;
3776}
3777
3778static void test_mdi_messages(void)
3779{
3780 MDICREATESTRUCTA mdi_cs;
3781 CLIENTCREATESTRUCT client_cs;
3782 HWND mdi_frame, mdi_child, mdi_child2, active_child;
3783 BOOL zoomed;
3784 RECT rc;
3785 HMENU hMenu = CreateMenu();
3786 LONG val;
3787
3789
3791
3792 trace("creating MDI frame window\n");
3793 mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
3796 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
3797 GetDesktopWindow(), hMenu,
3799 assert(mdi_frame);
3800 ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", FALSE);
3801
3802 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3803 ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
3804
3805 trace("creating MDI client window\n");
3806 GetClientRect(mdi_frame, &rc);
3807 client_cs.hWindowMenu = 0;
3808 client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
3809 mdi_client = CreateWindowExA(0, "MDI_client_class",
3810 NULL,
3812 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
3813 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
3815 SetWindowLongA(mdi_client, 0, 0xdeadbeef);
3816
3817 ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE);
3818 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3819 ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
3820
3821 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3822 ok(!active_child, "wrong active MDI child %p\n", active_child);
3823 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3824
3825 SetFocus(0);
3827
3828 trace("creating invisible MDI child window\n");
3829 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3830 WS_CHILD,
3833 assert(mdi_child);
3834
3836 ShowWindow(mdi_child, SW_SHOWNORMAL);
3837 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
3838
3839 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3840 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
3841
3842 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3843 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3844
3845 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3846 ok(!active_child, "wrong active MDI child %p\n", active_child);
3847 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3848
3849 ShowWindow(mdi_child, SW_HIDE);
3850 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE);
3852
3853 ShowWindow(mdi_child, SW_SHOW);
3854 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
3855
3856 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3857 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
3858
3859 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3860 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3861
3862 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3863 ok(!active_child, "wrong active MDI child %p\n", active_child);
3864 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3865
3866 DestroyWindow(mdi_child);
3868
3869 trace("creating visible MDI child window\n");
3870 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3874 assert(mdi_child);
3875 ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE);
3876
3877 ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3878 ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
3879
3880 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3881 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
3882
3883 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3884 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
3885 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3887
3888 DestroyWindow(mdi_child);
3889 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
3890
3891 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3892 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3893
3894 /* Win2k: MDI client still returns a just destroyed child as active
3895 * Win9x: MDI client returns 0
3896 */
3897 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3898 ok(active_child == mdi_child || /* win2k */
3899 !active_child, /* win9x */
3900 "wrong active MDI child %p\n", active_child);
3901 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3902
3904
3905 trace("creating invisible MDI child window\n");
3906 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
3907 WS_CHILD,
3910 assert(mdi_child2);
3911 ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
3912
3913 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
3914 ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
3915
3916 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3917 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3918
3919 /* Win2k: MDI client still returns a just destroyed child as active
3920 * Win9x: MDI client returns mdi_child2
3921 */
3922 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3923 ok(active_child == mdi_child || /* win2k */
3924 active_child == mdi_child2, /* win9x */
3925 "wrong active MDI child %p\n", active_child);
3926 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3928
3929 ShowWindow(mdi_child2, SW_MAXIMIZE);
3930 ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE);
3931
3932 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3933 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
3934
3935 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3936 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3937 ok(zoomed, "wrong zoomed state %d\n", zoomed);
3939
3940 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3941 ok(GetFocus() == mdi_child2 || /* win2k */
3942 GetFocus() == 0, /* win9x */
3943 "wrong focus window %p\n", GetFocus());
3944
3945 SetFocus(0);
3947
3948 ShowWindow(mdi_child2, SW_HIDE);
3949 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
3950
3951 ShowWindow(mdi_child2, SW_RESTORE);
3952 ok_sequence(WmRestoreMDIchildInvisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE);
3954
3955 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
3956 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
3957
3958 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3959 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3960 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3962
3963 SetFocus(0);
3965
3966 ShowWindow(mdi_child2, SW_HIDE);
3967 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
3968
3969 ShowWindow(mdi_child2, SW_SHOW);
3970 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
3971
3972 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3973 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3974
3975 ShowWindow(mdi_child2, SW_MAXIMIZE);
3976 ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE);
3977
3978 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3979 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3980
3981 ShowWindow(mdi_child2, SW_RESTORE);
3982 ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE);
3983
3984 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3985 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3986
3987 ShowWindow(mdi_child2, SW_MINIMIZE);
3988 ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", FALSE);
3989
3990 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
3991 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3992
3993 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
3994 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
3995 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
3997
3998 ShowWindow(mdi_child2, SW_RESTORE);
3999 ok_sequence(WmRestoreMDIchildVisibleSeq_2, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE);
4000
4001 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4002 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
4003
4004 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4005 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4006 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4008
4009 SetFocus(0);
4011
4012 ShowWindow(mdi_child2, SW_HIDE);
4013 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
4014
4015 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4016 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4017
4018 DestroyWindow(mdi_child2);
4019 ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
4020
4021 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4022 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4023
4024 trace("Testing WM_CHILDACTIVATE\n");
4025
4026 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4030
4031 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4035
4036 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4037 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4038 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4039
4041 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0);
4042 ok_sequence(WmChildActivateDisabledWindowSeq, "WM_CHILDACTIVATE sent to disabled window", FALSE);
4043
4044 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4045 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4046 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4048
4049 EnableWindow(mdi_child, TRUE);
4050
4051 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4052 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4053 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4054
4056 SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0);
4057 ok_sequence(WmChildActivateWindowSeq, "WM_CHILDACTIVATE sent to enabled window", FALSE);
4058
4059 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4060 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4061 ok(!zoomed, "wrong zoomed state %d\n", zoomed);
4063
4064 DestroyWindow(mdi_child);
4065 DestroyWindow(mdi_child2);
4067
4068 /* test for maximized MDI children */
4069 trace("creating maximized visible MDI child window 1\n");
4070 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4074 assert(mdi_child);
4075 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE);
4076 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
4077
4078 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4079 ok(GetFocus() == mdi_child || /* win2k */
4080 GetFocus() == 0, /* win9x */
4081 "wrong focus window %p\n", GetFocus());
4082
4083 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4084 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4085 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4087
4088 trace("creating maximized visible MDI child window 2\n");
4089 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4093 assert(mdi_child2);
4094 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
4095 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
4096 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
4097
4098 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4099 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
4100
4101 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4102 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4103 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4105
4106 trace("destroying maximized visible MDI child window 2\n");
4107 DestroyWindow(mdi_child2);
4108 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
4109
4110 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
4111
4112 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4113 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4114
4115 /* Win2k: MDI client still returns a just destroyed child as active
4116 * Win9x: MDI client returns 0
4117 */
4118 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4119 ok(active_child == mdi_child2 || /* win2k */
4120 !active_child, /* win9x */
4121 "wrong active MDI child %p\n", active_child);
4123
4124 ShowWindow(mdi_child, SW_MAXIMIZE);
4125 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
4127
4128 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4129 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
4130
4131 trace("re-creating maximized visible MDI child window 2\n");
4132 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4136 assert(mdi_child2);
4137 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE);
4138 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n");
4139 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
4140
4141 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4142 ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
4143
4144 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4145 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4146 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4148
4149 SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0);
4150 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE);
4151 ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
4152
4153 ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
4154 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4155 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
4156
4157 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4158 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4159 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4161
4162 DestroyWindow(mdi_child);
4163 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
4164
4165 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4166 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4167
4168 /* Win2k: MDI client still returns a just destroyed child as active
4169 * Win9x: MDI client returns 0
4170 */
4171 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4172 ok(active_child == mdi_child || /* win2k */
4173 !active_child, /* win9x */
4174 "wrong active MDI child %p\n", active_child);
4176
4177 trace("creating maximized invisible MDI child window\n");
4178 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4182 assert(mdi_child2);
4183 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", FALSE);
4184 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n");
4185 ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n");
4186 ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n");
4187
4188 /* Win2k: MDI client still returns a just destroyed child as active
4189 * Win9x: MDI client returns 0
4190 */
4191 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4192 ok(active_child == mdi_child || /* win2k */
4193 !active_child || active_child == mdi_child2, /* win9x */
4194 "wrong active MDI child %p\n", active_child);
4196
4197 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4198 ShowWindow(mdi_child2, SW_MAXIMIZE);
4199 ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE);
4200 ok(IsZoomed(mdi_child2), "MDI child should be maximized\n");
4201 ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
4202 ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
4203
4204 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4205 ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child);
4206 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4208
4209 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0);
4211
4212 /* end of test for maximized MDI children */
4213 SetFocus(0);
4215 trace("creating maximized visible MDI child window 1(Switch test)\n");
4216 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4220 assert(mdi_child);
4221 ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE);
4222 ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n");
4223
4224 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow());
4225 ok(GetFocus() == mdi_child || /* win2k */
4226 GetFocus() == 0, /* win9x */
4227 "wrong focus window %p(Switch test)\n", GetFocus());
4228
4229 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4230 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child);
4231 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed);
4233
4234 trace("creating maximized visible MDI child window 2(Switch test)\n");
4235 mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4239 assert(mdi_child2);
4240 ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE);
4241
4242 ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n");
4243 ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n");
4244
4245 ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow());
4246 ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus());
4247
4248 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4249 ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child);
4250 ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed);
4252
4253 trace("Switch child window.\n");
4255 ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE);
4256 trace("end of test for switch maximized MDI children\n");
4258
4259 /* Prepare for switching test of not maximized MDI children */
4260 ShowWindow( mdi_child, SW_NORMAL );
4261 ok(!IsZoomed(mdi_child), "wrong zoomed state for %p(Switch test)\n", mdi_child);
4262 ok(!IsZoomed(mdi_child2), "wrong zoomed state for %p(Switch test)\n", mdi_child2);
4263 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
4264 ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child);
4266
4267 SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child2, 0);
4268 ok_sequence(WmSwitchNotMaximizedChild, "Not maximized child did not switch correctly", FALSE);
4269 trace("end of test for switch not maximized MDI children\n");
4271
4274
4275 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0);
4277
4278 SetFocus(0);
4280 /* end of tests for switch maximized/not maximized MDI children */
4281
4282 mdi_cs.szClass = "MDI_child_Class";
4283 mdi_cs.szTitle = "MDI child";
4284 mdi_cs.hOwner = GetModuleHandleA(0);
4285 mdi_cs.x = 0;
4286 mdi_cs.y = 0;
4287 mdi_cs.cx = CW_USEDEFAULT;
4288 mdi_cs.cy = CW_USEDEFAULT;
4290 mdi_cs.lParam = 0;
4291 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
4292 ok(mdi_child != 0, "MDI child creation failed\n");
4293 ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
4294
4295 ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
4296
4297 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4298 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4299
4300 ok(IsZoomed(mdi_child), "MDI child should be maximized\n");
4301 ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
4302 ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
4303
4304 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4305 ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
4306 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4308
4310 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
4311
4312 ok(!IsWindow(mdi_child), "MDI child should be destroyed\n");
4313 active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed);
4314 ok(!active_child, "wrong active MDI child %p\n", active_child);
4315
4316 SetFocus(0);
4318
4320 ok(val == 0xdeadbeef || broken(val == 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val);
4322 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
4323
4324 /* test maximization of MDI child with invisible parent */
4325 client_cs.hWindowMenu = 0;
4326 mdi_client = CreateWindowA("MDI_client_class",
4327 NULL,
4329 0, 0, 660, 430,
4330 mdi_frame, 0, GetModuleHandleA(0), &client_cs);
4331 ok_sequence(WmCreateMDIclientSeq, "Create MDI client window", FALSE);
4332
4334 ok_sequence(WmHideMDIclientSeq, "Hide MDI client window", FALSE);
4335
4336 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
4338 0, 0, 650, 440,
4340 ok_sequence(WmCreateMDIchildInvisibleParentSeq, "Create MDI child window with invisible parent", FALSE);
4341
4342 SendMessageA(mdi_client, WM_MDIMAXIMIZE, (WPARAM) mdi_child, 0);
4343 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq, "Maximize MDI child window with invisible parent", TRUE);
4344 zoomed = IsZoomed(mdi_child);
4345 ok(zoomed, "wrong zoomed state %d\n", zoomed);
4346
4348 ok_sequence(WmShowMDIclientSeq, "Show MDI client window", FALSE);
4349
4350 DestroyWindow(mdi_child);
4351 ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible maximized MDI child window", TRUE);
4352
4353 /* end of test for maximization of MDI child with invisible parent */
4354
4356 ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
4357
4358 DestroyWindow(mdi_frame);
4359 ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);
4360}
4361/************************* End of MDI test **********************************/
4362
4364{
4366
4367 flush_events();
4369
4371 ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
4372
4373 ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
4374 ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
4375
4378 ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
4379
4380 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
4381 ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
4382
4383 /* restore original WS_VISIBLE state */
4385
4386 flush_events();
4388}
4389
4391{
4392 struct recvd_message msg;
4393
4394 if (ignore_message( message )) return 0;
4395
4396 switch (message)
4397 {
4398 /* ignore */
4399 case WM_MOUSEMOVE:
4400 case WM_NCMOUSEMOVE:
4401 case WM_NCMOUSELEAVE:
4402 case WM_SETCURSOR:
4403 return 0;
4404 case WM_NCHITTEST:
4405 return HTCLIENT;
4406 }
4407
4408 msg.hwnd = hwnd;
4409 msg.message = message;
4410 msg.flags = sent|wparam|lparam;
4411 msg.wParam = wParam;
4412 msg.lParam = lParam;
4413 msg.descr = "dialog";
4414 add_message(&msg);
4415
4416 if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
4417 if (message == WM_TIMER) EndDialog( hwnd, 0 );
4418 return 0;
4419}
4420
4422{
4423 struct recvd_message msg;
4424
4425 if (ignore_message( message )) return 0;
4426
4427 switch (message)
4428 {
4429 /* ignore */
4430 case WM_MOUSEMOVE:
4431 case WM_NCMOUSEMOVE:
4432 case WM_NCMOUSELEAVE:
4433 case WM_SETCURSOR:
4434 return 0;
4435 case WM_NCHITTEST:
4436 return HTCLIENT;
4437 }
4438
4439 msg.hwnd = hwnd;
4440 msg.message = message;
4441 msg.flags = sent|wparam|lparam;
4442 msg.wParam = wParam;
4443 msg.lParam = lParam;
4444 msg.descr = "dialog";
4445 add_message(&msg);
4446
4447 if (message == WM_INITDIALOG) EndDialog( hwnd, 0 );
4448 return 0;
4449}
4450
4451static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
4452{
4453 DWORD style, exstyle;
4454 INT xmin, xmax;
4455 BOOL ret;
4456
4457 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4459 /* do not be confused by WS_DLGFRAME set */
4460 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
4461
4462 if (clear) ok(style & clear, "style %08x should be set\n", clear);
4463 if (set) ok(!(style & set), "style %08x should not be set\n", set);
4464
4465 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
4466 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError());
4467 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
4468 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE);
4469 else
4470 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
4471
4473 if (set) ok(style & set, "style %08x should be set\n", set);
4474 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear);
4475
4476 /* a subsequent call should do nothing */
4477 ret = SetScrollRange(hwnd, ctl, min, max, FALSE);
4478 ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError());
4479 ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
4480
4481 xmin = 0xdeadbeef;
4482 xmax = 0xdeadbeef;
4483 ret = GetScrollRange(hwnd, ctl, &xmin, &xmax);
4484 ok( ret, "GetScrollRange(%d) error %d\n", ctl, GetLastError());
4485 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
4486 ok(xmin == min, "unexpected min scroll value %d\n", xmin);
4487 ok(xmax == max, "unexpected max scroll value %d\n", xmax);
4488}
4489
4490static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
4491{
4492 DWORD style, exstyle;
4493 SCROLLINFO si;
4494 BOOL ret;
4495
4496 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4498 /* do not be confused by WS_DLGFRAME set */
4499 if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
4500
4501 if (clear) ok(style & clear, "style %08x should be set\n", clear);
4502 if (set) ok(!(style & set), "style %08x should not be set\n", set);
4503
4504 si.cbSize = sizeof(si);
4505 si.fMask = SIF_RANGE;
4506 si.nMin = min;
4507 si.nMax = max;
4508 SetScrollInfo(hwnd, ctl, &si, TRUE);
4509 if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
4510 ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE);
4511 else
4512 ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
4513
4515 if (set) ok(style & set, "style %08x should be set\n", set);
4516 if (clear) ok(!(style & clear), "style %08x should not be set\n", clear);
4517
4518 /* a subsequent call should do nothing */
4519 SetScrollInfo(hwnd, ctl, &si, TRUE);
4520 if (style & WS_HSCROLL)
4521 ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4522 else if (style & WS_VSCROLL)
4523 ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4524 else
4525 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4526
4527 si.fMask = SIF_PAGE;
4528 si.nPage = 5;
4529 SetScrollInfo(hwnd, ctl, &si, FALSE);
4530 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4531
4532 si.fMask = SIF_POS;
4533 si.nPos = max - 1;
4534 SetScrollInfo(hwnd, ctl, &si, FALSE);
4535 ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
4536
4537 si.fMask = SIF_RANGE;
4538 si.nMin = 0xdeadbeef;
4539 si.nMax = 0xdeadbeef;
4540 ret = GetScrollInfo(hwnd, ctl, &si);
4541 ok( ret, "GetScrollInfo error %d\n", GetLastError());
4542 ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
4543 ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
4544 ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
4545}
4546
4547/* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4549{
4550 SCROLLINFO si;
4551 INT min, max;
4552 BOOL ret;
4553
4554 flush_events();
4556
4557 min = 0xdeadbeef;
4558 max = 0xdeadbeef;
4560 ok( ret, "GetScrollRange error %d\n", GetLastError());
4561 if (sequence->message != WmGetScrollRangeSeq[0].message)
4562 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
4563 /* values of min and max are undefined */
4565
4566 ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE);
4567 ok( ret, "SetScrollRange error %d\n", GetLastError());
4568 if (sequence->message != WmSetScrollRangeSeq[0].message)
4569 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
4571
4572 min = 0xdeadbeef;
4573 max = 0xdeadbeef;
4575 ok( ret, "GetScrollRange error %d\n", GetLastError());
4576 if (sequence->message != WmGetScrollRangeSeq[0].message)
4577 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
4578 /* values of min and max are undefined */
4580
4581 si.cbSize = sizeof(si);
4582 si.fMask = SIF_RANGE;
4583 si.nMin = 20;
4584 si.nMax = 160;
4586 if (sequence->message != WmSetScrollRangeSeq[0].message)
4587 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
4589
4590 si.fMask = SIF_PAGE;
4591 si.nPage = 10;
4593 if (sequence->message != WmSetScrollRangeSeq[0].message)
4594 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
4596
4597 si.fMask = SIF_POS;
4598 si.nPos = 20;
4600 if (sequence->message != WmSetScrollRangeSeq[0].message)
4601 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
4603
4604 si.fMask = SIF_RANGE;
4605 si.nMin = 0xdeadbeef;
4606 si.nMax = 0xdeadbeef;
4607 ret = GetScrollInfo(hwnd, SB_CTL, &si);
4608 ok( ret, "GetScrollInfo error %d\n", GetLastError());
4609 if (sequence->message != WmGetScrollInfoSeq[0].message)
4610 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
4611 /* values of min and max are undefined */
4613
4614 /* set WS_HSCROLL */
4615 test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
4616 /* clear WS_HSCROLL */
4618
4619 /* set WS_HSCROLL */
4620 test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
4621 /* clear WS_HSCROLL */
4623
4624 /* set WS_VSCROLL */
4625 test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
4626 /* clear WS_VSCROLL */
4628
4629 /* set WS_VSCROLL */
4630 test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
4631 /* clear WS_VSCROLL */
4633}
4634
4635static void test_showwindow(void)
4636{
4637 HWND hwnd, hchild;
4638 RECT rc;
4639
4640 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
4641 100, 100, 200, 200, 0, 0, 0, NULL);
4642 ok (hwnd != 0, "Failed to create overlapped window\n");
4643 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
4644 0, 0, 10, 10, hwnd, 0, 0, NULL);
4645 ok (hchild != 0, "Failed to create child\n");
4647
4648 /* ShowWindow( SW_SHOWNA) for invisible top level window */
4649 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
4650 ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
4651 ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE);
4652
4653 /* ShowWindow( SW_SHOWNA) for now visible top level window */
4654 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
4655 ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
4656 ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE);
4657 /* back to invisible */
4658 ShowWindow(hchild, SW_HIDE);
4661 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
4662 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
4663 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
4664 ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE);
4665 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
4666 ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
4668 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
4669 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
4670 ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE);
4671 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
4674 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
4675 ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
4676 ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE);
4677
4678 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
4679 ShowWindow( hchild, SW_HIDE);
4681 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
4682 ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
4683 ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE);
4684
4685 SetCapture(hchild);
4686 ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture());
4687 DestroyWindow(hchild);
4688 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
4689
4692
4693 /* Popup windows */
4694 /* Test 1:
4695 * 1. Create invisible maximized popup window.
4696 * 2. Move and resize it.
4697 * 3. Show it maximized.
4698 */
4699 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4700 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
4701 100, 100, 200, 200, 0, 0, 0, NULL);
4702 ok (hwnd != 0, "Failed to create popup window\n");
4703 ok(IsZoomed(hwnd), "window should be maximized\n");
4704 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
4705
4706 GetWindowRect(hwnd, &rc);
4709 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc ));
4710 /* Reset window's size & position */
4711 SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
4712 ok(IsZoomed(hwnd), "window should be maximized\n");
4714
4715 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4717 ok(IsZoomed(hwnd), "window should be maximized\n");
4718 ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE);
4719
4720 GetWindowRect(hwnd, &rc);
4723 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc ));
4726
4727 /* Test 2:
4728 * 1. Create invisible maximized popup window.
4729 * 2. Show it maximized.
4730 */
4731 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4732 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
4733 100, 100, 200, 200, 0, 0, 0, NULL);
4734 ok (hwnd != 0, "Failed to create popup window\n");
4735 ok(IsZoomed(hwnd), "window should be maximized\n");
4736 ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
4737
4738 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4740 ok(IsZoomed(hwnd), "window should be maximized\n");
4741 ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE);
4744
4745 /* Test 3:
4746 * 1. Create visible maximized popup window.
4747 */
4748 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
4749 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
4750 100, 100, 200, 200, 0, 0, 0, NULL);
4751 ok (hwnd != 0, "Failed to create popup window\n");
4752 ok(IsZoomed(hwnd), "window should be maximized\n");
4753 ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
4756
4757 /* Test 4:
4758 * 1. Create visible popup window.
4759 * 2. Maximize it.
4760 */
4761 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
4762 hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE,
4763 100, 100, 200, 200, 0, 0, 0, NULL);
4764 ok (hwnd != 0, "Failed to create popup window\n");
4765 ok(!IsZoomed(hwnd), "window should NOT be maximized\n");
4766 ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", FALSE);
4767
4768 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
4770 ok(IsZoomed(hwnd), "window should be maximized\n");
4771 ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
4774}
4775
4777{
4778 static const struct message seq[] =
4779 {
4780 { HCBT_ACTIVATE, hook },
4783 { HCBT_ACTIVATE, hook },
4787 { 0 }
4788 };
4789 HWND hwnd, recursive;
4790
4791 hwnd = CreateWindowExA(0, "SimpleWindowClass", NULL, WS_OVERLAPPED|WS_VISIBLE,
4792 100, 100, 200, 200, 0, 0, 0, NULL);
4793 ok(hwnd != 0, "Failed to create simple window\n");
4794
4795 recursive = CreateWindowExA(0, "RecursiveActivationClass", NULL, WS_OVERLAPPED|WS_VISIBLE,
4796 10, 10, 50, 50, hwnd, 0, 0, NULL);
4797 ok(recursive != 0, "Failed to create recursive activation window\n");
4799
4801 SetActiveWindow(recursive);
4802 ok_sequence(seq, "Recursive Activation", FALSE);
4803
4804 DestroyWindow(recursive);
4807}
4808
4809static void test_sys_menu(void)
4810{
4811 HWND hwnd;
4812 HMENU hmenu;
4813 UINT state;
4814
4815 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
4816 100, 100, 200, 200, 0, 0, 0, NULL);
4817 ok (hwnd != 0, "Failed to create overlapped window\n");
4818
4820
4821 /* test existing window without CS_NOCLOSE style */
4823 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
4824
4826 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
4827 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
4828
4830 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
4831
4833 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
4834 ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state);
4835
4837 ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
4838
4840 ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state);
4841 ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
4842
4843 /* test whether removing WS_SYSMENU destroys a system menu */
4848 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
4849
4851
4852 /* test new window with CS_NOCLOSE style */
4853 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW,
4854 100, 100, 200, 200, 0, 0, 0, NULL);
4855 ok (hwnd != 0, "Failed to create overlapped window\n");
4856
4858 ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
4859
4861 ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state);
4862
4864
4865 /* test new window without WS_SYSMENU style */
4866 hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW & ~WS_SYSMENU,
4867 100, 100, 200, 200, 0, 0, 0, NULL);
4868 ok(hwnd != 0, "Failed to create overlapped window\n");
4869
4871 ok(!hmenu, "GetSystemMenu error %d\n", GetLastError());
4872
4874}
4875
4876/* For shown WS_OVERLAPPEDWINDOW */
4877static const struct message WmSetIcon_1[] = {
4878 { WM_SETICON, sent },
4879 { 0x00AE, sent|defwinproc|optional }, /* XP */
4881 { WM_GETTEXT, sent|defwinproc|optional }, /* XP sends a duplicate */
4882 { 0 }
4883};
4884
4885/* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
4886static const struct message WmSetIcon_2[] = {
4887 { WM_SETICON, sent },
4888 { 0 }
4889};
4890
4891/* Sending undocumented 0x3B message with wparam = 0x8000000b */
4892static const struct message WmInitEndSession[] = {
4893 { 0x003B, sent },
4894 { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF },
4895 { 0 }
4896};
4897
4898/* Sending undocumented 0x3B message with wparam = 0x0000000b */
4899static const struct message WmInitEndSession_2[] = {
4900 { 0x003B, sent },
4902 { 0 }
4903};
4904
4905/* Sending undocumented 0x3B message with wparam = 0x80000008 */
4906static const struct message WmInitEndSession_3[] = {
4907 { 0x003B, sent },
4908 { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF },
4909 { 0 }
4910};
4911
4912/* Sending undocumented 0x3B message with wparam = 0x00000008 */
4913static const struct message WmInitEndSession_4[] = {
4914 { 0x003B, sent },
4916 { 0 }
4917};
4918
4919/* Sending undocumented 0x3B message with wparam = 0x80000001 */
4920static const struct message WmInitEndSession_5[] = {
4921 { 0x003B, sent },
4922 { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF },
4923 { 0 }
4924};
4925
4926static const struct message WmOptionalPaint[] = {
4927 { WM_PAINT, sent|optional },
4931 { 0 }
4932};
4933
4934static const struct message WmZOrder[] = {
4935 { WM_WINDOWPOSCHANGING, sent|wparam, 0, 0 },
4937 { HCBT_ACTIVATE, hook },
4939 { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 },
4943 { WM_ACTIVATEAPP, sent|wparam, 1, 0 },
4944 { WM_NCACTIVATE, sent|lparam, 1, 0 },
4947 { WM_ACTIVATE, sent|wparam|lparam, 1, 0 },
4948 { HCBT_SETFOCUS, hook },
4955 { 0 }
4956};
4957
4959{
4960 /* nothing */
4961}
4962
4964{
4965 DWORD ret;
4966 MSG msg;
4967
4969 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
4970
4971 PostMessageA(hwnd, WM_USER, 0, 0);
4972
4974 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
4975
4976 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
4977 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
4978
4980 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
4981
4982 PostMessageA(hwnd, WM_USER, 0, 0);
4983
4985 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
4986
4987 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n");
4988 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
4989
4990 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
4992 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
4993
4994 PostMessageA(hwnd, WM_USER, 0, 0);
4995
4996 /* new incoming message causes it to become signaled again */
4998 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
4999
5000 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5001 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5002 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5003 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5004
5005 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
5006 PostMessageA( hwnd, WM_USER, 0, 0 );
5007 ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n");
5008 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5009
5011 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
5012
5013 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5014 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5015
5016 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
5018 ok(ret, "QueueUserAPC failed %u\n", GetLastError());
5019
5021 ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
5022
5023 /* but even with MWMO_ALERTABLE window events are preferred */
5024 PostMessageA( hwnd, WM_USER, 0, 0 );
5025
5027 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
5028
5029 ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
5030 ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
5031
5032 /* the APC call is still queued */
5034 ok(ret == WAIT_IO_COMPLETION, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
5035}
5036
5038{
5039 DWORD ret;
5040 MSG msg;
5041 int i;
5042 static const WPARAM wparams[] = {0,
5049 DBT_CONFIGMGPRIVATE, /* 0x7fff */
5050 DBT_DEVICEARRIVAL, /* 0x8000 */
5057
5058 for (i = 0; i < ARRAY_SIZE(wparams); i++)
5059 {
5060 SetLastError(0xdeadbeef);
5061 ret = PostMessageA(hwnd, WM_DEVICECHANGE, wparams[i], 0);
5062 if (wparams[i] & 0x8000)
5063 {
5064 ok(ret == FALSE, "PostMessage should returned %d\n", ret);
5065 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY, "PostMessage error %08x\n", GetLastError());
5066 }
5067 else
5068 {
5070 ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
5071 memset(&msg, 0, sizeof(msg));
5072 ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should succeed\n");
5073 ok(msg.message == WM_DEVICECHANGE, "got %04x instead of WM_DEVICECHANGE\n", msg.message);
5074 }
5075 }
5076}
5077
5079{
5080 HWND hwnd = arg;
5081
5082 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
5083 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n");
5084
5085 return 0;
5086}
5087
5088/* Helper function to easier test SetWindowPos messages */
5089#define test_msg_setpos( expected_list, flags, todo ) \
5090 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
5091static void test_msg_setpos_(const struct message *expected_list, UINT flags, BOOL todo, const char *file, int line)
5092{
5093 HWND hwnd;
5094
5095 flush_events();
5097 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP,
5098 10, 10, 100, 100, NULL, 0, 0, NULL );
5099 ok (hwnd != 0, "Failed to create popup window\n");
5100 SetWindowPos(hwnd, NULL, 0, 0, 100, 100, flags);
5101 ok_sequence_(expected_list, "SetWindowPos:show_popup_first_show_window", todo, file, line);
5103}
5104
5105/* test if we receive the right sequence of messages */
5106static void test_messages(void)
5107{
5108 DWORD tid;
5109 HANDLE hthread;
5110 HWND hwnd, hparent, hchild;
5111 HWND hchild2, hbutton;
5112 HMENU hmenu;
5113 MSG msg;
5114 LRESULT res;
5115 POINT pos;
5116 BOOL ret;
5117
5119
5120 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
5121 100, 100, 200, 200, 0, 0, 0, NULL);
5122 ok (hwnd != 0, "Failed to create overlapped window\n");
5123 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
5124
5125 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5126 ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
5127 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
5128
5129 /* test WM_SETREDRAW on a not visible top level window */
5131
5133 flush_events();
5134 ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE);
5135 ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
5136
5137 ok(GetActiveWindow() == hwnd, "window should be active\n");
5138 ok(GetFocus() == hwnd, "window should have input focus\n");
5140 flush_events();
5141 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5142
5143 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5144 ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n");
5145 flush_events();
5146 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5147
5148 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5149 hthread = CreateThread(NULL, 0, show_window_thread, hwnd, 0, &tid);
5150 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
5151 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
5152 CloseHandle(hthread);
5153 flush_events();
5154 ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5155
5157 flush_events();
5158 ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
5159
5161 flush_events();
5162 ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
5163
5165 flush_events();
5166 ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE);
5168
5170 {
5172 flush_events();
5173 ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE);
5175 }
5176
5178 flush_events();
5179 ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE);
5181
5183 {
5185 flush_events();
5186 ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE);
5188 }
5189
5191 flush_events();
5192 ok_sequence(WmOptionalPaint, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
5193
5195 ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE);
5196 ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
5197 ok(GetActiveWindow() == hwnd, "window should still be active\n");
5198
5199 /* test WM_SETREDRAW on a visible top level window */
5201 flush_events();
5203
5204 trace("testing scroll APIs on a visible top level window %p\n", hwnd);
5206
5207 /* test resizing and moving */
5208 SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOACTIVATE );
5209 ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE );
5210 flush_events();
5212 SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE );
5213 ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE );
5214 flush_events();
5216 SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE );
5217 ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE );
5218 flush_events();
5220
5221 /* popups don't get WM_GETMINMAXINFO */
5225 SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOACTIVATE );
5226 ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
5227
5229 ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
5230
5231 /* Test if windows are correctly drawn when first shown */
5232
5233 /* Visible, redraw */
5234 flush_events();
5236 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE,
5237 10, 10, 100, 100, NULL, 0, 0, NULL );
5238 ok (hwnd != 0, "Failed to create popup window\n");
5240 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_visible", FALSE);
5242
5243 /* Invisible, show, message */
5244 flush_events();
5246 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP,
5247 10, 10, 100, 100, NULL, 0, 0, NULL );
5248 ok (hwnd != 0, "Failed to create popup window\n");
5250 SendMessageW(hwnd, WM_PAINT, 0, 0);
5251 ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_show", FALSE);
5253
5254 /* Invisible, show maximized, redraw */
5255 flush_events();
5257 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP,
5258 10, 10, 100, 100, NULL, 0, 0, NULL );
5259 ok (hwnd != 0, "Failed to create popup window\n");
5262 ok_sequence(WmShowPopupFirstDrawSeq_2, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE);
5264
5265 /* Test SetWindowPos */
5270
5276
5283
5290
5297
5298 /* Test SetWindowPos with child windows */
5299 flush_events();
5300 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5301 100, 100, 200, 200, 0, 0, 0, NULL);
5302 ok (hparent != 0, "Failed to create parent window\n");
5303
5304 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
5305 0, 0, 10, 10, hparent, 0, 0, NULL);
5306 ok (hchild != 0, "Failed to create child window\n");
5308 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW);
5309 ok_sequence(WmFirstDrawChildSeq1, /* Expect no messages for the child */
5310 "SetWindowPos:show_popup_first_show_window_child1", FALSE);
5311 DestroyWindow(hchild);
5312 DestroyWindow(hparent);
5313
5314 flush_events();
5315 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
5316 100, 100, 200, 200, 0, 0, 0, NULL);
5317 ok (hparent != 0, "Failed to create parent window\n");
5318
5319 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
5320 0, 0, 10, 10, hparent, 0, 0, NULL);
5321 ok (hchild != 0, "Failed to create child window\n");
5323 SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW);
5324 ok_sequence(WmFirstDrawChildSeq2, /* Expect child to be redrawn */
5325 "SetWindowPos:show_popup_first_show_window_child2", FALSE);
5326 DestroyWindow(hchild);
5327 DestroyWindow(hparent);
5328
5329 /* Test message sequence for extreme position and size */
5330
5332 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE,
5333 -10, -10, 10000, 10000, NULL, 0, 0, NULL );
5334 ok (hwnd != 0, "Failed to create popup window\n");
5335 ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", FALSE);
5337
5338
5339 /* Test child windows */
5340
5341 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5342 100, 100, 200, 200, 0, 0, 0, NULL);
5343 ok (hparent != 0, "Failed to create parent window\n");
5345
5346 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
5347 0, 0, 10, 10, hparent, 0, 0, NULL);
5348 ok (hchild != 0, "Failed to create child window\n");
5349 ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE);
5350 DestroyWindow(hchild);
5352
5353 /* visible child window with a caption */
5354 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
5356 0, 0, 10, 10, hparent, 0, 0, NULL);
5357 ok (hchild != 0, "Failed to create child window\n");
5358 ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
5359
5360 trace("testing scroll APIs on a visible child window %p\n", hchild);
5361 test_scroll_messages(hchild);
5362
5364 ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
5365
5366 DestroyWindow(hchild);
5368
5369 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5370 0, 0, 10, 10, hparent, 0, 0, NULL);
5371 ok (hchild != 0, "Failed to create child window\n");
5372 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
5373
5374 hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
5375 100, 100, 50, 50, hparent, 0, 0, NULL);
5376 ok (hchild2 != 0, "Failed to create child2 window\n");
5378
5379 hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
5380 0, 100, 50, 50, hchild, 0, 0, NULL);
5381 ok (hbutton != 0, "Failed to create button window\n");
5382
5383 /* test WM_SETREDRAW on a not visible child window */
5384 test_WM_SETREDRAW(hchild);
5385
5386 ShowWindow(hchild, SW_SHOW);
5387 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
5388
5389 /* check parent messages too */
5391 ShowWindow(hchild, SW_HIDE);
5392 ok_sequence(WmHideChildSeq2, "ShowWindow(SW_HIDE):child", FALSE);
5394
5395 ShowWindow(hchild, SW_SHOW);
5396 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
5397
5398 ShowWindow(hchild, SW_HIDE);
5399 ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
5400
5401 ShowWindow(hchild, SW_SHOW);
5402 ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
5403
5404 /* test WM_SETREDRAW on a visible child window */
5405 test_WM_SETREDRAW(hchild);
5406
5408 MoveWindow(hchild, 10, 10, 20, 20, TRUE);
5411
5412 ShowWindow(hchild, SW_HIDE);
5415 ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
5416
5417 ShowWindow(hchild, SW_HIDE);
5420 ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
5421
5422 /* DestroyWindow sequence below expects that a child has focus */
5423 SetFocus(hchild);
5425
5426 DestroyWindow(hchild);
5427 ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE);
5428 DestroyWindow(hchild2);
5429 DestroyWindow(hbutton);
5430
5432 hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
5433 0, 0, 100, 100, hparent, 0, 0, NULL);
5434 ok (hchild != 0, "Failed to create child popup window\n");
5435 ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE);
5436 DestroyWindow(hchild);
5437
5438 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5440 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
5441 0, 0, 100, 100, hparent, 0, 0, NULL);
5442 ok (hchild != 0, "Failed to create popup window\n");
5443 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
5444 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5445 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
5447 ShowWindow(hchild, SW_SHOW);
5448 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
5451 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
5454 ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE);
5455 DestroyWindow(hchild);
5456
5457 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5458 * changes nothing in message sequences.
5459 */
5461 hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
5462 0, 0, 100, 100, hparent, 0, 0, NULL);
5463 ok (hchild != 0, "Failed to create popup window\n");
5464 ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE);
5465 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5466 ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
5468 ShowWindow(hchild, SW_SHOW);
5469 ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE);
5472 ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE);
5473 DestroyWindow(hchild);
5474
5477 0, 0, 100, 100, hparent, 0, 0, NULL);
5478 ok(hwnd != 0, "Failed to create custom dialog window\n");
5479 ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
5480
5481 if(0) {
5482 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
5484 }
5485
5487
5488 test_def_id = TRUE;
5489 SendMessageA(hwnd, WM_NULL, 0, 0);
5490
5493 EndDialog( hwnd, 0 );
5494 ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
5495
5499
5500 ok(GetCursorPos(&pos), "GetCursorPos failed\n");
5501 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5502
5503 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP|WS_CHILD,
5504 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
5505 ok(hwnd != 0, "Failed to create custom dialog window\n");
5507 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
5509 ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
5510
5511 flush_events();
5513 ret = DrawMenuBar(hwnd);
5514 ok(ret, "DrawMenuBar failed: %d\n", GetLastError());
5515 flush_events();
5516 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
5517 ok(SetCursorPos(pos.x, pos.y), "SetCursorPos failed\n");
5518
5520
5521 hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_CHILD|WS_VISIBLE,
5522 0, 0, 100, 100, hparent, 0, GetModuleHandleA(0), NULL);
5523 ok(hwnd != 0, "Failed to create custom dialog window\n");
5524 flush_events();
5526 ret = DrawMenuBar(hwnd);
5527 ok(ret, "DrawMenuBar failed: %d\n", GetLastError());
5528 flush_events();
5529 ok_sequence(WmEmptySeq, "DrawMenuBar for a child window", FALSE);
5530
5532
5534 DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
5535 ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
5536
5537 DestroyWindow(hparent);
5539
5540 /* Message sequence for SetMenu */
5541 ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a destroyed window\n");
5542 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "last error is %d\n", GetLastError());
5543 ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
5544
5545 hmenu = CreateMenu();
5546 ok (hmenu != 0, "Failed to create menu\n");
5547 ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
5548 hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
5549 100, 100, 200, 200, 0, hmenu, 0, NULL);
5550 ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
5551 ok (SetMenu(hwnd, 0), "SetMenu\n");
5552 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE);
5553 ok (SetMenu(hwnd, 0), "SetMenu\n");
5554 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
5556 UpdateWindow( hwnd );
5557 flush_events();
5559 ok (SetMenu(hwnd, 0), "SetMenu\n");
5560 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE);
5561 ok (SetMenu(hwnd, hmenu), "SetMenu\n");
5562 ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE);
5563
5564 UpdateWindow( hwnd );
5565 flush_events();
5567 ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
5568 flush_events();
5569 ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
5570
5573
5574 /* Message sequence for EnableWindow */
5575 hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5576 100, 100, 200, 200, 0, 0, 0, NULL);
5577 ok (hparent != 0, "Failed to create parent window\n");
5578 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
5579 0, 0, 10, 10, hparent, 0, 0, NULL);
5580 ok (hchild != 0, "Failed to create child window\n");
5581
5582 SetFocus(hchild);
5583 flush_events();
5585
5586 EnableWindow(hparent, FALSE);
5587 ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE);
5588
5589 EnableWindow(hparent, FALSE);
5590 ok_sequence(WmEnableWindowSeq_2, "EnableWindow(FALSE)", FALSE);
5591
5592 EnableWindow(hparent, TRUE);
5593 ok_sequence(WmEnableWindowSeq_3, "EnableWindow(TRUE)", FALSE);
5594
5595 EnableWindow(hparent, TRUE);
5596 ok_sequence(WmEnableWindowSeq_4, "EnableWindow(TRUE)", FALSE);
5597
5598 flush_events();
5600
5602 test_WM_DEVICECHANGE(hparent);
5603
5604 /* the following test causes an exception in user.exe under win9x */
5605 if (!PostMessageW( hparent, WM_USER, 0, 0 ))
5606 {
5607 DestroyWindow(hparent);
5609 return;
5610 }
5611 PostMessageW( hparent, WM_USER+1, 0, 0 );
5612 /* PeekMessage(NULL) fails, but still removes the message */
5613 SetLastError(0xdeadbeef);
5614 ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" );
5615 ok( GetLastError() == ERROR_NOACCESS || /* Win2k */
5616 GetLastError() == 0xdeadbeef, /* NT4 */
5617 "last error is %d\n", GetLastError() );
5618 ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" );
5619 ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
5620
5621 DestroyWindow(hchild);
5622 DestroyWindow(hparent);
5624
5625 /* Message sequences for WM_SETICON */
5626 trace("testing WM_SETICON\n");
5627 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
5628 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5629 NULL, NULL, 0);
5632 flush_events();
5635 ok_sequence(WmSetIcon_1, "WM_SETICON for shown window with caption", FALSE);
5636
5638 flush_events();
5641 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window with caption", FALSE);
5644
5645 hwnd = CreateWindowExA(0, "TestPopupClass", NULL, WS_POPUP,
5646 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
5647 NULL, NULL, 0);
5650 flush_events();
5653 ok_sequence(WmSetIcon_2, "WM_SETICON for shown window without caption", FALSE);
5654
5656 flush_events();
5659 ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window without caption", FALSE);
5660
5662 res = SendMessageA(hwnd, 0x3B, 0x8000000b, 0);
5663 if (!res)
5664 {
5665 todo_wine win_skip( "Message 0x3b not supported\n" );
5666 goto done;
5667 }
5668 ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE);
5669 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res);
5670 res = SendMessageA(hwnd, 0x3B, 0x0000000b, 0);
5671 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE);
5672 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res);
5673 res = SendMessageA(hwnd, 0x3B, 0x0000000f, 0);
5674 ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE);
5675 ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res);
5676
5678 res = SendMessageA(hwnd, 0x3B, 0x80000008, 0);
5679 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE);
5680 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res);
5681 res = SendMessageA(hwnd, 0x3B, 0x00000008, 0);
5682 ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE);
5683 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res);
5684
5685 res = SendMessageA(hwnd, 0x3B, 0x80000004, 0);
5686 ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE);
5687 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res);
5688
5689 res = SendMessageA(hwnd, 0x3B, 0x80000001, 0);
5690 ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE);
5691 ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res);
5692
5693done:
5696}
5697
5698static void test_setwindowpos(void)
5699{
5700 HWND hwnd;
5701 RECT rc;
5702 LRESULT res;
5703 const INT winX = 100;
5704 const INT winY = 100;
5705 const INT sysX = GetSystemMetrics(SM_CXMINTRACK);
5706
5707 hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0,
5708 0, 0, winX, winY, 0,
5709 NULL, NULL, 0);
5710
5711 GetWindowRect(hwnd, &rc);
5712 expect(sysX, rc.right);
5713 expect(winY, rc.bottom);
5714
5715 flush_events();
5717 res = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, winX, winY, 0);
5718 ok_sequence(WmZOrder, "Z-Order", TRUE);
5719 ok(res == TRUE, "SetWindowPos expected TRUE, got %ld\n", res);
5720
5721 GetWindowRect(hwnd, &rc);
5722 expect(sysX, rc.right);
5723 expect(winY, rc.bottom);
5725}
5726
5727static void invisible_parent_tests(void)
5728{
5729 HWND hparent, hchild;
5730
5731 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
5732 100, 100, 200, 200, 0, 0, 0, NULL);
5733 ok (hparent != 0, "Failed to create parent window\n");
5735
5736 /* test showing child with hidden parent */
5737
5738 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5739 0, 0, 10, 10, hparent, 0, 0, NULL);
5740 ok (hchild != 0, "Failed to create child window\n");
5741 ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
5742
5743 ShowWindow( hchild, SW_MINIMIZE );
5744 ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
5745 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5746 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5747
5748 /* repeat */
5749 flush_events();
5751 ShowWindow( hchild, SW_MINIMIZE );
5752 ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
5753
5754 DestroyWindow(hchild);
5755 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5756 0, 0, 10, 10, hparent, 0, 0, NULL);
5758
5759 ShowWindow( hchild, SW_MAXIMIZE );
5760 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
5761 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5762 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5763
5764 /* repeat */
5765 flush_events();
5767 ShowWindow( hchild, SW_MAXIMIZE );
5768 ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
5769
5770 DestroyWindow(hchild);
5771 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5772 0, 0, 10, 10, hparent, 0, 0, NULL);
5774
5775 ShowWindow( hchild, SW_RESTORE );
5776 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE);
5777 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5778 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5779
5780 DestroyWindow(hchild);
5781 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5782 0, 0, 10, 10, hparent, 0, 0, NULL);
5784
5785 ShowWindow( hchild, SW_SHOWMINIMIZED );
5786 ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
5787 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5788 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5789
5790 /* repeat */
5791 flush_events();
5793 ShowWindow( hchild, SW_SHOWMINIMIZED );
5794 ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
5795
5796 DestroyWindow(hchild);
5797 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5798 0, 0, 10, 10, hparent, 0, 0, NULL);
5800
5801 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
5802 ShowWindow( hchild, SW_SHOWMAXIMIZED );
5803 ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE);
5804 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5805 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5806
5807 DestroyWindow(hchild);
5808 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5809 0, 0, 10, 10, hparent, 0, 0, NULL);
5811
5812 ShowWindow( hchild, SW_SHOWMINNOACTIVE );
5813 ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
5814 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5815 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5816
5817 /* repeat */
5818 flush_events();
5820 ShowWindow( hchild, SW_SHOWMINNOACTIVE );
5821 ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
5822
5823 DestroyWindow(hchild);
5824 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5825 0, 0, 10, 10, hparent, 0, 0, NULL);
5827
5828 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
5829 ShowWindow( hchild, SW_FORCEMINIMIZE );
5830 ok_sequence(WmEmptySeq, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE);
5831todo_wine {
5832 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
5833}
5834 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5835
5836 DestroyWindow(hchild);
5837 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5838 0, 0, 10, 10, hparent, 0, 0, NULL);
5840
5841 ShowWindow( hchild, SW_SHOWNA );
5842 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE);
5843 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5844 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5845
5846 /* repeat */
5847 flush_events();
5849 ShowWindow( hchild, SW_SHOWNA );
5850 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE);
5851
5852 DestroyWindow(hchild);
5853 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
5854 0, 0, 10, 10, hparent, 0, 0, NULL);
5856
5857 ShowWindow( hchild, SW_SHOW );
5858 ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOW) child with invisible parent", FALSE);
5859 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5860 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5861
5862 /* repeat */
5863 flush_events();
5865 ShowWindow( hchild, SW_SHOW );
5866 ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW) child with invisible parent", FALSE);
5867
5868 ShowWindow( hchild, SW_HIDE );
5869 ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE);
5870 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
5871 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5872
5874 ok_sequence(WmShowChildInvisibleParentSeq_6, "SetWindowPos:show child with invisible parent", FALSE);
5875 ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
5876 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5877
5879 ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE);
5880 ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
5881 ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
5882
5885 DestroyWindow(hchild);
5886 ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE);
5887
5888 DestroyWindow(hparent);
5890}
5891
5892/****************** button message test *************************/
5893#define ID_BUTTON 0x000e
5894
5895static const struct message WmSetFocusButtonSeq[] =
5896{
5897 { HCBT_SETFOCUS, hook },
5900 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5901 { WM_SETFOCUS, sent|wparam, 0 },
5904 { WM_APP, sent|wparam|lparam, 0, 0 },
5905 { 0 }
5906};
5907static const struct message WmKillFocusButtonSeq[] =
5908{
5909 { HCBT_SETFOCUS, hook },
5910 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5911 { WM_KILLFOCUS, sent|wparam, 0 },
5916 { WM_APP, sent|wparam|lparam, 0, 0 },
5917 { WM_PAINT, sent },
5919 { 0 }
5920};
5921static const struct message WmSetFocusStaticSeq[] =
5922{
5923 { HCBT_SETFOCUS, hook },
5926 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5927 { WM_SETFOCUS, sent|wparam, 0 },
5931 { WM_APP, sent|wparam|lparam, 0, 0 },
5932 { 0 }
5933};
5934static const struct message WmKillFocusStaticSeq[] =
5935{
5936 { HCBT_SETFOCUS, hook },
5937 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5938 { WM_KILLFOCUS, sent|wparam, 0 },
5943 { WM_APP, sent|wparam|lparam, 0, 0 },
5944 { WM_PAINT, sent },
5946 { 0 }
5947};
5948static const struct message WmSetFocusOwnerdrawSeq[] =
5949{
5950 { HCBT_SETFOCUS, hook },
5953 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5954 { WM_SETFOCUS, sent|wparam, 0 },
5956 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x001040e4 },
5958 { WM_APP, sent|wparam|lparam, 0, 0 },
5959 { 0 }
5960};
5961static const struct message WmKillFocusOwnerdrawSeq[] =
5962{
5963 { HCBT_SETFOCUS, hook },
5964 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5965 { WM_KILLFOCUS, sent|wparam, 0 },
5967 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000040e4 },
5971 { WM_APP, sent|wparam|lparam, 0, 0 },
5972 { WM_PAINT, sent },
5974 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 },
5975 { 0 }
5976};
5977static const struct message WmLButtonDownSeq[] =
5978{
5979 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
5980 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
5981 { HCBT_SETFOCUS, hook },
5984 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5989 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
5990 { 0 }
5991};
5992static const struct message WmLButtonDownStaticSeq[] =
5993{
5994 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
5995 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
5996 { HCBT_SETFOCUS, hook },
5999 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6004 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6005 { 0 }
6006};
6007static const struct message WmLButtonUpSeq[] =
6008{
6009 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6012 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6013 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6015 { 0 }
6016};
6017static const struct message WmLButtonUpStaticSeq[] =
6018{
6019 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6022 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6023 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6025 { 0 }
6026};
6027static const struct message WmLButtonUpAutoSeq[] =
6028{
6029 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6032 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6033 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6037 { 0 }
6038};
6039static const struct message WmLButtonUpBrokenSeq[] =
6040{
6041 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
6042 { 0 }
6043};
6044static const struct message WmSetFontButtonSeq[] =
6045{
6046 { WM_SETFONT, sent },
6047 { WM_PAINT, sent },
6050 { WM_CTLCOLORBTN, sent|defwinproc|optional }, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
6051 { 0 }
6052};
6053static const struct message WmSetFontStaticSeq[] =
6054{
6055 { WM_SETFONT, sent },
6056 { WM_PAINT, sent },
6059 { 0 }
6060};
6061static const struct message WmSetTextButtonSeq[] =
6062{
6063 { WM_SETTEXT, sent },
6068 { 0 }
6069};
6070static const struct message WmSetTextStaticSeq[] =
6071{
6072 { WM_SETTEXT, sent },
6075 { 0 }
6076};
6077static const struct message WmSetTextGroupSeq[] =
6078{
6079 { WM_SETTEXT, sent },
6081 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */
6082 { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */
6083 { 0 }
6084};
6085static const struct message WmSetTextInvisibleSeq[] =
6086{
6087 { WM_SETTEXT, sent },
6088 { 0 }
6089};
6090static const struct message WmSetStyleButtonSeq[] =
6091{
6092 { BM_SETSTYLE, sent },
6093 { WM_APP, sent|wparam|lparam, 0, 0 },
6094 { WM_PAINT, sent },
6095 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */
6096 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6098 { 0 }
6099};
6100static const struct message WmSetStyleStaticSeq[] =
6101{
6102 { BM_SETSTYLE, sent },
6103 { WM_APP, sent|wparam|lparam, 0, 0 },
6104 { WM_PAINT, sent },
6105 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */
6106 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6108 { 0 }
6109};
6110static const struct message WmSetStyleUserSeq[] =
6111{
6112 { BM_SETSTYLE, sent },
6113 { WM_APP, sent|wparam|lparam, 0, 0 },
6114 { WM_PAINT, sent },
6115 { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */
6116 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6119 { 0 }
6120};
6121static const struct message WmSetStyleOwnerdrawSeq[] =
6122{
6123 { BM_SETSTYLE, sent },
6124 { WM_APP, sent|wparam|lparam, 0, 0 },
6125 { WM_PAINT, sent },
6126 { WM_NCPAINT, sent|optional }, /* FIXME: Wine sends it */
6127 { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
6129 { WM_CTLCOLORBTN, sent|parent|optional }, /* Win9x doesn't send it */
6130 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 },
6131 { 0 }
6132};
6133static const struct message WmSetStateButtonSeq[] =
6134{
6135 { BM_SETSTATE, sent },
6137 { WM_APP, sent|wparam|lparam, 0, 0 },
6138 { 0 }
6139};
6140static const struct message WmSetStateStaticSeq[] =
6141{
6142 { BM_SETSTATE, sent },
6144 { WM_APP, sent|wparam|lparam, 0, 0 },
6145 { 0 }
6146};
6147static const struct message WmSetStateUserSeq[] =
6148{
6149 { BM_SETSTATE, sent },
6152 { WM_APP, sent|wparam|lparam, 0, 0 },
6153 { 0 }
6154};
6155static const struct message WmSetStateOwnerdrawSeq[] =
6156{
6157 { BM_SETSTATE, sent },
6159 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000120e4 },
6160 { WM_APP, sent|wparam|lparam, 0, 0 },
6161 { 0 }
6162};
6163static const struct message WmClearStateButtonSeq[] =
6164{
6165 { BM_SETSTATE, sent },
6168 { WM_APP, sent|wparam|lparam, 0, 0 },
6169 { 0 }
6170};
6171static const struct message WmDisableButtonSeq[] =
6172{
6173 { WM_LBUTTONDOWN, sent },
6177 { WM_LBUTTONUP, sent },
6185 { WM_COMMAND, sent },
6186 { 0 }
6187};
6188static const struct message WmClearStateOwnerdrawSeq[] =
6189{
6190 { BM_SETSTATE, sent },
6192 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000020e4 },
6193 { WM_APP, sent|wparam|lparam, 0, 0 },
6194 { 0 }
6195};
6196static const struct message WmSetCheckIgnoredSeq[] =
6197{
6198 { BM_SETCHECK, sent },
6199 { WM_APP, sent|wparam|lparam, 0, 0 },
6200 { 0 }
6201};
6202static const struct message WmSetCheckStaticSeq[] =
6203{
6204 { BM_SETCHECK, sent },
6206 { WM_APP, sent|wparam|lparam, 0, 0 },
6207 { 0 }
6208};
6209
6211
6213{
6214 static LONG defwndproc_counter = 0;
6215 LRESULT ret;
6216 struct recvd_message msg;
6217
6218 if (ignore_message( message )) return 0;
6219
6220 switch (message)
6221 {
6222 case WM_SYNCPAINT:
6223 break;
6224 case BM_SETSTATE:
6225 if (GetCapture())
6226 ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
6227
6229 goto log_it;
6230
6231 case WM_GETDLGCODE:
6232 if (lParam)
6233 {
6234 MSG *msg = (MSG *)lParam;
6235 lParam = MAKELPARAM(msg->message, msg->wParam);
6236 }
6238 goto log_it;
6239
6240 case BM_SETCHECK:
6241 case BM_GETCHECK:
6243 /* fall through */
6244log_it:
6245 default:
6246 msg.hwnd = hwnd;
6247 msg.message = message;
6248 msg.flags = sent|wparam|lparam;
6249 if (defwndproc_counter) msg.flags |= defwinproc;
6250 msg.wParam = wParam;
6251 msg.lParam = lParam;
6252 msg.descr = "button";
6253 add_message(&msg);
6254 }
6255
6256 defwndproc_counter++;
6258 defwndproc_counter--;
6259
6260 return ret;
6261}
6262
6263static void subclass_button(void)
6264{
6265 WNDCLASSA cls;
6266
6267 if (!GetClassInfoA(0, "button", &cls)) assert(0);
6268
6270
6273 cls.lpszClassName = "my_button_class";
6275 if (!RegisterClassA(&cls)) assert(0);
6276}
6277
6278static void test_button_messages(void)
6279{
6280 static const struct
6281 {
6282 DWORD style;
6283 DWORD dlg_code;
6284 const struct message *setfocus;
6285 const struct message *killfocus;
6286 const struct message *setstyle;
6287 const struct message *setstate;
6288 const struct message *clearstate;
6289 const struct message *setcheck;
6290 const struct message *lbuttondown;
6291 const struct message *lbuttonup;
6292 const struct message *setfont;
6293 const struct message *settext;
6294 } button[] = {
6343 NULL /* avoid infinite loop */, WmLButtonUpBrokenSeq, WmSetFontStaticSeq,
6350 };
6351 LOGFONTA logfont = { 0 };
6352 HFONT zfont, hfont2;
6353 unsigned int i;
6354 HWND hwnd, parent;
6355 DWORD dlg_code;
6356
6357 /* selection with VK_SPACE should capture button window */
6358 hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP,
6359 0, 0, 50, 14, 0, 0, 0, NULL);
6360 ok(hwnd != 0, "Failed to create button window\n");
6362 SetFocus(hwnd);
6364 ok(GetCapture() == hwnd, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6367
6369
6370 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6371 100, 100, 200, 200, 0, 0, 0, NULL);
6372 ok(parent != 0, "Failed to create parent window\n");
6373
6374 memset(&logfont, 0, sizeof(logfont));
6375 logfont.lfHeight = -12;
6376 logfont.lfWeight = FW_NORMAL;
6377 strcpy(logfont.lfFaceName, "Tahoma");
6378
6379 hfont2 = CreateFontIndirectA(&logfont);
6380 ok(hfont2 != NULL, "Failed to create Tahoma font\n");
6381
6382 for (i = 0; i < ARRAY_SIZE(button); i++)
6383 {
6384 MSG msg;
6385 DWORD style, state;
6386 HFONT prevfont;
6387 char desc[64];
6388 HDC hdc;
6389
6390 trace("button style %08x\n", button[i].style);
6391
6392 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY,
6393 0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL);
6394 ok(hwnd != 0, "Failed to create button window\n");
6395
6397 style &= ~(WS_CHILD | BS_NOTIFY);
6398 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6399 if (button[i].style == BS_USERBUTTON)
6400 ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style);
6401 else
6402 ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style);
6403
6404 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
6405 ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code);
6406
6409 SetFocus(0);
6410 flush_events();
6411 SetFocus(0);
6413
6415
6416 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6417 SetFocus(hwnd);
6418 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
6419 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6420 ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
6421
6422 SetFocus(0);
6423 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
6424 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6425 ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
6426
6427 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6428
6430 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
6431 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6432 ok_sequence(button[i].setstyle, "BM_SETSTYLE on a button", FALSE);
6433
6436 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
6437 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
6438
6440 ok(state == 0, "expected state 0, got %04x\n", state);
6441
6443
6445 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
6446 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6447 ok_sequence(button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE);
6448
6450 ok(state == 0x0004, "expected state 0x0004, got %04x\n", state);
6451
6454 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
6455
6457
6459 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
6460 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6461 ok_sequence(button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE);
6462
6464 ok(state == 0, "expected state 0, got %04x\n", state);
6465
6468 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
6469
6471 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
6472
6474
6476 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
6477 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6478 ok_sequence(WmSetCheckIgnoredSeq, "BM_SETCHECK on a button", FALSE);
6479
6481 ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
6482
6485 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
6486
6488
6490 SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
6491 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6492 ok_sequence(button[i].setcheck, "BM_SETCHECK on a button", FALSE);
6493
6494 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 1");
6495 sprintf(desc, "button[%i]: WM_SETTEXT on a visible button", i);
6496 ok_sequence(button[i].settext, desc, FALSE);
6497
6499 flush_events();
6501
6502 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 2");
6503 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i);
6505
6508 flush_events();
6510
6511 SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 3");
6512 sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i);
6514
6516 flush_events();
6517
6519 if (button[i].style == BS_PUSHBUTTON ||
6521 button[i].style == BS_GROUPBOX ||
6524 ok(state == BST_UNCHECKED, "expected check 0, got %04x\n", state);
6525 else
6526 ok(state == BST_CHECKED, "expected check 1, got %04x\n", state);
6527
6530 if (button[i].style == BS_RADIOBUTTON ||
6532 ok(style == (button[i].style | WS_TABSTOP), "expected style %04x | WS_TABSTOP got %04x\n", button[i].style, style);
6533 else
6534 ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
6535
6537
6539
6540 hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE,
6541 0, 0, 50, 14, 0, 0, 0, NULL);
6542 ok(hwnd != 0, "Failed to create button window\n");
6543
6545 flush_events();
6546
6548 SetFocus(0);
6550
6551 if (button[i].lbuttondown)
6552 {
6554 sprintf(desc, "button[%i]: WM_LBUTTONDOWN on a button", i);
6555 ok_sequence(button[i].lbuttondown, desc, FALSE);
6556 }
6557
6559 sprintf(desc, "button[%i]: WM_LBUTTONUP on a button", i);
6560 ok_sequence(button[i].lbuttonup, desc, FALSE);
6561
6566 sprintf(desc, "button[%i]: WM_SETFONT on a button", i);
6567 ok_sequence(button[i].setfont, desc, FALSE);
6568
6569 /* Test that original font is not selected back after painting */
6571
6572 prevfont = SelectObject(hdc, hfont2);
6573 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n");
6575 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i);
6576 SelectObject(hdc, prevfont);
6577
6578 prevfont = SelectObject(hdc, hfont2);
6579 ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n");
6581 ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PAINT\n", i);
6582 SelectObject(hdc, prevfont);
6583
6584 DeleteDC(hdc);
6585
6587 }
6588
6589 DeleteObject(hfont2);
6591
6592 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
6593
6594 parent = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6595 100, 100, 200, 200, 0, 0, 0, NULL);
6596 ok (hwnd != 0, "Failed to create overlapped window\n");
6597
6598 hwnd = CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
6599 0, 0, 50, 14, parent, 0, 0, NULL);
6600
6605 ok_sequence(WmDisableButtonSeq, "Mouseclick on a disabled button", FALSE);
6606
6609}
6610
6612{
6613 HWND hwnd;
6614 HDC hdc;
6615 HBITMAP hbmp1x1;
6616 HBITMAP hbmp2x2;
6617 HBITMAP hmask2x2;
6618 ICONINFO icon_info2x2;
6619 HICON hicon2x2;
6620 HBITMAP hbmp;
6621 HICON hicon;
6622 ICONINFO icon_info;
6623 BITMAP bm;
6624 DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP | WS_VISIBLE;
6625 LRESULT ret;
6626
6627 hdc = GetDC(0);
6628 hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1);
6629 hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2);
6630 ZeroMemory(&bm, sizeof(bm));
6631 ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW() success\n");
6632 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
6633 bm.bmWidth, bm.bmHeight);
6634 ZeroMemory(&bm, sizeof(bm));
6635 ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW() success\n");
6636 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
6637 bm.bmWidth, bm.bmHeight);
6638
6639 hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2);
6640 ZeroMemory(&icon_info2x2, sizeof(icon_info2x2));
6641 icon_info2x2.fIcon = TRUE;
6642 icon_info2x2.hbmMask = hmask2x2;
6643 icon_info2x2.hbmColor = hbmp2x2;
6644 hicon2x2 = CreateIconIndirect(&icon_info2x2);
6645
6646 ZeroMemory(&icon_info, sizeof(icon_info));
6647 ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo() success\n");
6648 ZeroMemory(&bm, sizeof(bm));
6649 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
6650 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
6651 bm.bmWidth, bm.bmHeight);
6652 DeleteObject(icon_info.hbmColor);
6653 DeleteObject(icon_info.hbmMask);
6654
6655 /* Set bitmap with BS_BITMAP */
6656 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0);
6657 ok(hwnd != NULL, "Expect hwnd not NULL\n");
6660 ok(hbmp != 0, "Expect hbmp not 0\n");
6661 ZeroMemory(&bm, sizeof(bm));
6662 ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
6663 ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
6664 bm.bmWidth, bm.bmHeight);
6666
6667 /* Set bitmap without BS_BITMAP */
6668 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
6669 ok(hwnd != NULL, "Expect hwnd not NULL\n");
6671 ok(ret == 0, "Expect ret to be 0\n");
6673 ok(hbmp == NULL, "Expect hbmp to be NULL\n");
6675
6676 /* Set icon with BS_ICON */
6677 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0);
6678 ok(hwnd != NULL, "Expect hwnd not NULL\n");
6681 ok(hicon != NULL, "Expect hicon not NULL\n");
6682 ZeroMemory(&icon_info, sizeof(icon_info));
6683 ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
6684 ZeroMemory(&bm, sizeof(bm));
6685 ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
6686 ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
6687 bm.bmWidth, bm.bmHeight);
6688 DeleteObject(icon_info.hbmColor);
6689 DeleteObject(icon_info.hbmMask);
6691
6692 /* Set icon without BS_ICON */
6693 hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
6694 ok(hwnd != NULL, "Expect hwnd not NULL\n");
6696 ok(ret == 0, "Expect ret to be 0\n");
6698 ok(hicon == NULL, "Expect hicon to be NULL\n");
6700
6701 /* Set icon with BS_BITMAP */
6702 hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0);
6703 ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
6705 ok(ret == 0, "Expect ret to be 0\n");
6707 ok(hicon == NULL, "Expect hicon to be NULL\n");
6709
6710 /* Set bitmap with BS_ICON */
6711 hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0);
6712 ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
6714 ok(ret == 0, "Expect ret to be 0\n");
6716 ok(hbmp == NULL, "Expect hbmp to be NULL\n");
6718
6719 DestroyIcon(hicon2x2);
6720 DeleteObject(hmask2x2);
6721 DeleteObject(hbmp2x2);
6722 DeleteObject(hbmp1x1);
6723 ReleaseDC(0, hdc);
6724}
6725
6726#define ID_RADIO1 501
6727#define ID_RADIO2 502
6728#define ID_RADIO3 503
6729#define ID_TEXT 504
6730
6732{
6733 { BM_CLICK, sent|wparam|lparam, 0, 0 },
6735 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6738 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6742 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6748 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6752 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6754 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6757 { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */
6758 { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */
6759 { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */
6760 { 0 }
6761};
6762
6764{
6766 { WM_KEYUP, sent|wparam|lparam, VK_UP, 0 },
6767 { 0 }
6768};
6769
6771{
6774 { 0 }
6775};
6776
6778{
6779 { WM_GETDLGCODE, sent|parent, 0, 0 },
6780
6781 /* optional trailer seen on some windows setups */
6782 { WM_CHANGEUISTATE, sent|optional },
6783 { WM_UPDATEUISTATE, sent|optional },
6784 { WM_UPDATEUISTATE, sent|optional },
6785 { WM_UPDATEUISTATE, sent|optional },
6786 { WM_UPDATEUISTATE, sent|optional },
6787 { WM_UPDATEUISTATE, sent|optional },
6788 { WM_UPDATEUISTATE, sent|optional },
6789 { WM_UPDATEUISTATE, sent|optional },
6790 { WM_UPDATEUISTATE, sent|optional },
6791 { WM_UPDATEUISTATE, sent|optional },
6792 { WM_UPDATEUISTATE, sent|optional },
6793 { WM_UPDATEUISTATE, sent|optional },
6794 { WM_UPDATEUISTATE, sent|optional },
6795 { WM_UPDATEUISTATE, sent|optional },
6796 { WM_UPDATEUISTATE, sent|optional },
6797 { WM_UPDATEUISTATE, sent|optional },
6798 { WM_UPDATEUISTATE, sent|optional },
6799 { WM_UPDATEUISTATE, sent|optional },
6800 { WM_UPDATEUISTATE, sent|optional },
6804 { WM_UPDATEUISTATE, sent|optional },
6807 { WM_UPDATEUISTATE, sent|optional },
6810 { WM_UPDATEUISTATE, sent|optional },
6813 { 0 }
6814};
6815
6817{
6818 { WM_GETDLGCODE, sent|parent, 0, 0 },
6821 { HCBT_SETFOCUS, hook },
6822 { WM_KILLFOCUS, sent, 0, 0 },
6825 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6826 { WM_SETFOCUS, sent, 0, 0 },
6831 { WM_GETDLGCODE, sent|parent, 0, 0 },
6832 { DM_GETDEFID, sent|parent, 0, 0 },
6834 { BM_CLICK, sent|wparam|lparam, 1, 0 },
6836 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
6839 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6843 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6847 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6851 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6856 { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
6857 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
6860 { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */
6861 { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */
6862 { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */
6863 { WM_PAINT, sent },
6865 { 0 }
6866};
6867
6869{
6873 { WM_GETDLGCODE, sent|parent, 0, 0 },
6878 { WM_USER, sent|parent, 0, 0 },
6880 { 0 }
6881};
6882
6884{
6885 { WM_GETDLGCODE, sent|parent, 0, 0 },
6886 { 0 }
6887};
6888
6890{
6891 ParentMsgCheckProcA(hwnd, msg, wp, lp);
6892 return 1;
6893}
6894
6896{
6897 HWND parent, radio1, radio2, radio3;
6898 RECT rc;
6899 MSG msg;
6900 DWORD ret;
6901
6903
6904 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc, 0);
6905 ok(parent != 0, "failed to create parent window\n");
6906
6907 radio1 = GetDlgItem(parent, ID_RADIO1);
6908 radio2 = GetDlgItem(parent, ID_RADIO2);
6909 radio3 = GetDlgItem(parent, ID_RADIO3);
6910
6911 /* this avoids focus messages in the generated sequence */
6912 SetFocus(radio2);
6913
6914 flush_events();
6916
6917 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
6918 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6919 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
6920 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6921 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
6922 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6923
6925
6926 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
6927 ok(ret == BST_CHECKED, "got %08x\n", ret);
6928 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
6929 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6930 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
6931 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6932
6934
6935 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
6936 ok(ret == BST_CHECKED, "got %08x\n", ret);
6937 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
6938 ok(ret == BST_CHECKED, "got %08x\n", ret);
6939 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
6940 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6941
6943
6944 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
6945 ok(ret == BST_CHECKED, "got %08x\n", ret);
6946 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
6947 ok(ret == BST_CHECKED, "got %08x\n", ret);
6948 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
6949 ok(ret == BST_CHECKED, "got %08x\n", ret);
6950
6951 GetWindowRect(radio2, &rc);
6952 SetCursorPos(rc.left+1, rc.top+1);
6953
6954 flush_events();
6956
6958
6959 SendMessageA(radio2, BM_CLICK, 0, 0);
6960 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
6961 ok_sequence(auto_radio_button_BM_CLICK, "BM_CLICK on auto-radio button", FALSE);
6962
6964
6965 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
6966 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6967 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
6968 ok(ret == BST_CHECKED, "got %08x\n", ret);
6969 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
6970 ok(ret == BST_UNCHECKED, "got %08x\n", ret);
6971
6973}
6974
6975#define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)
6976static void test_radio_dbg(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3, int line)
6977{
6978 DWORD ret;
6979
6980 ret = SendMessageA(radio1, BM_GETCHECK, 0, 0);
6981 ok_(__FILE__,line)(ret == state1 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret);
6982 ret = SendMessageA(radio2, BM_GETCHECK, 0, 0);
6983 ok_(__FILE__,line)(ret == state2 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret);
6984 ret = SendMessageA(radio3, BM_GETCHECK, 0, 0);
6985 ok_(__FILE__,line)(ret == state3 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret);
6986}
6987
6988static void set_radio(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3)
6989{
6990 SendMessageA(radio1, BM_SETCHECK, state1 ? BST_CHECKED : BST_UNCHECKED, 0);
6991 SendMessageA(radio2, BM_SETCHECK, state2 ? BST_CHECKED : BST_UNCHECKED, 0);
6992 SendMessageA(radio3, BM_SETCHECK, state3 ? BST_CHECKED : BST_UNCHECKED, 0);
6993}
6994
6996{
6997 HWND parent, radio1, radio2, radio3, hwnd;
6998 RECT rc;
6999 MSG msg;
7000 DWORD ret;
7001
7003
7004 parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc, 0);
7005 ok(parent != 0, "failed to create parent window\n");
7006
7007 radio1 = GetDlgItem(parent, ID_RADIO1);
7008 radio2 = GetDlgItem(parent, ID_RADIO2);
7009 radio3 = GetDlgItem(parent, ID_RADIO3);
7010
7011 flush_events();
7013
7014 test_radio(radio1, 0, radio2, 0, radio3, 0);
7015 set_radio(radio1, 1, radio2, 1, radio3, 1);
7016 test_radio(radio1, 1, radio2, 1, radio3, 1);
7017
7018 SetFocus(radio3);
7019
7020 flush_events();
7022
7024
7025 SendMessageA(radio3, WM_KEYDOWN, VK_UP, 0);
7026 SendMessageA(radio3, WM_KEYUP, VK_UP, 0);
7027 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7028 ok_sequence(auto_radio_button_VK_UP_child, "press/release VK_UP on auto-radio button", FALSE);
7029
7030 test_radio(radio1, 1, radio2, 1, radio3, 1);
7031
7032 flush_events();
7034
7037 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7038 ok_sequence(auto_radio_button_VK_UP_parent, "press/release VK_UP on dialog", FALSE);
7039
7040 test_radio(radio1, 1, radio2, 1, radio3, 1);
7041
7042 SetFocus(radio3);
7043 GetWindowRect(radio3, &rc);
7044
7045 flush_events();
7047
7048 msg.hwnd = parent;
7049 msg.message = WM_KEYDOWN;
7050 msg.wParam = VK_UP;
7051 msg.lParam = 0;
7052 msg.pt.x = rc.left + 1;
7053 msg.pt.y = rc.top + 1;
7055 ok(ret, "IsDialogMessage should return TRUE\n");
7056 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7057if (0) /* actual message sequence is different on every run in some Windows setups */
7058 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #1", FALSE);
7059 /* what really matters is that nothing has changed */
7060 test_radio(radio1, 1, radio2, 1, radio3, 1);
7061
7062 set_radio(radio1, 0, radio2, 1, radio3, 1);
7063 test_radio(radio1, 0, radio2, 1, radio3, 1);
7064
7065 flush_events();
7067
7069 ok(ret, "IsDialogMessage should return TRUE\n");
7070 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7071if (0) /* actual message sequence is different on every run in some Windows setups */
7072 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #2", FALSE);
7073 /* what really matters is that nothing has changed */
7074 test_radio(radio1, 0, radio2, 1, radio3, 1);
7075
7076 /* switch from radio3 ro radio1 */
7077 SetFocus(radio3);
7078 GetWindowRect(radio3, &rc);
7079
7080 flush_events();
7082
7083 msg.hwnd = parent;
7084 msg.message = WM_KEYDOWN;
7085 msg.wParam = VK_DOWN;
7086 msg.lParam = 0;
7087 msg.pt.x = rc.left + 1;
7088 msg.pt.y = rc.top + 1;
7090 ok(ret, "IsDialogMessage should return TRUE\n");
7091 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7092 ok_sequence(auto_radio_button_VK_DOWN_dialog, "IsDialogMessage(VK_DOWN)", TRUE);
7093
7094 test_radio(radio1, 1, radio2, 0, radio3, 0);
7095
7096 hwnd = GetFocus();
7097 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
7098 GetWindowRect(radio1, &rc);
7099
7100 msg.hwnd = parent;
7101 msg.message = WM_KEYDOWN;
7102 msg.wParam = VK_DOWN;
7103 msg.lParam = 0;
7104 msg.pt.x = rc.left + 1;
7105 msg.pt.y = rc.top + 1;
7107 ok(ret, "IsDialogMessage should return TRUE\n");
7108 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7110
7111 test_radio(radio1, 1, radio2, 0, radio3, 0);
7112
7113 hwnd = GetFocus();
7114 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
7115
7116 flush_events();
7118
7119 msg.hwnd = parent;
7120 msg.message = WM_KEYDOWN;
7121 msg.wParam = VK_UP;
7122 msg.lParam = 0;
7123 msg.pt.x = rc.left + 1;
7124 msg.pt.y = rc.top + 1;
7126 ok(ret, "IsDialogMessage should return TRUE\n");
7127 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7129
7130 test_radio(radio1, 1, radio2, 0, radio3, 0);
7131
7132 hwnd = GetFocus();
7133 ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
7134
7135 flush_events();
7137
7138 msg.hwnd = parent;
7139 msg.message = WM_KEYDOWN;
7140 msg.wParam = VK_UP;
7141 msg.lParam = 0;
7142 msg.pt.x = rc.left + 1;
7143 msg.pt.y = rc.top + 1;
7145 ok(ret, "IsDialogMessage should return TRUE\n");
7146 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
7147if (0) /* actual message sequence is different on every run in some Windows setups */
7148 ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #3", FALSE);
7149 /* what really matters is that nothing has changed */
7150 test_radio(radio1, 1, radio2, 0, radio3, 0);
7151
7153
7155}
7156
7157/****************** static message test *************************/
7158static const struct message WmSetFontStaticSeq2[] =
7159{
7160 { WM_SETFONT, sent },
7164 { 0 }
7165};
7166
7168
7170{
7171 static LONG defwndproc_counter = 0;
7172 LRESULT ret;
7173 struct recvd_message msg;
7174
7175 if (ignore_message( message )) return 0;
7176
7177 msg.hwnd = hwnd;
7178 msg.message = message;
7179 msg.flags = sent|wparam|lparam;
7180 if (defwndproc_counter) msg.flags |= defwinproc;
7181 msg.wParam = wParam;
7182 msg.lParam = lParam;
7183 msg.descr = "static";
7184 add_message(&msg);
7185
7186 defwndproc_counter++;
7188 defwndproc_counter--;
7189
7190 return ret;
7191}
7192
7193static void subclass_static(void)
7194{
7195 WNDCLASSA cls;
7196
7197 if (!GetClassInfoA(0, "static", &cls)) assert(0);
7198
7200
7203 cls.lpszClassName = "my_static_class";
7205 if (!RegisterClassA(&cls)) assert(0);
7206}
7207
7208static void test_static_messages(void)
7209{
7210 /* FIXME: make as comprehensive as the button message test */
7211 static const struct
7212 {
7213 DWORD style;
7214 DWORD dlg_code;
7215 const struct message *setfont;
7216 } static_ctrl[] = {
7219 };
7220 unsigned int i;
7221 HWND hwnd;
7222 DWORD dlg_code;
7223
7225
7226 for (i = 0; i < ARRAY_SIZE(static_ctrl); i++)
7227 {
7228 hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP,
7229 0, 0, 50, 14, 0, 0, 0, NULL);
7230 ok(hwnd != 0, "Failed to create static window\n");
7231
7232 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
7233 ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code);
7234
7237 SetFocus(0);
7239
7240 trace("static style %08x\n", static_ctrl[i].style);
7242 ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE);
7243
7245 }
7246}
7247
7248/****************** ComboBox message test *************************/
7249#define ID_COMBOBOX 0x000f
7250
7251static const struct message SetCurSelComboSeq[] =
7252{
7253 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7254 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7255 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 },
7256 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 },
7257 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 },
7258 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */
7259 { LB_GETTEXT, sent|wparam, 0 },
7261 { LB_GETITEMDATA, sent|wparam|lparam, 0, 0 },
7262 { WM_DRAWITEM, sent|wparam|lparam|parent, ID_COMBOBOX, 0x100010f3 },
7263 { 0 }
7264};
7265
7266static const struct message SetCurSelComboSeq2[] =
7267{
7268 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7269 { LB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7270 { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 },
7271 { LB_GETCURSEL, sent|wparam|lparam, 0, 0 },
7272 { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 },
7273 { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */
7274 { LB_GETTEXT, sent|wparam, 0 },
7275 { 0 }
7276};
7277
7278static const struct message SetCurSelComboSeq_edit[] =
7279{
7280 { CB_SETCURSEL, sent|wparam|lparam, 0, 0 },
7281 { WM_SETTEXT, sent|wparam, 0 },
7283 { 0 }
7284};
7285
7286static const struct message WmKeyDownComboSeq[] =
7287{
7294 { 0 }
7295};
7296
7297static const struct message WmSetPosComboSeq[] =
7298{
7303 { WM_MOVE, sent|defwinproc },
7309 { 0 }
7310};
7311
7312static const struct message WMSetFocusComboBoxSeq[] =
7313{
7314 { WM_SETFOCUS, sent },
7316 { WM_SETFOCUS, sent },
7319 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */
7320 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */
7322 { 0 }
7323};
7324
7325static const struct message SetFocusButtonSeq[] =
7326{
7327 { WM_KILLFOCUS, sent },
7328 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */
7329 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */
7333 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */
7334 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */
7337 { 0 }
7338};
7339
7340static const struct message SetFocusComboBoxSeq[] =
7341{
7343 { WM_SETFOCUS, sent },
7345 { WM_SETFOCUS, sent },
7348 { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */
7349 { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */
7351 { 0 }
7352};
7353
7354static const struct message SetFocusButtonSeq2[] =
7355{
7356 { WM_KILLFOCUS, sent },
7357 { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */
7358 { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */
7366 { 0 }
7367};
7368
7370
7373{
7374 static LONG defwndproc_counter = 0;
7375 LRESULT ret;
7376 struct recvd_message msg;
7377
7378 /* do not log painting messages */
7379 if (message != WM_PAINT &&
7380 message != WM_NCPAINT &&
7381 message != WM_SYNCPAINT &&
7383 message != WM_NCHITTEST &&
7384 message != WM_GETTEXT &&
7386 {
7387 msg.hwnd = hwnd;
7388 msg.message = message;
7389 msg.flags = sent|wparam|lparam;
7390 if (defwndproc_counter) msg.flags |= defwinproc;
7391 msg.wParam = wParam;
7392 msg.lParam = lParam;
7393 msg.descr = "combo edit";
7394 add_message(&msg);
7395 }
7396
7397 defwndproc_counter++;
7399 defwndproc_counter--;
7400
7401 return ret;
7402}
7403
7406{
7407 static LONG defwndproc_counter = 0;
7408 LRESULT ret;
7409 struct recvd_message msg;
7410
7411 /* do not log painting messages */
7412 if (message != WM_PAINT &&
7413 message != WM_NCPAINT &&
7414 message != WM_SYNCPAINT &&
7416 message != WM_NCHITTEST &&
7418 {
7419 msg.hwnd = hwnd;
7420 msg.message = message;
7421 msg.flags = sent|wparam|lparam;
7422 if (defwndproc_counter) msg.flags |= defwinproc;
7423 msg.wParam = wParam;
7424 msg.lParam = lParam;
7425 msg.descr = "combo lbox";
7426 add_message(&msg);
7427 }
7428
7429 defwndproc_counter++;
7431 defwndproc_counter--;
7432
7433 return ret;
7434}
7435
7437{
7438 static LONG defwndproc_counter = 0;
7439 LRESULT ret;
7440 struct recvd_message msg;
7441
7442 /* do not log painting messages */
7443 if (message != WM_PAINT &&
7444 message != WM_NCPAINT &&
7445 message != WM_SYNCPAINT &&
7447 message != WM_NCHITTEST &&
7448 message != WM_GETTEXT &&
7450 {
7451 msg.hwnd = hwnd;
7452 msg.message = message;
7453 msg.flags = sent|wparam|lparam;
7454 if (defwndproc_counter) msg.flags |= defwinproc;
7455 msg.wParam = wParam;
7456 msg.lParam = lParam;
7457 msg.descr = "combo";
7458 add_message(&msg);
7459 }
7460
7461 defwndproc_counter++;
7463 defwndproc_counter--;
7464
7465 return ret;
7466}
7467
7468static void subclass_combobox(void)
7469{
7470 WNDCLASSA cls;
7471
7472 if (!GetClassInfoA(0, "ComboBox", &cls)) assert(0);
7473
7475
7478 cls.lpszClassName = "my_combobox_class";
7480 if (!RegisterClassA(&cls)) assert(0);
7481}
7482
7483static void test_combobox_messages(void)
7484{
7485 HWND parent, combo, button, edit, lbox;
7486 LRESULT ret;
7487 COMBOBOXINFO cbInfo;
7488 BOOL res;
7489
7491
7492 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7493 100, 100, 200, 200, 0, 0, 0, NULL);
7494 ok(parent != 0, "Failed to create parent window\n");
7496
7497 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
7498 0, 0, 100, 150, parent, (HMENU)ID_COMBOBOX, 0, NULL);
7499 ok(combo != 0, "Failed to create combobox window\n");
7500
7501 UpdateWindow(combo);
7502
7503 ret = SendMessageA(combo, WM_GETDLGCODE, 0, 0);
7504 ok(ret == (DLGC_WANTCHARS | DLGC_WANTARROWS), "wrong dlg_code %08lx\n", ret);
7505
7506 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0");
7507 ok(ret == 0, "expected 0, got %ld\n", ret);
7508 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 1");
7509 ok(ret == 1, "expected 1, got %ld\n", ret);
7510 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 2");
7511 ok(ret == 2, "expected 2, got %ld\n", ret);
7512
7513 SendMessageA(combo, CB_SETCURSEL, 0, 0);
7514 SetFocus(combo);
7516
7518 SendMessageA(combo, WM_KEYDOWN, VK_DOWN, 0);
7519 SendMessageA(combo, WM_KEYUP, VK_DOWN, 0);
7521 ok_sequence(WmKeyDownComboSeq, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE);
7522
7524 SetWindowPos(combo, 0, 10, 10, 120, 130, SWP_NOZORDER);
7525 ok_sequence(WmSetPosComboSeq, "repositioning messages on a ComboBox", FALSE);
7526
7527 DestroyWindow(combo);
7529
7530 /* Start again. Test combobox text selection when getting and losing focus */
7531 parent = CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7532 10, 10, 300, 300, NULL, NULL, NULL, NULL);
7533 ok(parent != 0, "Failed to create parent window\n");
7534
7535 combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
7536 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL);
7537 ok(combo != 0, "Failed to create combobox window\n");
7538
7539 cbInfo.cbSize = sizeof(COMBOBOXINFO);
7540 SetLastError(0xdeadbeef);
7541 res = GetComboBoxInfo(combo, &cbInfo);
7542 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError());
7543 edit = cbInfo.hwndItem;
7544
7547
7549 5, 50, 100, 20, parent, NULL,
7551 ok(button != 0, "Failed to create button window\n");
7552
7555 SendMessageA(combo, WM_SETFOCUS, 0, (LPARAM)edit);
7557 ok_sequence(WMSetFocusComboBoxSeq, "WM_SETFOCUS on a ComboBox", TRUE);
7558
7563 ok_sequence(SetFocusButtonSeq, "SetFocus on a Button", TRUE);
7564
7565 SendMessageA(combo, WM_SETTEXT, 0, (LPARAM)"Wine Test");
7566
7569 SetFocus(combo);
7571 ok_sequence(SetFocusComboBoxSeq, "SetFocus on a ComboBox", TRUE);
7572
7577 ok_sequence(SetFocusButtonSeq2, "SetFocus on a Button (2)", TRUE);
7578
7579 SetFocus(combo);
7580 SendMessageA(combo, WM_SETREDRAW, FALSE, 0);
7583 SendMessageA(combo, CB_SETCURSEL, 0, 0);
7585 ok_sequence(SetCurSelComboSeq_edit, "CB_SETCURSEL on a ComboBox with edit control", FALSE);
7586
7588 DestroyWindow(combo);
7589
7590 combo = CreateWindowExA(0, "my_combobox_class", "test",
7592 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL);
7593 ok(combo != 0, "Failed to create combobox window\n");
7594
7595 ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0");
7596 ok(ret == 0, "expected 0, got %ld\n", ret);
7597
7598 cbInfo.cbSize = sizeof(COMBOBOXINFO);
7599 SetLastError(0xdeadbeef);
7600 res = GetComboBoxInfo(combo, &cbInfo);
7601 ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError());
7602 lbox = cbInfo.hwndList;
7606
7608 SendMessageA(combo, CB_SETCURSEL, 0, 0);
7610 ok_sequence(SetCurSelComboSeq, "CB_SETCURSEL on a ComboBox", FALSE);
7611
7612 ShowWindow(combo, SW_HIDE);
7615 SendMessageA(combo, CB_SETCURSEL, 0, 0);
7617 ok_sequence(SetCurSelComboSeq2, "CB_SETCURSEL on a ComboBox", FALSE);
7618
7619 DestroyWindow(combo);
7621}
7622
7623/****************** WM_IME_KEYDOWN message test *******************/
7624
7625static const struct message WmImeKeydownMsgSeq_0[] =
7626{
7628 { WM_CHAR, wparam, 'A' },
7629 { 0 }
7630};
7631
7632static const struct message WmImeKeydownMsgSeq_1[] =
7633{
7636 { 0 }
7637};
7638
7640{
7641 struct recvd_message msg;
7642
7643 msg.hwnd = hwnd;
7644 msg.message = message;
7645 msg.flags = wparam|lparam;
7646 msg.wParam = wParam;
7647 msg.lParam = lParam;
7648 msg.descr = "wmime_keydown";
7649 add_message(&msg);
7650
7652}
7653
7655{
7656 WNDCLASSA cls;
7657
7658 ZeroMemory(&cls, sizeof(WNDCLASSA));
7660 cls.hInstance = GetModuleHandleA(0);
7661 cls.lpszClassName = "wmime_keydown_class";
7662 if (!RegisterClassA(&cls)) assert(0);
7663}
7664
7666{
7667 HWND hwnd;
7668 MSG msg;
7669
7670 trace("Message sequences by WM_IME_KEYDOWN\n");
7671
7673 hwnd = CreateWindowExA(0, "wmime_keydown_class", NULL, WS_OVERLAPPEDWINDOW,
7674 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
7675 NULL, NULL, 0);
7676 flush_events();
7678
7680 SendMessageA(hwnd, WM_CHAR, 'A', 1);
7681 ok_sequence(WmImeKeydownMsgSeq_0, "WM_IME_KEYDOWN 0", FALSE);
7682
7683 while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) )
7684 {
7687 }
7688 ok_sequence(WmImeKeydownMsgSeq_1, "WM_IME_KEYDOWN 1", FALSE);
7689
7691}
7692
7693/************* painting message test ********************/
7694
7696{
7697 DWORD i, size;
7698 RGNDATA *data = NULL;
7699 RECT *rect;
7700
7701 if (!hrgn)
7702 {
7703 printf( "null region\n" );
7704 return;
7705 }
7706 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
7707 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
7709 printf("%d rects:", data->rdh.nCount );
7710 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
7711 printf( " %s", wine_dbgstr_rect( rect ));
7712 printf("\n");
7713 HeapFree( GetProcessHeap(), 0, data );
7714}
7715
7716#define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn )
7717static void check_update_rgn_( int line, HWND hwnd, HRGN hrgn )
7718{
7719 INT ret;
7720 RECT r1, r2;
7721 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
7722 HRGN update = CreateRectRgn( 0, 0, 0, 0 );
7723
7724 ret = GetUpdateRgn( hwnd, update, FALSE );
7725 ok( ret != ERROR, "GetUpdateRgn failed\n" );
7726 if (ret == NULLREGION)
7727 {
7728 ok_(__FILE__,line)( !hrgn, "Update region shouldn't be empty\n" );
7729 }
7730 else
7731 {
7732 if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
7733 {
7734 ok_(__FILE__,line)( 0, "Regions are different\n" );
7735 if (winetest_debug > 0)
7736 {
7737 printf( "Update region: " );
7738 dump_region( update );
7739 printf( "Wanted region: " );
7740 dump_region( hrgn );
7741 }
7742 }
7743 }
7744 GetRgnBox( update, &r1 );
7745 GetUpdateRect( hwnd, &r2, FALSE );
7746 ok_(__FILE__,line)( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n",
7748
7749 DeleteObject( tmp );
7750 DeleteObject( update );
7751}
7752
7753static const struct message WmInvalidateRgn[] = {
7754 { WM_NCPAINT, sent },
7756 { 0 }
7757};
7758
7759static const struct message WmGetUpdateRect[] = {
7760 { WM_NCPAINT, sent },
7762 { WM_PAINT, sent },
7763 { 0 }
7764};
7765
7766static const struct message WmInvalidateFull[] = {
7767 { WM_NCPAINT, sent|wparam, 1 },
7769 { 0 }
7770};
7771
7772static const struct message WmInvalidateErase[] = {
7773 { WM_NCPAINT, sent|wparam, 1 },
7775 { WM_ERASEBKGND, sent },
7776 { 0 }
7777};
7778
7779static const struct message WmInvalidatePaint[] = {
7780 { WM_PAINT, sent },
7783 { 0 }
7784};
7785
7786static const struct message WmInvalidateErasePaint[] = {
7787 { WM_PAINT, sent },
7791 { 0 }
7792};
7793
7794static const struct message WmInvalidateErasePaint2[] = {
7795 { WM_PAINT, sent },
7799 { 0 }
7800};
7801
7802static const struct message WmErase[] = {
7803 { WM_ERASEBKGND, sent },
7804 { 0 }
7805};
7806
7807static const struct message WmPaint[] = {
7808 { WM_PAINT, sent },
7809 { 0 }
7810};
7811
7812static const struct message WmParentOnlyPaint[] = {
7813 { WM_PAINT, sent|parent },
7814 { 0 }
7815};
7816
7817static const struct message WmInvalidateParent[] = {
7818 { WM_NCPAINT, sent|parent },
7821 { 0 }
7822};
7823
7824static const struct message WmInvalidateParentChild[] = {
7825 { WM_NCPAINT, sent|parent },
7828 { WM_NCPAINT, sent },
7830 { WM_ERASEBKGND, sent },
7831 { 0 }
7832};
7833
7834static const struct message WmInvalidateParentChild2[] = {
7836 { WM_NCPAINT, sent },
7838 { WM_ERASEBKGND, sent },
7839 { 0 }
7840};
7841
7842static const struct message WmParentPaint[] = {
7843 { WM_PAINT, sent|parent },
7844 { WM_PAINT, sent },
7845 { 0 }
7846};
7847
7848static const struct message WmParentPaintNc[] = {
7849 { WM_PAINT, sent|parent },
7850 { WM_PAINT, sent },
7854 { 0 }
7855};
7856
7857static const struct message WmChildPaintNc[] = {
7858 { WM_PAINT, sent },
7862 { 0 }
7863};
7864
7865static const struct message WmParentErasePaint[] = {
7866 { WM_PAINT, sent|parent },
7870 { WM_PAINT, sent },
7874 { 0 }
7875};
7876
7877static const struct message WmParentOnlyNcPaint[] = {
7878 { WM_PAINT, sent|parent },
7881 { 0 }
7882};
7883
7884static const struct message WmSetParentStyle[] = {
7885 { WM_STYLECHANGING, sent|parent },
7886 { WM_STYLECHANGED, sent|parent },
7887 { 0 }
7888};
7889
7890static void test_paint_messages(void)
7891{
7892 BOOL ret;
7893 RECT rect, rect2;
7894 POINT pt;
7895 MSG msg;
7896 HWND hparent, hchild;
7897 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
7898 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
7899 HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
7900 100, 100, 200, 200, 0, 0, 0, NULL);
7901 ok (hwnd != 0, "Failed to create overlapped window\n");
7902
7904 UpdateWindow( hwnd );
7905 flush_events();
7907
7908 check_update_rgn( hwnd, 0 );
7909 SetRectRgn( hrgn, 10, 10, 20, 20 );
7911 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
7913 SetRectRgn( hrgn2, 20, 20, 30, 30 );
7915 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
7918 /* validate everything */
7920 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
7921 check_update_rgn( hwnd, 0 );
7922
7923 /* test empty region */
7924 SetRectRgn( hrgn, 10, 10, 10, 15 );
7926 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
7927 check_update_rgn( hwnd, 0 );
7928 /* test empty rect */
7929 SetRect( &rect, 10, 10, 10, 15 );
7931 ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
7932 check_update_rgn( hwnd, 0 );
7933
7934 /* flush pending messages */
7935 flush_events();
7937
7938 GetClientRect( hwnd, &rect );
7939 SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top );
7940 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
7941 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
7942 */
7943 SetRectEmpty( &rect );
7944 ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) failed\n");
7946 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
7947 flush_events();
7948 ok_sequence( WmPaint, "Paint", FALSE );
7950 check_update_rgn( hwnd, 0 );
7951
7952 SetRectEmpty( &rect );
7954 "RedrawWindow failed\n");
7955 check_update_rgn( hwnd, 0 );
7956
7957 SetRectEmpty( &rect );
7959 "RedrawWindow failed\n");
7960 check_update_rgn( hwnd, 0 );
7961
7962 GetWindowRect( hwnd, &rect );
7964 "RedrawWindow failed\n");
7965 check_update_rgn( hwnd, 0 );
7966
7967 flush_events();
7969 "RedrawWindow failed\n");
7971 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
7972 flush_events();
7973 ok_sequence( WmPaint, "Paint", FALSE );
7975 check_update_rgn( hwnd, 0 );
7976
7979 "RedrawWindow failed\n");
7981 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */
7982 "region should be null (%d)\n", ret );
7983 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
7985 flush_events();
7986
7989 "RedrawWindow failed\n");
7991 ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */
7992 "region should be null (%d)\n", ret );
7993 if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
7995 flush_events();
7996
7997 SetRectRgn( hrgn2, rect.left, rect.top, rect.right, rect.bottom );
7999 "RedrawWindow failed\n");
8001 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8002 flush_events();
8003 ok_sequence( WmPaint, "Paint", FALSE );
8005 check_update_rgn( hwnd, 0 );
8006
8008 "RedrawWindow failed\n");
8009 check_update_rgn( hwnd, 0 );
8010
8012 "RedrawWindow failed\n");
8014 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8015 flush_events();
8016 ok_sequence( WmPaint, "Paint", FALSE );
8018 check_update_rgn( hwnd, 0 );
8019
8020 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
8021 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8022 */
8023 SetRectEmpty( &rect );
8024 if (ValidateRect(0, &rect) && /* not supported on Win9x */
8025 GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */
8026 {
8028 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8029 flush_events();
8030 ok_sequence( WmPaint, "Paint", FALSE );
8032 check_update_rgn( hwnd, 0 );
8033 }
8034
8035 SetLastError(0xdeadbeef);
8036 ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n");
8038 "wrong error code %d\n", GetLastError());
8039 check_update_rgn( hwnd, 0 );
8040 flush_events();
8041 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
8042
8043 SetLastError(0xdeadbeef);
8044 ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n");
8046 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8047 "wrong error code %d\n", GetLastError());
8048 check_update_rgn( hwnd, 0 );
8049 flush_events();
8050 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
8051
8052 SetLastError(0xdeadbeef);
8053 ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n");
8055 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8056 "wrong error code %d\n", GetLastError());
8057 check_update_rgn( hwnd, 0 );
8058 flush_events();
8059 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
8060
8061 /* now with frame */
8062 SetRectRgn( hrgn, -5, -5, 20, 20 );
8063
8064 /* flush pending messages */
8065 flush_events();
8068 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
8069
8070 SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
8072
8075 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
8076
8079 ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
8080
8081 GetClientRect( hwnd, &rect );
8082 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
8084
8087 ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
8088
8091 ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE );
8092 check_update_rgn( hwnd, 0 );
8093
8096 ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE );
8097 check_update_rgn( hwnd, 0 );
8098
8100 SetRectRgn( hrgn, 0, 0, 100, 100 );
8102 SetRectRgn( hrgn, 0, 0, 50, 100 );
8104 SetRectRgn( hrgn, 50, 0, 100, 100 );
8107 ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */
8108 check_update_rgn( hwnd, 0 );
8109
8111 SetRectRgn( hrgn, 0, 0, 100, 100 );
8113 SetRectRgn( hrgn, 0, 0, 100, 50 );
8115 ok_sequence( WmErase, "Erase", FALSE );
8116 SetRectRgn( hrgn, 0, 50, 100, 100 );
8118
8120 SetRectRgn( hrgn, 0, 0, 100, 100 );
8122 SetRectRgn( hrgn, 0, 0, 50, 50 );
8124 ok_sequence( WmPaint, "Paint", FALSE );
8125
8127 SetRectRgn( hrgn, -4, -4, -2, -2 );
8129 SetRectRgn( hrgn, -200, -200, -198, -198 );
8131 ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
8132
8134 SetRectRgn( hrgn, -4, -4, -2, -2 );
8136 SetRectRgn( hrgn, -4, -4, -3, -3 );
8138 SetRectRgn( hrgn, 0, 0, 1, 1 );
8140 ok_sequence( WmPaint, "Paint", FALSE );
8141
8143 SetRectRgn( hrgn, -4, -4, -1, -1 );
8146 /* make sure no WM_PAINT was generated */
8147 flush_events();
8148 ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
8149
8151 SetRectRgn( hrgn, -4, -4, -1, -1 );
8153 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
8154 {
8155 if (msg.hwnd == hwnd && msg.message == WM_PAINT)
8156 {
8157 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
8159 ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret );
8161 ok( ret, "Invalid GetUpdateRect result %d\n", ret );
8162 /* this will send WM_NCPAINT and validate the non client area */
8163 ret = GetUpdateRect( hwnd, &rect, TRUE );
8164 ok( !ret, "Invalid GetUpdateRect result %d\n", ret );
8165 }
8167 }
8168 ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
8169
8171
8172 /* now test with a child window */
8173
8174 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
8175 100, 100, 200, 200, 0, 0, 0, NULL);
8176 ok (hparent != 0, "Failed to create parent window\n");
8177
8178 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER,
8179 10, 10, 100, 100, hparent, 0, 0, NULL);
8180 ok (hchild != 0, "Failed to create child window\n");
8181
8182 ShowWindow( hparent, SW_SHOW );
8183 UpdateWindow( hparent );
8184 UpdateWindow( hchild );
8185 flush_events();
8188
8189 SetRect( &rect, 0, 0, 50, 50 );
8190 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8192 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
8193
8194 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8195 pt.x = pt.y = 0;
8196 MapWindowPoints( hchild, hparent, &pt, 1 );
8197 SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y );
8198 check_update_rgn( hchild, hrgn );
8199 SetRectRgn( hrgn, 0, 0, 50, 50 );
8200 check_update_rgn( hparent, hrgn );
8201 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
8202 ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE );
8203 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
8204 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
8205
8206 flush_events();
8207 ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
8208
8210 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
8211 ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE );
8212 RedrawWindow( hchild, NULL, 0, RDW_ERASENOW );
8213 ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
8214
8215 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
8217 ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
8218
8222 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
8223 ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
8224
8225 /* flush all paint messages */
8226 flush_events();
8228
8229 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
8231 SetRectRgn( hrgn, 0, 0, 50, 50 );
8232 check_update_rgn( hparent, hrgn );
8233 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
8234 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8235 SetRectRgn( hrgn, 0, 0, 50, 50 );
8236 check_update_rgn( hparent, hrgn );
8237
8238 /* flush all paint messages */
8239 flush_events();
8242
8243 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
8244 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8245 SetRectRgn( hrgn, 0, 0, 50, 50 );
8246 check_update_rgn( hparent, hrgn );
8247 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
8248 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8249 SetRectRgn( hrgn2, 10, 10, 50, 50 );
8251 check_update_rgn( hparent, hrgn );
8252 /* flush all paint messages */
8253 flush_events();
8255
8256 /* same as above but parent gets completely validated */
8257 SetRect( &rect, 20, 20, 30, 30 );
8258 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8259 SetRectRgn( hrgn, 20, 20, 30, 30 );
8260 check_update_rgn( hparent, hrgn );
8261 RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW );
8262 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8263 check_update_rgn( hparent, 0 ); /* no update region */
8264 flush_events();
8265 ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
8266
8267 /* make sure RDW_VALIDATE on child doesn't have the same effect */
8269 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8270 SetRectRgn( hrgn, 20, 20, 30, 30 );
8271 check_update_rgn( hparent, hrgn );
8272 RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE );
8273 SetRectRgn( hrgn, 20, 20, 30, 30 );
8274 check_update_rgn( hparent, hrgn );
8275
8276 /* same as above but normal WM_PAINT doesn't validate parent */
8278 SetRect( &rect, 20, 20, 30, 30 );
8279 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8280 SetRectRgn( hrgn, 20, 20, 30, 30 );
8281 check_update_rgn( hparent, hrgn );
8282 /* no WM_PAINT in child while parent still pending */
8283 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8284 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
8285 while (PeekMessageA( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8286 ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
8287
8289 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
8290 /* no WM_PAINT in child while parent still pending */
8291 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8292 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
8294 /* now that parent is valid child should get WM_PAINT */
8295 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8296 ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE );
8297 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8298 ok_sequence( WmEmptySeq, "No other message", FALSE );
8299
8300 /* same thing with WS_CLIPCHILDREN in parent */
8303 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
8304 /* changing style invalidates non client area, but we need to invalidate something else to see it */
8305 RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW );
8306 ok_sequence( WmEmptySeq, "No message", FALSE );
8307 RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW );
8308 ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
8309
8312 SetRectRgn( hrgn, 20, 20, 30, 30 );
8313 check_update_rgn( hparent, hrgn );
8314 /* no WM_PAINT in child while parent still pending */
8315 while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8316 ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE );
8317 /* WM_PAINT in parent first */
8318 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
8319 ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
8320
8321 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
8323 SetRect( &rect, 0, 0, 30, 30 );
8325 SetRectRgn( hrgn, 0, 0, 30, 30 );
8326 check_update_rgn( hparent, hrgn );
8327 flush_events();
8328 ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
8329
8330 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8332 SetRect( &rect, -10, 0, 30, 30 );
8334 SetRect( &rect, 0, 0, 20, 20 );
8335 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
8336 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
8337 ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
8338
8339 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8341 SetRect( &rect, -10, 0, 30, 30 );
8343 SetRect( &rect, 0, 0, 100, 100 );
8344 RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN );
8345 RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW );
8346 ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE );
8347 RedrawWindow( hparent, NULL, 0, RDW_ERASENOW );
8348 ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
8349
8350 /* WS_CLIPCHILDREN doesn't exclude children from update region */
8353 GetClientRect( hparent, &rect );
8354 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
8355 check_update_rgn( hparent, hrgn );
8356 flush_events();
8357
8359 GetClientRect( hparent, &rect );
8360 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
8361 check_update_rgn( hparent, hrgn );
8362 flush_events();
8363
8364 /* test RDW_INTERNALPAINT behavior */
8365
8368 flush_events();
8369 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
8370
8372 flush_events();
8373 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
8374
8375 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
8376 flush_events();
8377 ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
8378
8380 UpdateWindow( hparent );
8381 flush_events();
8383 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
8385 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
8387 flush_events();
8388 ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
8389
8390 UpdateWindow( hparent );
8391 flush_events();
8393 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
8395 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
8397 flush_events();
8398 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
8399
8401 ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
8402 RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
8403 flush_events();
8404 ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
8405
8407 UpdateWindow( hparent );
8408 flush_events();
8410 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
8412 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
8414 flush_events();
8415 ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
8416
8417 UpdateWindow( hparent );
8418 flush_events();
8420 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
8422 SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
8424 flush_events();
8425 ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
8426
8427 ok(GetWindowLongA( hparent, GWL_STYLE ) & WS_VISIBLE, "parent should be visible\n");
8428 ok(GetWindowLongA( hchild, GWL_STYLE ) & WS_VISIBLE, "child should be visible\n");
8429
8430 UpdateWindow( hparent );
8431 flush_events();
8433 trace("testing SetWindowPos(-10000, -10000) on child\n");
8434 SetWindowPos( hchild, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER );
8435 check_update_rgn( hchild, 0 );
8436 flush_events();
8437
8438#if 0 /* this one doesn't pass under Wine yet */
8439 UpdateWindow( hparent );
8440 flush_events();
8442 trace("testing ShowWindow(SW_MINIMIZE) on child\n");
8443 ShowWindow( hchild, SW_MINIMIZE );
8444 check_update_rgn( hchild, 0 );
8445 flush_events();
8446#endif
8447
8448 UpdateWindow( hparent );
8449 flush_events();
8451 trace("testing SetWindowPos(-10000, -10000) on parent\n");
8452 SetWindowPos( hparent, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER );
8453 check_update_rgn( hparent, 0 );
8454 flush_events();
8455
8457 DestroyWindow( hparent );
8458 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
8459
8460 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
8461
8462 hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE,
8463 100, 100, 200, 200, 0, 0, 0, NULL);
8464 ok (hparent != 0, "Failed to create parent window\n");
8465
8466 hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
8467 10, 10, 100, 100, hparent, 0, 0, NULL);
8468 ok (hchild != 0, "Failed to create child window\n");
8469
8470 ShowWindow( hparent, SW_SHOW );
8471 UpdateWindow( hparent );
8472 UpdateWindow( hchild );
8473 flush_events();
8475
8476 /* moving child outside of parent boundaries changes update region */
8477 SetRect( &rect, 0, 0, 40, 40 );
8478 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
8479 SetRectRgn( hrgn, 0, 0, 40, 40 );
8480 check_update_rgn( hchild, hrgn );
8481 MoveWindow( hchild, -10, 10, 100, 100, FALSE );
8482 SetRectRgn( hrgn, 10, 0, 40, 40 );
8483 check_update_rgn( hchild, hrgn );
8484 MoveWindow( hchild, -10, -10, 100, 100, FALSE );
8485 SetRectRgn( hrgn, 10, 10, 40, 40 );
8486 check_update_rgn( hchild, hrgn );
8487
8488 /* moving parent off-screen does too */
8489 SetRect( &rect, 0, 0, 100, 100 );
8491 SetRectRgn( hrgn, 0, 0, 100, 100 );
8492 check_update_rgn( hparent, hrgn );
8493 SetRectRgn( hrgn, 10, 10, 40, 40 );
8494 check_update_rgn( hchild, hrgn );
8495 MoveWindow( hparent, -20, -20, 200, 200, FALSE );
8496 GetUpdateRect( hparent, &rect2, FALSE );
8497 if (!EqualRect( &rect2, &rect )) /* Win 8 and later don't crop update to screen */
8498 {
8499 rect.left += 20;
8500 rect.top += 20;
8501 }
8502 SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
8503 check_update_rgn( hparent, hrgn );
8504 SetRectRgn( hrgn, rect.left + 10, rect.top + 10, 40, 40 );
8505 check_update_rgn( hchild, hrgn );
8506
8507 /* invalidated region is cropped by the parent rects */
8508 SetRect( &rect, 0, 0, 50, 50 );
8509 RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
8510 SetRectRgn( hrgn, rect2.left + 10, rect2.top + 10, 50, 50 );
8511 check_update_rgn( hchild, hrgn );
8512
8513 DestroyWindow( hparent );
8514 ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
8516
8517 DeleteObject( hrgn );
8519}
8520
8521struct wnd_event
8522{
8523 HWND hwnd;
8527};
8528
8530{
8531 MSG msg;
8532 struct wnd_event *wnd_event = param;
8533
8534 wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW,
8535 100, 100, 200, 200, 0, 0, 0, NULL);
8536 ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
8537
8539
8540 while (GetMessageA(&msg, 0, 0, 0))
8541 {
8544 }
8545
8546 ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
8547
8548 return 0;
8549}
8550
8552{
8553 struct wnd_event *wnd_event = param;
8554 HWND hchild;
8555 MSG msg;
8556
8557 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
8558 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL);
8559 ok (hchild != 0, "Failed to create child window\n");
8560 flush_events();
8563
8564 for (;;)
8565 {
8567 if (!IsWindow( hchild )) break; /* will be destroyed when parent thread exits */
8568 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8569 }
8570 return 0;
8571}
8572
8574{
8575 struct wnd_event *wnd_event = param;
8576 struct wnd_event child_event;
8577 DWORD ret, tid;
8578 MSG msg;
8579
8580 child_event.hwnd = CreateWindowExA(0, "TestWindowClass", "Test child",
8581 WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL);
8582 ok (child_event.hwnd != 0, "Failed to create child window\n");
8583 SetFocus( child_event.hwnd );
8584 flush_events();
8586 child_event.start_event = wnd_event->start_event;
8588 for (;;)
8589 {
8591 if (ret != 1) break;
8592 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8593 }
8595 ok( !ret, "WaitForSingleObject failed %x\n", ret );
8596 return 0;
8597}
8598
8599static const char manifest_dep[] =
8600"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
8601"<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
8602" <file name=\"testdep.dll\" />"
8603"</assembly>";
8604
8605static const char manifest_main[] =
8606"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
8607"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
8608"<dependency>"
8609" <dependentAssembly>"
8610" <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
8611" </dependentAssembly>"
8612"</dependency>"
8613"</assembly>";
8614
8615static void create_manifest_file(const char *filename, const char *manifest)
8616{
8618 HANDLE file;
8619 DWORD size;
8620
8623 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
8626}
8627
8628static HANDLE test_create(const char *file)
8629{
8631 ACTCTXW actctx;
8632 HANDLE handle;
8633
8635 memset(&actctx, 0, sizeof(ACTCTXW));
8636 actctx.cbSize = sizeof(ACTCTXW);
8637 actctx.lpSource = path;
8638
8639 handle = pCreateActCtxW(&actctx);
8640 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
8641
8642 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
8643 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
8644 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
8645 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
8646 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
8647 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
8648 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
8649 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
8650 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
8651
8652 return handle;
8653}
8654
8656{
8659 DWORD tid;
8660 WNDPROC proc;
8661 MSG msg;
8662 char buf[256];
8663 int len, expected_len;
8664 struct wnd_event wnd_event;
8665 BOOL ret;
8666
8669 {
8670 win_skip("skipping interthread message test under win9x\n");
8671 return;
8672 }
8673
8675 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
8676
8677 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8678
8680
8681 SetLastError(0xdeadbeef);
8682 ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n");
8683 ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef,
8684 "wrong error code %d\n", GetLastError());
8685
8687 ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
8688
8689 expected_len = lstrlenA("window caption text");
8690 memset(buf, 0, sizeof(buf));
8691 SetLastError(0xdeadbeef);
8693 ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len, expected_len);
8694 ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
8695
8696 msg.hwnd = wnd_event.hwnd;
8697 msg.message = WM_GETTEXT;
8698 msg.wParam = sizeof(buf);
8699 msg.lParam = (LPARAM)buf;
8700 memset(buf, 0, sizeof(buf));
8701 SetLastError(0xdeadbeef);
8703 ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */
8704 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len, GetLastError());
8705
8706 /* the following test causes an exception in user.exe under win9x */
8707 msg.hwnd = wnd_event.hwnd;
8708 msg.message = WM_TIMER;
8709 msg.wParam = 0;
8711 SetLastError(0xdeadbeef);
8713 ok(!len && GetLastError() == 0xdeadbeef,
8714 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len, GetLastError());
8715
8717 ok( ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
8718
8719 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8721
8722 ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
8723
8724 wnd_event.hwnd = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8725 100, 100, 200, 200, 0, 0, 0, NULL);
8726 ok (wnd_event.hwnd != 0, "Failed to create parent window\n");
8727 flush_events();
8733 for (;;)
8734 {
8736 if (ret != 1) break;
8737 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8738 }
8739 ok( !ret, "MsgWaitForMultipleObjects failed %x\n", ret );
8740 /* now wait for the thread without processing messages; this shouldn't deadlock */
8742 ret = WaitForSingleObject( hThread, 5000 );
8743 ok( !ret, "WaitForSingleObject failed %x\n", ret );
8745
8747 ok( !ret, "WaitForSingleObject failed %x\n", ret );
8749
8752 flush_events();
8753 ok_sequence(WmExitThreadSeq, "destroy child on thread exit", FALSE);
8756
8757 /* activation context tests */
8758 if (!pActivateActCtx)
8759 {
8760 win_skip("Activation contexts are not supported, skipping\n");
8761 return;
8762 }
8763
8764 create_manifest_file("testdep1.manifest", manifest_dep);
8765 create_manifest_file("main.manifest", manifest_main);
8766
8767 context = test_create("main.manifest");
8768 DeleteFileA("testdep1.manifest");
8769 DeleteFileA("main.manifest");
8770
8771 handle = (void*)0xdeadbeef;
8772 ret = pGetCurrentActCtx(&handle);
8773 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError());
8774 ok(handle == 0, "active context %p\n", handle);
8775
8778 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
8779 ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8781
8782 /* context is activated after thread creation, so it doesn't inherit it by default */
8783 ret = pActivateActCtx(context, &cookie);
8784 ok(ret, "activation failed: %u\n", GetLastError());
8785
8786 handle = 0;
8787 ret = pGetCurrentActCtx(&handle);
8788 ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError());
8789 ok(handle != 0, "active context %p\n", handle);
8790 pReleaseActCtx(handle);
8791
8792 /* destination window will test for active context */
8793 ret = SendMessageA(wnd_event.hwnd, WM_USER+10, 0, 0);
8794 ok(ret, "thread window returned %d\n", ret);
8795
8796 event = CreateEventW(NULL, 0, 0, NULL);
8798 ok(ret, "thread window returned %d\n", ret);
8799 ok(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8801
8803 ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
8804
8805 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8807
8808 ret = pDeactivateActCtx(0, cookie);
8809 ok(ret, "DeactivateActCtx failed: %u\n", GetLastError());
8810 pReleaseActCtx(context);
8811}
8812
8813
8814static const struct message WmVkN[] = {
8815 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
8816 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
8817 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
8818 { WM_CHAR, wparam|lparam, 'n', 1 },
8819 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 },
8820 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
8821 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
8822 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
8823 { 0 }
8824};
8825static const struct message WmShiftVkN[] = {
8829 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
8830 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
8831 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
8832 { WM_CHAR, wparam|lparam, 'N', 1 },
8833 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 },
8834 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
8835 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
8836 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
8837 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
8838 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
8839 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
8840 { 0 }
8841};
8842static const struct message WmCtrlVkN[] = {
8846 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
8847 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
8848 { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 },
8849 { WM_CHAR, wparam|lparam, 0x000e, 1 },
8850 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
8851 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
8852 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
8853 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
8854 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
8855 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
8856 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
8857 { 0 }
8858};
8859static const struct message WmCtrlVkN_2[] = {
8863 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
8864 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
8865 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 },
8866 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
8867 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
8868 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
8869 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
8870 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
8871 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
8872 { 0 }
8873};
8874static const struct message WmAltVkN[] = {
8875 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
8876 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
8877 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
8878 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
8879 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
8880 { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
8881 { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 },
8882 { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 },
8884 { HCBT_SYSCOMMAND, hook },
8886 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
8887 { 0x00AE, sent|defwinproc|optional }, /* XP */
8888 { WM_GETTEXT, sent|defwinproc|optional }, /* XP */
8890 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
8892 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
8895 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
8897 { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
8898 { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */
8899 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
8900 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
8901 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
8902 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
8903 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
8904 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
8905 { 0 }
8906};
8907static const struct message WmAltVkN_2[] = {
8908 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
8909 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
8910 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
8911 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
8912 { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 },
8913 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 },
8914 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
8915 { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 },
8916 { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
8917 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
8918 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
8919 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
8920 { 0 }
8921};
8922static const struct message WmCtrlAltVkN[] = {
8926 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
8927 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
8928 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
8929 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
8930 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
8931 { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 },
8932 { WM_CHAR, optional },
8933 { WM_CHAR, sent|optional },
8934 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
8935 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
8936 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
8937 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
8938 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
8939 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
8940 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
8941 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
8942 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
8943 { 0 }
8944};
8945static const struct message WmCtrlShiftVkN[] = {
8952 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
8953 { WM_KEYDOWN, wparam|lparam, 'N', 1 },
8954 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 },
8955 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
8956 { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 },
8957 { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
8958 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
8959 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
8960 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
8961 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
8962 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
8963 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
8964 { 0 }
8965};
8966static const struct message WmCtrlAltShiftVkN[] = {
8970 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
8971 { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
8972 { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
8973 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0x20000001 }, /* XP */
8974 { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 },
8975 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 },
8976 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */
8977 { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 },
8978 { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 },
8979 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */
8980 { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 },
8981 { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 },
8982 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xe0000001 }, /* XP */
8983 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 },
8984 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 },
8985 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
8986 { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
8987 { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
8988 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */
8989 { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 },
8990 { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 },
8991 { 0 }
8992};
8993static const struct message WmAltPressRelease[] = {
8994 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */
8995 { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 },
8996 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 },
8997 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
8998 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
8999 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
9001 { HCBT_SYSCOMMAND, hook },
9003 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
9005 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
9007 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
9008
9009 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x30000001 }, /* XP */
9010
9011 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
9012 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
9015 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
9017 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */
9018 { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 },
9019 { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
9020 { 0 }
9021};
9022static const struct message WmShiftMouseButton[] = {
9026 { WM_MOUSEMOVE, wparam|optional, 0, 0 },
9027 { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 },
9030 { WM_LBUTTONUP, wparam, MK_SHIFT, 0 },
9032 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */
9033 { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 },
9034 { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 },
9035 { 0 }
9036};
9037static const struct message WmF1Seq[] = {
9038 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 1 }, /* XP */
9039 { WM_KEYDOWN, wparam|lparam, VK_F1, 1 },
9040 { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 },
9041 { WM_KEYF1, wparam|lparam, 0, 0 },
9042 { WM_KEYF1, sent|wparam|lparam, 0, 0 },
9043 { WM_HELP, sent|defwinproc },
9044 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 0xc0000001 }, /* XP */
9045 { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 },
9046 { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 },
9047 { 0 }
9048};
9049static const struct message WmVkAppsSeq[] = {
9052 { WM_KEYDOWN, sent|wparam|lparam, VK_APPS, 0x00000001 },
9053 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 0xc0000001 }, /* XP */
9054 { WM_KEYUP, wparam|lparam, VK_APPS, 0xc0000001 },
9055 { WM_KEYUP, sent|wparam|lparam, VK_APPS, 0xc0000001 },
9056 { WM_CONTEXTMENU, lparam, /*hwnd*/0, -1 },
9057 { WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, -1 },
9058 { 0 }
9059};
9060static const struct message WmVkF10Seq[] = {
9061 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
9063 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 },
9064 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
9065 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
9066 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
9068 { HCBT_SYSCOMMAND, hook },
9070 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
9072 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
9074 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
9075
9076 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0x10000001 }, /* XP */
9077
9078 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
9079 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
9080 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
9083 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
9085 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
9086 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
9087 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
9088 { 0 }
9089};
9090static const struct message WmShiftF10Seq[] = {
9093 { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x00000001 },
9094 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
9096 { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 },
9097 { WM_CONTEXTMENU, sent|defwinproc|lparam, /*hwnd*/0, -1 },
9098 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
9099 { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
9100 { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
9102 { HCBT_SYSCOMMAND, hook },
9106 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xd0000001 }, /* XP */
9107 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0x10000001 }, /* XP */
9109 { WM_MENUSELECT, sent|defwinproc|wparam|lparam, 0xffff0000, 0 },
9111 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, /* XP */
9112 { WM_KEYUP, wparam|lparam, VK_ESCAPE, 0xc0000001 },
9113 { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 },
9114 { 0 }
9115};
9116
9117static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
9118{
9119 MSG msg;
9120
9121 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
9122 {
9123 struct recvd_message log_msg;
9124
9125 /* ignore some unwanted messages */
9126 if (msg.message == WM_MOUSEMOVE ||
9127 msg.message == WM_TIMER ||
9128 ignore_message( msg.message ))
9129 continue;
9130
9131 log_msg.hwnd = msg.hwnd;
9132 log_msg.message = msg.message;
9133 log_msg.flags = wparam|lparam;
9134 log_msg.wParam = msg.wParam;
9135 log_msg.lParam = msg.lParam;
9136 log_msg.descr = "accel";
9137 add_message(&log_msg);
9138
9140 {
9143 }
9144 }
9145}
9146
9147static void test_accelerators(void)
9148{
9149 RECT rc;
9150 POINT pt;
9151 SHORT state;
9152 HACCEL hAccel;
9153 HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
9154 100, 100, 200, 200, 0, 0, 0, NULL);
9155 BOOL ret;
9156
9157 assert(hwnd != 0);
9159 flush_events();
9161
9162 SetFocus(hwnd);
9163 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
9164
9166 ok(!(state & 0x8000), "wrong Shift state %04x\n", state);
9168 ok(state == 0, "wrong CapsLock state %04x\n", state);
9169
9171 assert(hAccel != 0);
9172
9173 flush_events();
9174 pump_msg_loop(hwnd, 0);
9176
9177 trace("testing VK_N press/release\n");
9179 keybd_event('N', 0, 0, 0);
9180 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9182 if (!sequence_cnt) /* we didn't get any message */
9183 {
9184 skip( "queuing key events not supported\n" );
9185 goto done;
9186 }
9187 ok_sequence(WmVkN, "VK_N press/release", FALSE);
9188
9189 trace("testing Shift+VK_N press/release\n");
9191 keybd_event(VK_SHIFT, 0, 0, 0);
9192 keybd_event('N', 0, 0, 0);
9193 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9196 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
9197
9198 trace("testing Ctrl+VK_N press/release\n");
9200 keybd_event(VK_CONTROL, 0, 0, 0);
9201 keybd_event('N', 0, 0, 0);
9202 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9205 ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
9206
9207 trace("testing Alt+VK_N press/release\n");
9209 keybd_event(VK_MENU, 0, 0, 0);
9210 keybd_event('N', 0, 0, 0);
9211 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9214 ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
9215
9216 trace("testing Ctrl+Alt+VK_N press/release 1\n");
9218 keybd_event(VK_CONTROL, 0, 0, 0);
9219 keybd_event(VK_MENU, 0, 0, 0);
9220 keybd_event('N', 0, 0, 0);
9221 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9225 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
9226
9228 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError());
9229
9231 assert(hAccel != 0);
9232
9233 trace("testing VK_N press/release\n");
9235 keybd_event('N', 0, 0, 0);
9236 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9238 ok_sequence(WmVkN, "VK_N press/release", FALSE);
9239
9240 trace("testing Shift+VK_N press/release\n");
9242 keybd_event(VK_SHIFT, 0, 0, 0);
9243 keybd_event('N', 0, 0, 0);
9244 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9247 ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
9248
9249 trace("testing Ctrl+VK_N press/release 2\n");
9251 keybd_event(VK_CONTROL, 0, 0, 0);
9252 keybd_event('N', 0, 0, 0);
9253 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9256 ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
9257
9258 trace("testing Alt+VK_N press/release 2\n");
9260 keybd_event(VK_MENU, 0, 0, 0);
9261 keybd_event('N', 0, 0, 0);
9262 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9265 ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
9266
9267 trace("testing Ctrl+Alt+VK_N press/release 2\n");
9269 keybd_event(VK_CONTROL, 0, 0, 0);
9270 keybd_event(VK_MENU, 0, 0, 0);
9271 keybd_event('N', 0, 0, 0);
9272 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9276 ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
9277
9278 trace("testing Ctrl+Shift+VK_N press/release\n");
9280 keybd_event(VK_CONTROL, 0, 0, 0);
9281 keybd_event(VK_SHIFT, 0, 0, 0);
9282 keybd_event('N', 0, 0, 0);
9283 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9287 ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE);
9288
9289 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
9291 keybd_event(VK_CONTROL, 0, 0, 0);
9292 keybd_event(VK_MENU, 0, 0, 0);
9293 keybd_event(VK_SHIFT, 0, 0, 0);
9294 keybd_event('N', 0, 0, 0);
9295 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
9300 ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE);
9301
9303 ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError());
9304 hAccel = 0;
9305
9306 trace("testing Alt press/release\n");
9308 keybd_event(VK_MENU, 0, 0, 0);
9310 keybd_event(VK_MENU, 0, 0, 0);
9312 pump_msg_loop(hwnd, 0);
9313 /* this test doesn't pass in Wine for managed windows */
9314 ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
9315
9316 trace("testing VK_F1 press/release\n");
9317 keybd_event(VK_F1, 0, 0, 0);
9319 pump_msg_loop(hwnd, 0);
9320 ok_sequence(WmF1Seq, "F1 press/release", FALSE);
9321
9322 trace("testing VK_APPS press/release\n");
9323 keybd_event(VK_APPS, 0, 0, 0);
9325 pump_msg_loop(hwnd, 0);
9326 ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE);
9327
9328 trace("testing VK_F10 press/release\n");
9329 keybd_event(VK_F10, 0, 0, 0);
9331 keybd_event(VK_F10, 0, 0, 0);
9333 pump_msg_loop(hwnd, 0);
9334 ok_sequence(WmVkF10Seq, "VK_F10 press/release", TRUE);
9335
9336 trace("testing SHIFT+F10 press/release\n");
9337 keybd_event(VK_SHIFT, 0, 0, 0);
9338 keybd_event(VK_F10, 0, 0, 0);
9341 keybd_event(VK_ESCAPE, 0, 0, 0);
9343 pump_msg_loop(hwnd, 0);
9344 ok_sequence(WmShiftF10Seq, "SHIFT+F10 press/release", TRUE);
9345
9346 trace("testing Shift+MouseButton press/release\n");
9347 /* first, move mouse pointer inside of the window client area */
9348 GetClientRect(hwnd, &rc);
9349 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
9350 rc.left += (rc.right - rc.left)/2;
9351 rc.top += (rc.bottom - rc.top)/2;
9352 SetCursorPos(rc.left, rc.top);
9354
9355 flush_events();
9357 GetCursorPos(&pt);
9358 if (pt.x == rc.left && pt.y == rc.top)
9359 {
9360 int i;
9361 keybd_event(VK_SHIFT, 0, 0, 0);
9362 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
9363 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
9365 pump_msg_loop(hwnd, 0);
9366 for (i = 0; i < sequence_cnt; i++) if (sequence[i].message == WM_LBUTTONDOWN) break;
9367 if (i < sequence_cnt)
9368 ok_sequence(WmShiftMouseButton, "Shift+MouseButton press/release", FALSE);
9369 else
9370 skip( "Shift+MouseButton event didn't get to the window\n" );
9371 }
9372
9373done:
9376}
9377
9378/************* window procedures ********************/
9379
9382{
9383 static LONG defwndproc_counter = 0;
9384 static LONG beginpaint_counter = 0;
9385 LRESULT ret;
9386 struct recvd_message msg;
9387
9388 if (ignore_message( message )) return 0;
9389
9390 switch (message)
9391 {
9392 case WM_ENABLE:
9393 {
9395 ok((BOOL)wParam == !(style & WS_DISABLED),
9396 "wrong WS_DISABLED state: %ld != %d\n", wParam, !(style & WS_DISABLED));
9397 break;
9398 }
9399
9400 case WM_CAPTURECHANGED:
9402 {
9404 if (style & WS_CHILD)
9406 else if (style & WS_POPUP)
9408 else
9410 }
9411 break;
9412
9413 case WM_NCDESTROY:
9414 {
9415 HWND capture;
9416
9417 ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n");
9418 capture = GetCapture();
9419 if (capture)
9420 {
9421 ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture);
9422 trace("current capture %p, releasing...\n", capture);
9424 }
9425 }
9426 /* fall through */
9427 case WM_DESTROY:
9428 if (pGetAncestor)
9429 ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n");
9431 {
9433 if (style & WS_CHILD)
9435 else if (style & WS_POPUP)
9437 else
9439 }
9440 break;
9441
9442 /* test_accelerators() depends on this */
9443 case WM_NCHITTEST:
9444 return HTCLIENT;
9445
9446 case WM_USER+10:
9447 {
9448 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo;
9449 HANDLE handle, event = (HANDLE)lParam;
9450 BOOL ret;
9451
9452 handle = (void*)0xdeadbeef;
9453 ret = pGetCurrentActCtx(&handle);
9454 ok(ret, "failed to get current context, %u\n", GetLastError());
9455 ok(handle == 0, "got active context %p\n", handle);
9456
9457 memset(&basicinfo, 0xff, sizeof(basicinfo));
9458 ret = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, 0, ActivationContextBasicInformation,
9459 &basicinfo, sizeof(basicinfo), NULL);
9460 ok(ret, "got %d, error %d\n", ret, GetLastError());
9461 ok(basicinfo.hActCtx == NULL, "got %p\n", basicinfo.hActCtx);
9462 ok(basicinfo.dwFlags == 0, "got %x\n", basicinfo.dwFlags);
9463
9464 if (event) SetEvent(event);
9465 return 1;
9466 }
9467
9468 /* ignore */
9469 case WM_MOUSEMOVE:
9470 case WM_MOUSEACTIVATE:
9471 case WM_NCMOUSEMOVE:
9472 case WM_SETCURSOR:
9473 case WM_IME_SELECT:
9474 return 0;
9475 }
9476
9477 msg.hwnd = hwnd;
9478 msg.message = message;
9479 msg.flags = sent|wparam|lparam;
9480 if (defwndproc_counter) msg.flags |= defwinproc;
9481 if (beginpaint_counter) msg.flags |= beginpaint;
9482 msg.wParam = wParam;
9483 msg.lParam = lParam;
9484 msg.descr = "MsgCheckProc";
9485 add_message(&msg);
9486
9488 {
9490 RECT rc;
9491 MINMAXINFO *minmax = (MINMAXINFO *)lParam;
9492
9493 GetClientRect(parent, &rc);
9494 trace("parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
9495 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
9496 minmax->ptReserved.x, minmax->ptReserved.y,
9497 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
9498 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
9499 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
9500 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
9501
9502 ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %d != %d\n",
9503 minmax->ptMaxSize.x, rc.right);
9504 ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %d != %d\n",
9505 minmax->ptMaxSize.y, rc.bottom);
9506 }
9507
9508 if (message == WM_PAINT)
9509 {
9510 PAINTSTRUCT ps;
9511 beginpaint_counter++;
9512 BeginPaint( hwnd, &ps );
9513 beginpaint_counter--;
9514 EndPaint( hwnd, &ps );
9515 return 0;
9516 }
9517
9519 {
9520 /* don't create context menu */
9521 return 0;
9522 }
9523
9524 defwndproc_counter++;
9525 ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam)
9527 defwndproc_counter--;
9528
9529 return ret;
9530}
9531
9533{
9535}
9536
9538{
9540}
9541
9543{
9544 static LONG defwndproc_counter = 0;
9545 LRESULT ret;
9546 struct recvd_message msg;
9547
9548 if (ignore_message( message )) return 0;
9549
9550 switch (message)
9551 {
9552 case WM_QUERYENDSESSION:
9553 case WM_ENDSESSION:
9554 lParam &= ~0x01; /* Vista adds a 0x01 flag */
9555 break;
9556 }
9557
9558 msg.hwnd = hwnd;
9559 msg.message = message;
9560 msg.flags = sent|wparam|lparam;
9561 if (defwndproc_counter) msg.flags |= defwinproc;
9562 msg.wParam = wParam;
9563 msg.lParam = lParam;
9564 msg.descr = "popup";
9565 add_message(&msg);
9566
9567 if (message == WM_CREATE)
9568 {
9571 }
9572
9573 defwndproc_counter++;
9575 defwndproc_counter--;
9576
9577 return ret;
9578}
9579
9581{
9582 static LONG defwndproc_counter = 0;
9583 static LONG beginpaint_counter = 0;
9584 LRESULT ret;
9585 struct recvd_message msg;
9586
9587 if (ignore_message( message )) return 0;
9588
9595 {
9596 switch (message)
9597 {
9598 /* ignore */
9599 case WM_NCHITTEST:
9600 return HTCLIENT;
9601 case WM_SETCURSOR:
9602 case WM_MOUSEMOVE:
9603 case WM_NCMOUSEMOVE:
9604 return 0;
9605
9606 case WM_ERASEBKGND:
9607 {
9608 RECT rc;
9609 INT ret = GetClipBox((HDC)wParam, &rc);
9610
9611 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret, wine_dbgstr_rect(&rc));
9612 break;
9613 }
9614 }
9615
9616 msg.hwnd = hwnd;
9617 msg.message = message;
9618 msg.flags = sent|parent|wparam|lparam;
9619 if (defwndproc_counter) msg.flags |= defwinproc;
9620 if (beginpaint_counter) msg.flags |= beginpaint;
9621 msg.wParam = wParam;
9622 msg.lParam = lParam;
9623 msg.descr = "parent";
9624 add_message(&msg);
9625 }
9626
9627 if (message == WM_PAINT)
9628 {
9629 PAINTSTRUCT ps;
9630 beginpaint_counter++;
9631 BeginPaint( hwnd, &ps );
9632 beginpaint_counter--;
9633 EndPaint( hwnd, &ps );
9634 return 0;
9635 }
9636
9637 defwndproc_counter++;
9639 defwndproc_counter--;
9640
9641 return message == WM_COMPAREITEM ? -1 : ret;
9642}
9643
9645{
9646 if (message == WM_CREATE)
9647 PostMessageA(hwnd, WM_CLOSE, 0, 0);
9648 else if (message == WM_CLOSE)
9649 {
9650 /* Only the first WM_QUIT will survive the window destruction */
9651 PostMessageA(hwnd, WM_USER, 0x1234, 0x5678);
9652 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678);
9653 PostMessageA(hwnd, WM_QUIT, 0x4321, 0x8765);
9654 }
9655
9656 return DefWindowProcA(hwnd, message, wp, lp);
9657}
9658
9660{
9661 static LONG defwndproc_counter = 0;
9662 LRESULT ret;
9663 struct recvd_message msg;
9664
9665 if (ignore_message( message )) return 0;
9666
9667 if (test_def_id)
9668 {
9670 ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
9671 if (after_end_dialog)
9672 ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
9673 else
9674 ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
9675 }
9676
9677 msg.hwnd = hwnd;
9678 msg.message = message;
9679 msg.flags = sent|wparam|lparam;
9680 if (defwndproc_counter) msg.flags |= defwinproc;
9681 msg.wParam = wParam;
9682 msg.lParam = lParam;
9683 msg.descr = "dialog";
9684 add_message(&msg);
9685
9686 defwndproc_counter++;
9688 defwndproc_counter--;
9689
9690 return ret;
9691}
9692
9694{
9695 static LONG defwndproc_counter = 0;
9696 LRESULT ret;
9697 struct recvd_message msg;
9698
9699 /* log only specific messages we are interested in */
9700 switch (message)
9701 {
9702#if 0 /* probably log these as well */
9703 case WM_ACTIVATE:
9704 case WM_SETFOCUS:
9705 case WM_KILLFOCUS:
9706#endif
9707 case WM_SHOWWINDOW:
9708 case WM_SIZE:
9709 case WM_MOVE:
9710 case WM_GETMINMAXINFO:
9713 break;
9714
9715 default: /* ignore */
9716 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
9718 }
9719
9720 msg.hwnd = hwnd;
9721 msg.message = message;
9722 msg.flags = sent|wparam|lparam;
9723 if (defwndproc_counter) msg.flags |= defwinproc;
9724 msg.wParam = wParam;
9725 msg.lParam = lParam;
9726 msg.descr = "show";
9727 add_message(&msg);
9728
9729 defwndproc_counter++;
9731 defwndproc_counter--;
9732
9733 return ret;
9734}
9735
9737{
9738 static LONG defwndproc_counter = 0;
9739 struct recvd_message msg;
9740 LRESULT ret;
9741
9742 switch (message)
9743 {
9744 /* log only specific messages we are interested in */
9745 case WM_NCACTIVATE:
9746 case WM_ACTIVATE:
9747 case WM_SETFOCUS:
9748 case WM_KILLFOCUS:
9749 break;
9750 default:
9752 }
9753
9754 msg.hwnd = hwnd;
9755 msg.message = message;
9756 msg.flags = sent|wparam|lparam;
9757 if (defwndproc_counter) msg.flags |= defwinproc;
9758 msg.wParam = wParam;
9759 msg.lParam = lParam;
9760 msg.descr = "recursive_activation";
9761 add_message(&msg);
9762
9763 /* recursively activate ourselves by first losing activation and changing it back */
9765 {
9768 return 0;
9769 }
9770
9771 defwndproc_counter++;
9773 defwndproc_counter--;
9774
9775 return ret;
9776}
9777
9779{
9780 switch (msg)
9781 {
9782 case WM_CREATE: return 0;
9783 case WM_PAINT:
9784 {
9785 MSG msg2;
9786 static int i = 0;
9787
9788 if (i < 256)
9789 {
9790 i++;
9791 if (PeekMessageA(&msg2, 0, 0, 0, 1))
9792 {
9793 TranslateMessage(&msg2);
9794 DispatchMessageA(&msg2);
9795 }
9796 i--;
9797 }
9798 else ok(broken(1), "infinite loop\n");
9799 if ( i == 0)
9802 }
9803 }
9805}
9806
9808{
9809 static LONG defwndproc_counter = 0;
9810 LRESULT ret;
9811 struct recvd_message msg;
9812 DWORD queue_status;
9813
9814 if (ignore_message( message )) return 0;
9815
9816 if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) ||
9818 {
9819 msg.hwnd = hwnd;
9820 msg.message = message;
9821 msg.flags = sent|wparam|lparam;
9822 if (defwndproc_counter) msg.flags |= defwinproc;
9823 msg.wParam = wParam;
9824 msg.lParam = lParam;
9825 msg.descr = "HotkeyMsgCheckProcA";
9826 add_message(&msg);
9827 }
9828
9829 defwndproc_counter++;
9831 defwndproc_counter--;
9832
9833 if (message == WM_APP)
9834 {
9835 queue_status = GetQueueStatus(QS_HOTKEY);
9836 ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status);
9837 queue_status = GetQueueStatus(QS_POSTMESSAGE);
9838 ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status);
9839 PostMessageA(hwnd, WM_APP+1, 0, 0);
9840 }
9841 else if (message == WM_APP+1)
9842 {
9843 queue_status = GetQueueStatus(QS_HOTKEY);
9844 ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status);
9845 }
9846
9847 return ret;
9848}
9849
9851{
9852 WNDCLASSA cls;
9853 WNDCLASSW clsW;
9854
9855 cls.style = 0;
9857 cls.cbClsExtra = 0;
9858 cls.cbWndExtra = 0;
9859 cls.hInstance = GetModuleHandleA(0);
9860 cls.hIcon = 0;
9863 cls.lpszMenuName = NULL;
9864 cls.lpszClassName = "TestWindowClass";
9865 if(!RegisterClassA(&cls)) return FALSE;
9866
9868 cls.lpszClassName = "HotkeyWindowClass";
9869 if(!RegisterClassA(&cls)) return FALSE;
9870
9872 cls.lpszClassName = "ShowWindowClass";
9873 if(!RegisterClassA(&cls)) return FALSE;
9874
9876 cls.lpszClassName = "RecursiveActivationClass";
9877 if(!RegisterClassA(&cls)) return FALSE;
9878
9880 cls.lpszClassName = "TestPopupClass";
9881 if(!RegisterClassA(&cls)) return FALSE;
9882
9884 cls.lpszClassName = "TestParentClass";
9885 if(!RegisterClassA(&cls)) return FALSE;
9886
9888 cls.lpszClassName = "StopQuitClass";
9889 if(!RegisterClassA(&cls)) return FALSE;
9890
9892 cls.lpszClassName = "SimpleWindowClass";
9893 if(!RegisterClassA(&cls)) return FALSE;
9894
9896 cls.lpszClassName = "PaintLoopWindowClass";
9897 if(!RegisterClassA(&cls)) return FALSE;
9898
9899 cls.style = CS_NOCLOSE;
9900 cls.lpszClassName = "NoCloseWindowClass";
9901 if(!RegisterClassA(&cls)) return FALSE;
9902
9903 ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
9904 cls.style = 0;
9905 cls.hInstance = GetModuleHandleA(0);
9906 cls.hbrBackground = 0;
9908 cls.lpszClassName = "TestDialogClass";
9909 if(!RegisterClassA(&cls)) return FALSE;
9910
9911 clsW.style = 0;
9913 clsW.cbClsExtra = 0;
9914 clsW.cbWndExtra = 0;
9915 clsW.hInstance = GetModuleHandleW(0);
9916 clsW.hIcon = 0;
9917 clsW.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
9919 clsW.lpszMenuName = NULL;
9921 RegisterClassW(&clsW); /* ignore error, this fails on Win9x */
9922
9923 return TRUE;
9924}
9925
9927{
9928 char buf[256];
9929
9930 if (GetClassNameA(hwnd, buf, sizeof(buf)))
9931 {
9932 if (!lstrcmpiA(buf, "TestWindowClass") ||
9933 !lstrcmpiA(buf, "ShowWindowClass") ||
9934 !lstrcmpiA(buf, "RecursiveActivationClass") ||
9935 !lstrcmpiA(buf, "TestParentClass") ||
9936 !lstrcmpiA(buf, "TestPopupClass") ||
9937 !lstrcmpiA(buf, "SimpleWindowClass") ||
9938 !lstrcmpiA(buf, "TestDialogClass") ||
9939 !lstrcmpiA(buf, "MDI_frame_class") ||
9940 !lstrcmpiA(buf, "MDI_client_class") ||
9941 !lstrcmpiA(buf, "MDI_child_class") ||
9942 !lstrcmpiA(buf, "my_button_class") ||
9943 !lstrcmpiA(buf, "my_edit_class") ||
9944 !lstrcmpiA(buf, "static") ||
9945 !lstrcmpiA(buf, "ListBox") ||
9946 !lstrcmpiA(buf, "ComboBox") ||
9947 !lstrcmpiA(buf, "MyDialogClass") ||
9948 !lstrcmpiA(buf, "#32770") ||
9949 !lstrcmpiA(buf, "#32768"))
9950 return TRUE;
9951 }
9952 return FALSE;
9953}
9954
9956{
9957 HWND hwnd;
9958
9959 ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
9960
9961 if (nCode == HCBT_CLICKSKIPPED)
9962 {
9963 /* ignore this event, XP sends it a lot when switching focus between windows */
9964 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
9965 }
9966
9967 if (nCode == HCBT_SYSCOMMAND || nCode == HCBT_KEYSKIPPED)
9968 {
9969 struct recvd_message msg;
9970
9971 msg.hwnd = 0;
9972 msg.message = nCode;
9973 msg.flags = hook|wparam|lparam;
9974 msg.wParam = wParam;
9975 msg.lParam = lParam;
9976 msg.descr = "CBT";
9977 add_message(&msg);
9978
9979 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
9980 }
9981
9982 if (nCode == HCBT_DESTROYWND)
9983 {
9985 {
9987 if (style & WS_CHILD)
9989 else if (style & WS_POPUP)
9991 else
9993 }
9994 }
9995
9996 /* Log also SetFocus(0) calls */
9997 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
9998
10000 {
10001 struct recvd_message msg;
10002
10003 msg.hwnd = hwnd;
10004 msg.message = nCode;
10005 msg.flags = hook|wparam|lparam;
10006 msg.wParam = wParam;
10007 msg.lParam = lParam;
10008 msg.descr = "CBT";
10009 add_message(&msg);
10010 }
10011 return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
10012}
10013
10015 DWORD event,
10016 HWND hwnd,
10017 LONG object_id,
10018 LONG child_id,
10020 DWORD event_time)
10021{
10022 ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
10023
10024 /* ignore mouse cursor events */
10025 if (object_id == OBJID_CURSOR) return;
10026
10027 if (!hwnd || is_our_logged_class(hwnd))
10028 {
10029 struct recvd_message msg;
10030
10031 msg.hwnd = hwnd;
10032 msg.message = event;
10034 msg.wParam = object_id;
10035 msg.lParam = child_id;
10036 msg.descr = "WEH";
10037 add_message(&msg);
10038 }
10039}
10040
10041static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};
10042static const WCHAR wszAnsi[] = {'U',0};
10043
10045{
10046 switch (uMsg)
10047 {
10048 case CB_FINDSTRINGEXACT:
10049 trace("String: %p\n", (LPCWSTR)lParam);
10051 return 1;
10053 return 0;
10054 return -1;
10055 }
10056 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
10057}
10058
10059static const struct message WmGetTextLengthAfromW[] = {
10062 { 0 }
10063};
10064
10065static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0};
10066
10067/* dummy window proc for WM_GETTEXTLENGTH test */
10069{
10070 switch(msg)
10071 {
10072 case WM_GETTEXTLENGTH:
10073 return lstrlenW(dummy_window_text) + 37; /* some random length */
10074 case WM_GETTEXT:
10076 return lstrlenW( (LPWSTR)lp );
10077 default:
10078 return DefWindowProcW( hwnd, msg, wp, lp );
10079 }
10080}
10081
10083{
10084 static const WCHAR wszMsgConversionClass[] =
10085 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
10086 WNDCLASSW cls;
10087 LRESULT lRes;
10088 HWND hwnd;
10089 WNDPROC wndproc, newproc;
10090 BOOL ret;
10091
10092 cls.style = 0;
10094 cls.cbClsExtra = 0;
10095 cls.cbWndExtra = 0;
10097 cls.hIcon = NULL;
10099 cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
10100 cls.lpszMenuName = NULL;
10101 cls.lpszClassName = wszMsgConversionClass;
10102 /* this call will fail on Win9x, but that doesn't matter as this test is
10103 * meaningless on those platforms */
10104 if(!RegisterClassW(&cls)) return;
10105
10106 hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
10107 100, 100, 200, 200, 0, 0, 0, NULL);
10108 ok(hwnd != NULL, "Window creation failed\n");
10109
10110 /* {W, A} -> A */
10111
10114 ok(lRes == 0, "String should have been converted\n");
10116 ok(lRes == 1, "String shouldn't have been converted\n");
10117
10118 /* {W, A} -> W */
10119
10122 ok(lRes == 1, "String shouldn't have been converted\n");
10124 ok(lRes == 1, "String shouldn't have been converted\n");
10125
10126 /* Synchronous messages */
10127
10129 ok(lRes == 0, "String should have been converted\n");
10131 ok(lRes == 1, "String shouldn't have been converted\n");
10132
10133 /* Asynchronous messages */
10134
10135 SetLastError(0);
10138 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10139 SetLastError(0);
10142 "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10143 SetLastError(0);
10146 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10147 SetLastError(0);
10150 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10151 SetLastError(0);
10154 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10155 SetLastError(0);
10158 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10159 SetLastError(0);
10162 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10163 SetLastError(0);
10166 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError());
10167
10168 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
10169
10172 100, 100, 200, 200, 0, 0, 0, NULL);
10173 assert(hwnd);
10175 lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0);
10176 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
10178 "got bad length %ld\n", lRes );
10179
10182 hwnd, WM_GETTEXTLENGTH, 0, 0);
10183 ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
10185 "got bad length %ld\n", lRes );
10186
10189 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
10191 NULL, 0, NULL, NULL ) ||
10192 broken(lRes == lstrlenW(dummy_window_text) + 37),
10193 "got bad length %ld\n", lRes );
10194
10195 SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */
10196 lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
10198 NULL, 0, NULL, NULL ) ||
10199 broken(lRes == lstrlenW(dummy_window_text) + 37),
10200 "got bad length %ld\n", lRes );
10201
10203 ok( ret, "DestroyWindow() error %d\n", GetLastError());
10204}
10205
10207{
10211};
10212
10214{
10215}
10216
10217#define TIMER_ID 0x19
10218#define TIMER_COUNT_EXPECTED 100
10219#define TIMER_COUNT_TOLERANCE 10
10220
10221static int count = 0;
10223{
10224 count++;
10225}
10226
10229{
10230 count++;
10232}
10233
10235{
10236 struct timer_info *info = x;
10237 DWORD r;
10238
10239 r = KillTimer(info->hWnd, 0x19);
10240 ok(r,"KillTimer failed in thread\n");
10241 r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc);
10242 ok(r,"SetTimer failed in thread\n");
10243 ok(r==TIMER_ID,"SetTimer id different\n");
10244 r = SetEvent(info->handles[0]);
10245 ok(r,"SetEvent failed in thread\n");
10246 return 0;
10247}
10248
10249static void test_timers(void)
10250{
10251 struct timer_info info;
10252 DWORD start;
10253 DWORD id;
10254 MSG msg;
10255
10256 info.hWnd = CreateWindowA("TestWindowClass", NULL,
10258 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
10259 NULL, NULL, 0);
10260
10261 info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc);
10262 ok(info.id, "SetTimer failed\n");
10263 ok(info.id==TIMER_ID, "SetTimer timer ID different\n");
10264 info.handles[0] = CreateEventW(NULL,0,0,NULL);
10265 info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
10266
10268
10269 WaitForSingleObject(info.handles[1], INFINITE);
10270
10271 CloseHandle(info.handles[0]);
10272 CloseHandle(info.handles[1]);
10273
10274 ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
10275
10276 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
10277 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
10278 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
10279 * ±9 counts (~4 ms) around the expected value.
10280 */
10281 count = 0;
10282 id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count);
10283 ok(id != 0, "did not get id from SetTimer.\n");
10284 ok(id==TIMER_ID, "SetTimer timer ID different\n");
10285 start = GetTickCount();
10286 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0))
10291 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */
10292 || broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3, win8 */,
10293 "did not get expected count for minimum timeout (%d != ~%d).\n",
10295 ok(KillTimer(info.hWnd, id), "KillTimer failed\n");
10296 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
10297 if (pSetSystemTimer)
10298 {
10299 int syscount = 0;
10300
10301 count = 0;
10302 id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count);
10303 ok(id != 0, "did not get id from SetSystemTimer.\n");
10304 ok(id==TIMER_ID, "SetTimer timer ID different\n");
10305 start = GetTickCount();
10306 while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0))
10307 {
10308 if (msg.message == WM_SYSTIMER)
10309 syscount++;
10311 }
10313 || broken(abs(syscount-64) < TIMER_COUNT_TOLERANCE) /* most common */
10314 || broken(syscount > 4000 && syscount < 12000) /* win2k3sp0 */,
10315 "did not get expected count for minimum timeout (%d != ~%d).\n",
10316 syscount, TIMER_COUNT_EXPECTED);
10317 todo_wine ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n",
10318 count);
10319 ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n");
10320 }
10321
10322 ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
10323}
10324
10325static void test_timers_no_wnd(void)
10326{
10327 static UINT_PTR ids[0xffff];
10328 UINT_PTR id, id2;
10329 DWORD start;
10330 MSG msg;
10331 int i;
10332
10333 count = 0;
10334 id = SetTimer(NULL, 0, 100, callback_count);
10335 ok(id != 0, "did not get id from SetTimer.\n");
10336 id2 = SetTimer(NULL, id, 200, callback_count);
10337 ok(id2 == id, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2, id);
10338 Sleep(150);
10339 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
10340 ok(count == 0, "did not get zero count as expected (%i).\n", count);
10341 Sleep(150);
10342 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
10343 ok(count == 1, "did not get one count as expected (%i).\n", count);
10344 KillTimer(NULL, id);
10345 Sleep(250);
10346 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
10347 ok(count == 1, "killing replaced timer did not work (%i).\n", count);
10348
10349 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
10350 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
10351 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
10352 * ±9 counts (~4 ms) around the expected value.
10353 */
10354 count = 0;
10355 id = SetTimer(NULL, 0, 0, callback_count);
10356 ok(id != 0, "did not get id from SetTimer.\n");
10357 start = GetTickCount();
10358 while (GetTickCount()-start < 1001 && GetMessageA(&msg, NULL, 0, 0))
10362 || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */,
10363 "did not get expected count for minimum timeout (%d != ~%d).\n",
10365 KillTimer(NULL, id);
10366 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
10367
10368 if (pSetCoalescableTimer)
10369 {
10370 count = 0;
10371 id = pSetCoalescableTimer(NULL, 0, 0, callback_count, 0);
10372 ok(id != 0, "SetCoalescableTimer failed with %u.\n", GetLastError());
10373 start = GetTickCount();
10374 while (GetTickCount()-start < 100 && GetMessageA(&msg, NULL, 0, 0))
10376 ok(count > 1, "expected count > 1, got %d.\n", count);
10377 KillTimer(NULL, id);
10378 }
10379 else
10380 win_skip("SetCoalescableTimer not available.\n");
10381
10382 /* Check what happens when we're running out of timers */
10383 for (i = 0; i < ARRAY_SIZE(ids); i++)
10384 {
10385 SetLastError(0xdeadbeef);
10387 if (!ids[i]) break;
10388 }
10389 ok(i != ARRAY_SIZE(ids), "all timers were created successfully\n");
10391 "GetLastError() = %d\n", GetLastError());
10392 while (i > 0) KillTimer(NULL, ids[--i]);
10393}
10394
10396{
10397 UINT_PTR id;
10398 MSG msg;
10399
10400 exception = code;
10401 id = SetTimer(NULL, 0, 1000, callback_exception);
10402 ok(id != 0, "did not get id from SetTimer.\n");
10403
10404 memset(&msg, 0, sizeof(msg));
10405 msg.message = WM_TIMER;
10406 msg.wParam = id;
10407 msg.lParam = (LPARAM)callback_exception;
10408
10409 count = 0;
10411 ok(count == 1, "did not get one count as expected (%i).\n", count);
10412
10413 KillTimer(NULL, id);
10414}
10415
10416static void test_timers_exceptions(void)
10417{
10427 test_timers_exception(0xE000BEEF); /* customer exception */
10428}
10429
10430/* Various win events with arbitrary parameters */
10431static const struct message WmWinEventsSeq[] = {
10432 { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
10433 { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
10434 { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
10435 { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
10436 { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
10437 { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
10438 { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
10439 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
10440 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
10441 /* our win event hook ignores OBJID_CURSOR events */
10442 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
10443 { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 },
10444 { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 },
10445 { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 },
10446 { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 },
10447 { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
10448 { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
10449 { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 },
10450 { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 },
10451 { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 },
10452 { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 },
10453 { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 },
10454 { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 },
10455 { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
10456 { 0 }
10457};
10458static const struct message WmWinEventCaretSeq[] = {
10459 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
10460 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
10461 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */
10462 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
10463 { 0 }
10464};
10465static const struct message WmWinEventCaretSeq_2[] = {
10466 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
10467 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
10468 { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
10469 { 0 }
10470};
10471static const struct message WmWinEventAlertSeq[] = {
10472 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 },
10473 { 0 }
10474};
10475static const struct message WmWinEventAlertSeq_2[] = {
10476 /* create window in the thread proc */
10477 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 },
10478 /* our test event */
10479 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 },
10480 { 0 }
10481};
10482static const struct message WmGlobalHookSeq_1[] = {
10483 /* create window in the thread proc */
10484 { HCBT_CREATEWND, hook|lparam, 0, 2 },
10485 /* our test events */
10488 { 0 }
10489};
10490static const struct message WmGlobalHookSeq_2[] = {
10491 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */
10492 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */
10493 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */
10494 { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */
10495 { 0 }
10496};
10497
10498static const struct message WmMouseLLHookSeq[] = {
10499 { WM_MOUSEMOVE, hook },
10500 { WM_LBUTTONUP, hook },
10501 { WM_MOUSEMOVE, hook },
10502 { 0 }
10503};
10504
10506 DWORD event,
10507 HWND hwnd,
10508 LONG object_id,
10509 LONG child_id,
10511 DWORD event_time)
10512{
10513 char buf[256];
10514
10515 if (GetClassNameA(hwnd, buf, sizeof(buf)))
10516 {
10517 if (!lstrcmpiA(buf, "TestWindowClass") ||
10518 !lstrcmpiA(buf, "static"))
10519 {
10520 struct recvd_message msg;
10521
10522 msg.hwnd = hwnd;
10523 msg.message = event;
10525 msg.wParam = object_id;
10526 msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2);
10527 msg.descr = "WEH_2";
10528 add_message(&msg);
10529 }
10530 }
10531}
10532
10533static HHOOK hCBT_global_hook;
10535
10537{
10538 HWND hwnd;
10539 char buf[256];
10540
10541 if (nCode == HCBT_SYSCOMMAND)
10542 {
10543 struct recvd_message msg;
10544
10545 msg.hwnd = 0;
10546 msg.message = nCode;
10547 msg.flags = hook|wparam|lparam;
10548 msg.wParam = wParam;
10549 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
10550 msg.descr = "CBT_2";
10551 add_message(&msg);
10552
10554 }
10555 /* WH_MOUSE_LL hook */
10556 if (nCode == HC_ACTION)
10557 {
10559
10560 /* we can't test for real mouse events */
10561 if (mhll->flags & LLMHF_INJECTED)
10562 {
10563 struct recvd_message msg;
10564
10565 memset (&msg, 0, sizeof (msg));
10566 msg.message = wParam;
10567 msg.flags = hook;
10568 msg.descr = "CBT_2";
10569 add_message(&msg);
10570 }
10572 }
10573
10574 /* Log also SetFocus(0) calls */
10575 hwnd = wParam ? (HWND)wParam : (HWND)lParam;
10576
10577 if (GetClassNameA(hwnd, buf, sizeof(buf)))
10578 {
10579 if (!lstrcmpiA(buf, "TestWindowClass") ||
10580 !lstrcmpiA(buf, "static"))
10581 {
10582 struct recvd_message msg;
10583
10584 msg.hwnd = hwnd;
10585 msg.message = nCode;
10586 msg.flags = hook|wparam|lparam;
10587 msg.wParam = wParam;
10588 msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
10589 msg.descr = "CBT_2";
10590 add_message(&msg);
10591 }
10592 }
10594}
10595
10597{
10598 HWND hwnd;
10599 MSG msg;
10600 HANDLE hevent = *(HANDLE *)param;
10601
10602 assert(pNotifyWinEvent);
10603
10604 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
10605 assert(hwnd);
10606 trace("created thread window %p\n", hwnd);
10607
10608 *(HWND *)param = hwnd;
10609
10611 /* this event should be received only by our new hook proc,
10612 * an old one does not expect an event from another thread.
10613 */
10614 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0);
10616
10617 while (GetMessageA(&msg, 0, 0, 0))
10618 {
10621 }
10622 return 0;
10623}
10624
10626{
10627 HWND hwnd;
10628 MSG msg;
10629 HANDLE hevent = *(HANDLE *)param;
10630
10632 /* these events should be received only by our new hook proc,
10633 * an old one does not expect an event from another thread.
10634 */
10635
10636 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
10637 assert(hwnd);
10638 trace("created thread window %p\n", hwnd);
10639
10640 *(HWND *)param = hwnd;
10641
10642 /* Windows doesn't like when a thread plays games with the focus,
10643 that leads to all kinds of misbehaviours and failures to activate
10644 a window. So, better keep next lines commented out.
10645 SetFocus(0);
10646 SetFocus(hwnd);*/
10647
10650
10652
10653 while (GetMessageA(&msg, 0, 0, 0))
10654 {
10657 }
10658 return 0;
10659}
10660
10662{
10663 HWND hwnd;
10664 MSG msg;
10665 HANDLE hevent = *(HANDLE *)param;
10666
10667 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
10668 assert(hwnd);
10669 trace("created thread window %p\n", hwnd);
10670
10671 *(HWND *)param = hwnd;
10672
10674
10675 /* Windows doesn't like when a thread plays games with the focus,
10676 * that leads to all kinds of misbehaviours and failures to activate
10677 * a window. So, better don't generate a mouse click message below.
10678 */
10679 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
10680 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
10681 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
10682
10684 while (GetMessageA(&msg, 0, 0, 0))
10685 {
10688 }
10689 return 0;
10690}
10691
10692static void test_winevents(void)
10693{
10694 BOOL ret;
10695 MSG msg;
10696 HWND hwnd, hwnd2;
10697 UINT i;
10698 HANDLE hthread, hevent;
10699 DWORD tid;
10701 const struct message *events = WmWinEventsSeq;
10702
10703 hwnd = CreateWindowExA(0, "TestWindowClass", NULL,
10705 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
10706 NULL, NULL, 0);
10707 assert(hwnd);
10708
10709 /****** start of global hook test *************/
10711 if (!hCBT_global_hook)
10712 {
10713 ok(DestroyWindow(hwnd), "failed to destroy window\n");
10714 skip( "cannot set global hook\n" );
10715 return;
10716 }
10717
10718 hevent = CreateEventA(NULL, 0, 0, NULL);
10719 assert(hevent);
10720 hwnd2 = hevent;
10721
10722 hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid);
10723 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
10724
10725 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10726
10727 ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
10728
10730 /* this one should be received only by old hook proc */
10732 /* this one should be received only by old hook proc */
10734
10735 ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
10736
10738 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError());
10739
10741 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10742 CloseHandle(hthread);
10744 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
10745 /****** end of global hook test *************/
10746
10747 if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent)
10748 {
10749 ok(DestroyWindow(hwnd), "failed to destroy window\n");
10750 return;
10751 }
10752
10754
10755 if (0)
10756 {
10757 /* this test doesn't pass under Win9x */
10758 /* win2k ignores events with hwnd == 0 */
10759 SetLastError(0xdeadbeef);
10760 pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
10761 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
10762 GetLastError() == 0xdeadbeef, /* Win9x */
10763 "unexpected error %d\n", GetLastError());
10764 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
10765 }
10766
10767 for (i = 0; i < ARRAY_SIZE(WmWinEventsSeq); i++)
10768 pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
10769
10770 ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
10771
10772 /****** start of event filtering test *************/
10773 hhook = pSetWinEventHook(
10774 EVENT_OBJECT_SHOW, /* 0x8002 */
10775 EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */
10779 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError());
10780
10781 hevent = CreateEventA(NULL, 0, 0, NULL);
10782 assert(hevent);
10783 hwnd2 = hevent;
10784
10785 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
10786 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
10787
10788 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10789
10790 ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
10791
10793 /* this one should be received only by old hook proc */
10794 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
10795 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
10796 /* this one should be received only by old hook proc */
10797 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
10798
10799 ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
10800
10801 ret = pUnhookWinEvent(hhook);
10802 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
10803
10805 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10806 CloseHandle(hthread);
10808 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
10809 /****** end of event filtering test *************/
10810
10811 /****** start of out of context event test *************/
10812 hhook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0,
10815 ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError());
10816
10817 hevent = CreateEventA(NULL, 0, 0, NULL);
10818 assert(hevent);
10819 hwnd2 = hevent;
10820
10822
10823 hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
10824 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
10825
10826 ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10827
10828 ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
10829 /* process pending winevent messages */
10830 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
10831 ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
10832
10834 /* this one should be received only by old hook proc */
10835 pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
10836 pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
10837 /* this one should be received only by old hook proc */
10838 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
10839
10840 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE);
10841 /* process pending winevent messages */
10842 ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
10843 ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
10844
10845 ret = pUnhookWinEvent(hhook);
10846 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
10847
10849 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10850 CloseHandle(hthread);
10852 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
10853 /****** end of out of context event test *************/
10854
10855 /****** start of MOUSE_LL hook test *************/
10857 /* WH_MOUSE_LL is not supported on Win9x platforms */
10858 if (!hCBT_global_hook)
10859 {
10860 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
10861 goto skip_mouse_ll_hook_test;
10862 }
10863
10864 hevent = CreateEventA(NULL, 0, 0, NULL);
10865 assert(hevent);
10866 hwnd2 = hevent;
10867
10868 hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid);
10869 ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
10870
10871 while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT)
10872 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
10873
10874 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE);
10876
10877 mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0);
10878 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
10879 mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
10880
10881 ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE);
10882
10884 ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError());
10885
10887 ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
10888 CloseHandle(hthread);
10890 ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
10891 /****** end of MOUSE_LL hook test *************/
10892skip_mouse_ll_hook_test:
10893
10894 ok(DestroyWindow(hwnd), "failed to destroy window\n");
10895}
10896
10897static void test_set_hook(void)
10898{
10899 BOOL ret;
10900 HHOOK hhook;
10901 HWINEVENTHOOK hwinevent_hook;
10902
10904 ok(hhook != 0, "local hook does not require hModule set to 0\n");
10906
10907 if (0)
10908 {
10909 /* this test doesn't pass under Win9x: BUG! */
10910 SetLastError(0xdeadbeef);
10912 ok(!hhook, "global hook requires hModule != 0\n");
10913 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %d\n", GetLastError());
10914 }
10915
10916 SetLastError(0xdeadbeef);
10918 ok(!hhook, "SetWinEventHook with invalid proc should fail\n");
10919 ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */
10920 GetLastError() == 0xdeadbeef, /* Win9x */
10921 "unexpected error %d\n", GetLastError());
10922
10923 SetLastError(0xdeadbeef);
10924 ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
10925 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */
10926 GetLastError() == 0xdeadbeef, /* Win9x */
10927 "unexpected error %d\n", GetLastError());
10928
10929 if (!pSetWinEventHook || !pUnhookWinEvent) return;
10930
10931 /* even process local incontext hooks require hmodule */
10932 SetLastError(0xdeadbeef);
10933 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc,
10935 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
10936 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
10937 GetLastError() == 0xdeadbeef, /* Win9x */
10938 "unexpected error %d\n", GetLastError());
10939
10940 /* even thread local incontext hooks require hmodule */
10941 SetLastError(0xdeadbeef);
10942 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc,
10944 ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
10945 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
10946 GetLastError() == 0xdeadbeef, /* Win9x */
10947 "unexpected error %d\n", GetLastError());
10948
10949 if (0)
10950 {
10951 /* these 3 tests don't pass under Win9x */
10952 SetLastError(0xdeadbeef);
10953 hwinevent_hook = pSetWinEventHook(1, 0, 0, win_event_proc,
10955 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
10956 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError());
10957
10958 SetLastError(0xdeadbeef);
10959 hwinevent_hook = pSetWinEventHook(-1, 1, 0, win_event_proc,
10961 ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
10962 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError());
10963
10964 SetLastError(0xdeadbeef);
10965 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc,
10966 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT);
10967 ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n");
10968 ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %d\n", GetLastError());
10969 }
10970
10971 SetLastError(0xdeadbeef);
10972 hwinevent_hook = pSetWinEventHook(0, 0, 0, win_event_proc,
10974 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError());
10975 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10976 ret = pUnhookWinEvent(hwinevent_hook);
10977 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
10978
10979todo_wine {
10980 /* This call succeeds under win2k SP4, but fails under Wine.
10981 Does win2k test/use passed process id? */
10982 SetLastError(0xdeadbeef);
10983 hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc,
10984 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT);
10985 ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError());
10986 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10987 ret = pUnhookWinEvent(hwinevent_hook);
10988 ok( ret, "UnhookWinEvent error %d\n", GetLastError());
10989}
10990
10991 SetLastError(0xdeadbeef);
10992 ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n");
10993 ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
10994 GetLastError() == 0xdeadbeef, /* Win9x */
10995 "unexpected error %d\n", GetLastError());
10996}
10997
10999static HHOOK recursive_hook;
11001
11003{
11004 LRESULT res;
11005 MSG msg;
11006 BOOL b;
11007
11008 hook_depth++;
11011
11013 ok(b, "PeekMessage failed\n");
11014
11016
11017 hook_depth--;
11018 return res;
11019}
11020
11021static void test_recursive_hook(void)
11022{
11023 MSG msg;
11024 BOOL b;
11025
11026 hook_hwnd = CreateWindowA("Static", NULL, WS_POPUP, 0, 0, 200, 60, NULL, NULL, NULL, NULL);
11027 ok(hook_hwnd != NULL, "CreateWindow failed\n");
11028
11030 ok(recursive_hook != NULL, "SetWindowsHookEx failed\n");
11031
11033 PostMessageW(hook_hwnd, WM_USER+1, 0, 0);
11034
11035 hook_depth = 0;
11036 GetMessageW(&msg, hook_hwnd, 0, 0);
11037 ok(15 <= max_hook_depth && max_hook_depth < 45, "max_hook_depth = %d\n", max_hook_depth);
11038 trace("max_hook_depth = %d\n", max_hook_depth);
11039
11041 ok(b, "UnhokWindowsHookEx failed\n");
11042
11044}
11045
11046static const struct message ScrollWindowPaint1[] = {
11047 { WM_PAINT, sent },
11050 { WM_PAINT, sent|optional },
11057 { 0 }
11058};
11059
11060static const struct message ScrollWindowPaint2[] = {
11061 { WM_PAINT, sent },
11062 { 0 }
11063};
11064
11065static void test_scrollwindowex(void)
11066{
11067 HWND hwnd, hchild;
11068 RECT rect={0,0,130,130};
11069
11070 hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll",
11072 100, 100, 200, 200, 0, 0, 0, NULL);
11073 ok (hwnd != 0, "Failed to create overlapped window\n");
11074 hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
11076 10, 10, 150, 150, hwnd, 0, 0, NULL);
11077 ok (hchild != 0, "Failed to create child\n");
11079 flush_events();
11081
11082 /* scroll without the child window */
11083 trace("start scroll\n");
11084 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
11086 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE);
11087 trace("end scroll\n");
11089 flush_events();
11090 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE);
11091 flush_events();
11093
11094 /* Now without the SW_ERASE flag */
11095 trace("start scroll\n");
11097 ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE);
11098 trace("end scroll\n");
11100 flush_events();
11101 ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", FALSE);
11102 flush_events();
11104
11105 /* now scroll the child window as well */
11106 trace("start scroll\n");
11107 ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
11109 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
11110 /* windows sometimes a WM_MOVE */
11111 ok_sequence(WmEmptySeq, "ScrollWindowEx", TRUE);
11112 trace("end scroll\n");
11114 flush_events();
11115 ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE);
11116 flush_events();
11118
11119 /* now scroll with ScrollWindow() */
11120 trace("start scroll with ScrollWindow\n");
11121 ScrollWindow( hwnd, 5, 5, NULL, NULL);
11122 trace("end scroll\n");
11124 flush_events();
11125 ok_sequence(ScrollWindowPaint1, "ScrollWindow", FALSE);
11126
11127 ok(DestroyWindow(hchild), "failed to destroy window\n");
11128 ok(DestroyWindow(hwnd), "failed to destroy window\n");
11130}
11131
11132static const struct message destroy_window_with_children[] = {
11133 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
11134 { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */
11135 { 0x0090, sent|optional },
11136 { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */
11137 { 0x0090, sent|optional },
11138 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */
11139 { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
11140 { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
11141 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */
11142 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */
11143 { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
11144 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
11145 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
11146 { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
11147 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */
11148 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */
11149 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */
11150 { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */
11151 { 0 }
11152};
11153
11154static void test_DestroyWindow(void)
11155{
11156 BOOL ret;
11157 HWND parent, child1, child2, child3, child4, test;
11158 UINT_PTR child_id = WND_CHILD_ID + 1;
11159
11160 parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
11161 100, 100, 200, 200, 0, 0, 0, NULL);
11162 assert(parent != 0);
11163 child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
11164 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL);
11165 assert(child1 != 0);
11166 child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
11167 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL);
11168 assert(child2 != 0);
11169 child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD,
11170 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL);
11171 assert(child3 != 0);
11172 child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP,
11173 0, 0, 50, 50, parent, 0, 0, NULL);
11174 assert(child4 != 0);
11175
11176 /* test owner/parent of child2 */
11177 test = GetParent(child2);
11178 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
11179 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
11180 if(pGetAncestor) {
11181 test = pGetAncestor(child2, GA_PARENT);
11182 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
11183 }
11184 test = GetWindow(child2, GW_OWNER);
11185 ok(!test, "wrong owner %p\n", test);
11186
11187 test = SetParent(child2, parent);
11188 ok(test == GetDesktopWindow(), "wrong old parent %p\n", test);
11189
11190 /* test owner/parent of the parent */
11192 ok(!test, "wrong parent %p\n", test);
11193 ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent);
11194 if(pGetAncestor) {
11195 test = pGetAncestor(parent, GA_PARENT);
11196 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
11197 }
11199 ok(!test, "wrong owner %p\n", test);
11200
11201 /* test owner/parent of child1 */
11202 test = GetParent(child1);
11203 ok(test == parent, "wrong parent %p\n", test);
11204 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
11205 if(pGetAncestor) {
11206 test = pGetAncestor(child1, GA_PARENT);
11207 ok(test == parent, "wrong parent %p\n", test);
11208 }
11209 test = GetWindow(child1, GW_OWNER);
11210 ok(!test, "wrong owner %p\n", test);
11211
11212 /* test owner/parent of child2 */
11213 test = GetParent(child2);
11214 ok(test == parent, "wrong parent %p\n", test);
11215 ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
11216 if(pGetAncestor) {
11217 test = pGetAncestor(child2, GA_PARENT);
11218 ok(test == parent, "wrong parent %p\n", test);
11219 }
11220 test = GetWindow(child2, GW_OWNER);
11221 ok(!test, "wrong owner %p\n", test);
11222
11223 /* test owner/parent of child3 */
11224 test = GetParent(child3);
11225 ok(test == child1, "wrong parent %p\n", test);
11226 ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
11227 if(pGetAncestor) {
11228 test = pGetAncestor(child3, GA_PARENT);
11229 ok(test == child1, "wrong parent %p\n", test);
11230 }
11231 test = GetWindow(child3, GW_OWNER);
11232 ok(!test, "wrong owner %p\n", test);
11233
11234 /* test owner/parent of child4 */
11235 test = GetParent(child4);
11236 ok(test == parent, "wrong parent %p\n", test);
11237 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
11238 if(pGetAncestor) {
11239 test = pGetAncestor(child4, GA_PARENT);
11240 ok(test == GetDesktopWindow(), "wrong parent %p\n", test);
11241 }
11242 test = GetWindow(child4, GW_OWNER);
11243 ok(test == parent, "wrong owner %p\n", test);
11244
11246
11247 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
11248 parent, child1, child2, child3, child4);
11249
11250 SetCapture(child4);
11251 test = GetCapture();
11252 ok(test == child4, "wrong capture window %p\n", test);
11253
11256 ok( ret, "DestroyWindow() error %d\n", GetLastError());
11258 ok_sequence(destroy_window_with_children, "destroy window with children", FALSE);
11259
11260 ok(!IsWindow(parent), "parent still exists\n");
11261 ok(!IsWindow(child1), "child1 still exists\n");
11262 ok(!IsWindow(child2), "child2 still exists\n");
11263 ok(!IsWindow(child3), "child3 still exists\n");
11264 ok(!IsWindow(child4), "child4 still exists\n");
11265
11266 test = GetCapture();
11267 ok(!test, "wrong capture window %p\n", test);
11268}
11269
11270
11271static const struct message WmDispatchPaint[] = {
11272 { WM_NCPAINT, sent },
11275 { WM_ERASEBKGND, sent },
11276 { 0 }
11277};
11278
11280{
11281 if (message == WM_PAINT) return 0;
11282 return MsgCheckProcA( hwnd, message, wParam, lParam );
11283}
11284
11285static void test_DispatchMessage(void)
11286{
11287 RECT rect;
11288 MSG msg;
11289 int count;
11290 HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
11291 100, 100, 200, 200, 0, 0, 0, NULL);
11293 UpdateWindow( hwnd );
11294 flush_events();
11297
11298 SetRect( &rect, -5, -5, 5, 5 );
11300 count = 0;
11301 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
11302 {
11303 if (msg.message != WM_PAINT) DispatchMessageA( &msg );
11304 else
11305 {
11308 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
11309 if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
11310 else ok_sequence( WmEmptySeq, "WmEmpty", FALSE );
11311 if (++count > 10) break;
11312 }
11313 }
11314 ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" );
11315
11316 trace("now without DispatchMessage\n");
11319 count = 0;
11320 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
11321 {
11322 if (msg.message != WM_PAINT) DispatchMessageA( &msg );
11323 else
11324 {
11325 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
11327 /* this will send WM_NCCPAINT just like DispatchMessage does */
11329 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
11330 DeleteObject( hrgn );
11331 GetClientRect( hwnd, &rect );
11332 ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */
11333 ok( !count, "Got multiple WM_PAINTs\n" );
11334 if (++count > 10) break;
11335 }
11336 }
11337
11340 count = 0;
11341 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
11342 {
11343 if (msg.message != WM_PAINT) DispatchMessageA( &msg );
11344 else
11345 {
11346 HDC hdc;
11347
11349 hdc = BeginPaint( hwnd, NULL );
11350 ok( !hdc, "got valid hdc %p from BeginPaint\n", hdc );
11351 ok( !EndPaint( hwnd, NULL ), "EndPaint succeeded\n" );
11352 ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE );
11353 ok( !count, "Got multiple WM_PAINTs\n" );
11354 if (++count > 10) break;
11355 }
11356 }
11358}
11359
11360
11361static const struct message WmUser[] = {
11362 { WM_USER, sent },
11363 { 0 }
11364};
11365
11367{
11371};
11372
11374{
11375 struct sendmsg_info *info = arg;
11376 SetLastError( 0xdeadbeef );
11377 info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL );
11378 if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT ||
11379 broken(GetLastError() == 0), /* win9x */
11380 "unexpected error %d\n", GetLastError());
11381 return 0;
11382}
11383
11385{
11387 {
11388 MSG msg;
11389 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA(&msg);
11390 }
11391}
11392
11394{
11395 if (message == WM_USER) Sleep(200);
11396 return MsgCheckProcA( hwnd, message, wParam, lParam );
11397}
11398
11400{
11401 HANDLE thread;
11402 struct sendmsg_info info;
11403 DWORD tid;
11404 BOOL is_win9x;
11405
11406 info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
11407 100, 100, 200, 200, 0, 0, 0, NULL);
11408 flush_events();
11410
11411 info.timeout = 1000;
11412 info.ret = 0xdeadbeef;
11416 ok( info.ret == 1, "SendMessageTimeout failed\n" );
11417 ok_sequence( WmUser, "WmUser", FALSE );
11418
11419 info.timeout = 1;
11420 info.ret = 0xdeadbeef;
11422 Sleep(100); /* SendMessageTimeout should time out here */
11425 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
11426 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
11427
11428 /* 0 means infinite timeout (but not on win9x) */
11429 info.timeout = 0;
11430 info.ret = 0xdeadbeef;
11432 Sleep(100);
11435 is_win9x = !info.ret;
11436 if (is_win9x) ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
11437 else ok_sequence( WmUser, "WmUser", FALSE );
11438
11439 /* timeout is treated as signed despite the prototype (but not on win9x) */
11440 info.timeout = 0x7fffffff;
11441 info.ret = 0xdeadbeef;
11443 Sleep(100);
11446 ok( info.ret == 1, "SendMessageTimeout failed\n" );
11447 ok_sequence( WmUser, "WmUser", FALSE );
11448
11449 info.timeout = 0x80000000;
11450 info.ret = 0xdeadbeef;
11452 Sleep(100);
11455 if (is_win9x)
11456 {
11457 ok( info.ret == 1, "SendMessageTimeout failed\n" );
11458 ok_sequence( WmUser, "WmUser", FALSE );
11459 }
11460 else
11461 {
11462 ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
11463 ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
11464 }
11465
11466 /* now check for timeout during message processing */
11468 info.timeout = 100;
11469 info.ret = 0xdeadbeef;
11473 /* we should time out but still get the message */
11474 ok( info.ret == 0, "SendMessageTimeout failed\n" );
11475 ok_sequence( WmUser, "WmUser", FALSE );
11476
11477 DestroyWindow( info.hwnd );
11478}
11479
11480
11481/****************** edit message test *************************/
11482#define ID_EDIT 0x1234
11483static const struct message sl_edit_setfocus[] =
11484{
11485 { HCBT_SETFOCUS, hook },
11488 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
11489 { WM_SETFOCUS, sent|wparam, 0 },
11494 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11495 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11497 { 0 }
11498};
11499static const struct message sl_edit_invisible[] =
11500{
11501 { HCBT_SETFOCUS, hook },
11504 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
11506 { WM_SETFOCUS, sent },
11508 { 0 }
11509};
11510static const struct message ml_edit_setfocus[] =
11511{
11512 { HCBT_SETFOCUS, hook },
11515 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
11516 { WM_SETFOCUS, sent|wparam, 0 },
11519 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11520 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11522 { 0 }
11523};
11524static const struct message sl_edit_killfocus[] =
11525{
11526 { HCBT_SETFOCUS, hook },
11527 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
11528 { WM_KILLFOCUS, sent|wparam, 0 },
11529 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11530 { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11534 { 0 }
11535};
11536static const struct message sl_edit_lbutton_dblclk[] =
11537{
11539 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
11540 { 0 }
11541};
11542static const struct message sl_edit_lbutton_down[] =
11543{
11544 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
11545 { HCBT_SETFOCUS, hook },
11548 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
11553 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11554 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11555 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11557 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
11558 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11561 { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11562 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11563 { 0 }
11564};
11565static const struct message ml_edit_lbutton_down[] =
11566{
11567 { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
11568 { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
11569 { HCBT_SETFOCUS, hook },
11572 { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
11576 { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11577 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11579 { 0 }
11580};
11581static const struct message sl_edit_lbutton_up[] =
11582{
11583 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
11584 { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11585 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
11587 { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
11588 { 0 }
11589};
11590static const struct message ml_edit_lbutton_up[] =
11591{
11592 { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
11593 { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
11595 { 0 }
11596};
11597
11599
11601{
11602 static LONG defwndproc_counter = 0;
11603 LRESULT ret;
11604 struct recvd_message msg;
11605
11606 if (ignore_message( message )) return 0;
11607
11608 msg.hwnd = hwnd;
11609 msg.message = message;
11610 msg.flags = sent|wparam|lparam;
11611 if (defwndproc_counter) msg.flags |= defwinproc;
11612 msg.wParam = wParam;
11613 msg.lParam = lParam;
11614 msg.descr = "edit";
11615 add_message(&msg);
11616
11617 defwndproc_counter++;
11619 defwndproc_counter--;
11620
11621 return ret;
11622}
11623
11624static void subclass_edit(void)
11625{
11626 WNDCLASSA cls;
11627
11628 if (!GetClassInfoA(0, "edit", &cls)) assert(0);
11629
11631
11634 cls.lpszClassName = "my_edit_class";
11636 if (!RegisterClassA(&cls)) assert(0);
11637}
11638
11639static void test_edit_messages(void)
11640{
11641 HWND hwnd, parent;
11642 DWORD dlg_code;
11643
11644 subclass_edit();
11646
11647 parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
11648 100, 100, 200, 200, 0, 0, 0, NULL);
11649 ok (parent != 0, "Failed to create parent window\n");
11650
11651 /* test single line edit */
11652 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD,
11653 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
11654 ok(hwnd != 0, "Failed to create edit window\n");
11655
11656 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
11657 ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08x\n", dlg_code);
11658
11660 SetFocus(hwnd);
11661 ok_sequence(sl_edit_invisible, "SetFocus(hwnd) on an invisible edit", FALSE);
11662
11665 SetFocus(0);
11667
11668 SetFocus(hwnd);
11669 ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE);
11670
11671 SetFocus(0);
11672 ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE);
11673
11674 SetFocus(0);
11677
11679 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE);
11680
11681 SetFocus(0);
11684
11686 ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE);
11687
11689 ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE);
11690
11692
11693 /* test multiline edit */
11694 hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE,
11695 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
11696 ok(hwnd != 0, "Failed to create edit window\n");
11697
11698 dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
11700 "wrong dlg_code %08x\n", dlg_code);
11701
11704 SetFocus(0);
11706
11707 SetFocus(hwnd);
11708 ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE);
11709
11710 SetFocus(0);
11711 ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE);
11712
11713 SetFocus(0);
11716
11718 ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE);
11719
11720 SetFocus(0);
11723
11725 ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE);
11726
11728 ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE);
11729
11732
11734}
11735
11736/**************************** End of Edit test ******************************/
11737
11738static const struct message WmKeyDownSkippedSeq[] =
11739{
11740 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */
11741 { 0 }
11742};
11744{
11745 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x40000001 }, /* XP */
11746 { 0 }
11747};
11748static const struct message WmKeyUpSkippedSeq[] =
11749{
11750 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
11751 { 0 }
11752};
11753static const struct message WmUserKeyUpSkippedSeq[] =
11754{
11755 { WM_USER, sent },
11756 { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */
11757 { 0 }
11758};
11759
11760#define EV_STOP 0
11761#define EV_SENDMSG 1
11762#define EV_ACK 2
11763
11765{
11767 HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
11768};
11769
11771{
11772 DWORD ret;
11773 struct peekmsg_info *info = param;
11774
11775 trace("thread: looping\n");
11776 SetEvent(info->hevent[EV_ACK]);
11777
11778 while (1)
11779 {
11781
11782 switch (ret)
11783 {
11784 case WAIT_OBJECT_0 + EV_STOP:
11785 trace("thread: exiting\n");
11786 return 0;
11787
11789 trace("thread: sending message\n");
11790 ret = SendNotifyMessageA(info->hwnd, WM_USER, 0, 0);
11791 ok(ret, "SendNotifyMessageA failed error %u\n", GetLastError());
11792 SetEvent(info->hevent[EV_ACK]);
11793 break;
11794
11795 default:
11796 trace("unexpected return: %04x\n", ret);
11797 assert(0);
11798 break;
11799 }
11800 }
11801 return 0;
11802}
11803
11804static void test_PeekMessage(void)
11805{
11806 MSG msg;
11807 HANDLE hthread;
11808 DWORD tid, qstatus;
11809 UINT qs_all_input = QS_ALLINPUT;
11810 UINT qs_input = QS_INPUT;
11811 BOOL ret;
11812 struct peekmsg_info info;
11813
11814 info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
11815 100, 100, 200, 200, 0, 0, 0, NULL);
11816 assert(info.hwnd);
11817 ShowWindow(info.hwnd, SW_SHOW);
11818 UpdateWindow(info.hwnd);
11819 SetFocus(info.hwnd);
11820
11821 info.hevent[EV_STOP] = CreateEventA(NULL, 0, 0, NULL);
11822 info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL);
11823 info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL);
11824
11825 hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid);
11826 WaitForSingleObject(info.hevent[EV_ACK], 10000);
11827
11828 flush_events();
11830
11831 SetLastError(0xdeadbeef);
11832 qstatus = GetQueueStatus(qs_all_input);
11834 {
11835 trace("QS_RAWINPUT not supported on this platform\n");
11836 qs_all_input &= ~QS_RAWINPUT;
11837 qs_input &= ~QS_RAWINPUT;
11838 }
11839 if (qstatus & QS_POSTMESSAGE)
11840 {
11841 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) /* nothing */ ;
11842 qstatus = GetQueueStatus(qs_all_input);
11843 }
11844 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
11845
11846 trace("signalling to send message\n");
11847 SetEvent(info.hevent[EV_SENDMSG]);
11849
11850 /* pass invalid QS_xxxx flags */
11851 SetLastError(0xdeadbeef);
11852 qstatus = GetQueueStatus(0xffffffff);
11853 ok(qstatus == 0 || broken(qstatus) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus);
11854 if (!qstatus)
11855 {
11856 ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError());
11857 qstatus = GetQueueStatus(qs_all_input);
11858 }
11859 qstatus &= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
11861 "wrong qstatus %08x\n", qstatus);
11862
11863 msg.message = 0;
11864 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
11865 ok(!ret,
11866 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11867 msg.message);
11868 ok_sequence(WmUser, "WmUser", FALSE);
11869
11870 qstatus = GetQueueStatus(qs_all_input);
11871 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
11872
11873 keybd_event('N', 0, 0, 0);
11874 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
11875 qstatus = GetQueueStatus(qs_all_input);
11876 if (!(qstatus & MAKELONG(QS_KEY, QS_KEY)))
11877 {
11878 skip( "queuing key events not supported\n" );
11879 goto done;
11880 }
11881 ok(qstatus == MAKELONG(QS_KEY, QS_KEY) ||
11882 /* keybd_event seems to trigger a sent message on NT4 */
11884 "wrong qstatus %08x\n", qstatus);
11885
11886 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
11887 qstatus = GetQueueStatus(qs_all_input);
11890 "wrong qstatus %08x\n", qstatus);
11891
11892 InvalidateRect(info.hwnd, NULL, FALSE);
11893 qstatus = GetQueueStatus(qs_all_input);
11896 "wrong qstatus %08x\n", qstatus);
11897
11898 trace("signalling to send message\n");
11899 SetEvent(info.hevent[EV_SENDMSG]);
11901
11902 qstatus = GetQueueStatus(qs_all_input);
11904 "wrong qstatus %08x\n", qstatus);
11905
11906 msg.message = 0;
11907 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16));
11908 if (ret && msg.message == WM_CHAR)
11909 {
11910 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11911 goto done;
11912 }
11913 ok(!ret,
11914 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11915 msg.message);
11916 if (!sequence_cnt) /* nt4 doesn't fetch anything with PM_QS_* flags */
11917 {
11918 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11919 goto done;
11920 }
11921 ok_sequence(WmUser, "WmUser", FALSE);
11922
11923 qstatus = GetQueueStatus(qs_all_input);
11924 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
11925 "wrong qstatus %08x\n", qstatus);
11926
11927 trace("signalling to send message\n");
11928 SetEvent(info.hevent[EV_SENDMSG]);
11930
11931 qstatus = GetQueueStatus(qs_all_input);
11933 "wrong qstatus %08x\n", qstatus);
11934
11935 msg.message = 0;
11936 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE );
11937 ok(!ret,
11938 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11939 msg.message);
11940 ok_sequence(WmUser, "WmUser", FALSE);
11941
11942 qstatus = GetQueueStatus(qs_all_input);
11943 ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
11944 "wrong qstatus %08x\n", qstatus);
11945
11946 msg.message = 0;
11947 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
11948 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
11949 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11950 ret, msg.message, msg.wParam);
11951 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
11952
11953 qstatus = GetQueueStatus(qs_all_input);
11954 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
11955 "wrong qstatus %08x\n", qstatus);
11956
11957 msg.message = 0;
11958 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
11959 ok(!ret,
11960 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11961 msg.message);
11962 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
11963
11964 qstatus = GetQueueStatus(qs_all_input);
11965 ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
11966 "wrong qstatus %08x\n", qstatus);
11967
11968 msg.message = 0;
11969 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT);
11970 ok(ret && msg.message == WM_PAINT,
11971 "got %d and %04x instead of TRUE and WM_PAINT\n", ret, msg.message);
11973 ok_sequence(WmPaint, "WmPaint", FALSE);
11974
11975 qstatus = GetQueueStatus(qs_all_input);
11976 ok(qstatus == MAKELONG(0, QS_KEY),
11977 "wrong qstatus %08x\n", qstatus);
11978
11979 msg.message = 0;
11980 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT);
11981 ok(!ret,
11982 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11983 msg.message);
11984 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
11985
11986 qstatus = GetQueueStatus(qs_all_input);
11987 ok(qstatus == MAKELONG(0, QS_KEY),
11988 "wrong qstatus %08x\n", qstatus);
11989
11990 trace("signalling to send message\n");
11991 SetEvent(info.hevent[EV_SENDMSG]);
11993
11994 qstatus = GetQueueStatus(qs_all_input);
11996 "wrong qstatus %08x\n", qstatus);
11997
11998 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
11999
12000 qstatus = GetQueueStatus(qs_all_input);
12002 "wrong qstatus %08x\n", qstatus);
12003
12004 msg.message = 0;
12006 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
12007 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
12008 ret, msg.message, msg.wParam);
12009 ok_sequence(WmUser, "WmUser", FALSE);
12010
12011 qstatus = GetQueueStatus(qs_all_input);
12012 ok(qstatus == MAKELONG(0, QS_KEY),
12013 "wrong qstatus %08x\n", qstatus);
12014
12015 msg.message = 0;
12017 ok(!ret,
12018 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12019 msg.message);
12020 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
12021
12022 qstatus = GetQueueStatus(qs_all_input);
12023 ok(qstatus == MAKELONG(0, QS_KEY),
12024 "wrong qstatus %08x\n", qstatus);
12025
12026 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
12027
12028 qstatus = GetQueueStatus(qs_all_input);
12030 "wrong qstatus %08x\n", qstatus);
12031
12032 trace("signalling to send message\n");
12033 SetEvent(info.hevent[EV_SENDMSG]);
12035
12036 qstatus = GetQueueStatus(qs_all_input);
12038 "wrong qstatus %08x\n", qstatus);
12039
12040 msg.message = 0;
12041 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16));
12042 ok(!ret,
12043 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12044 msg.message);
12045 ok_sequence(WmUser, "WmUser", FALSE);
12046
12047 qstatus = GetQueueStatus(qs_all_input);
12048 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
12049 "wrong qstatus %08x\n", qstatus);
12050
12051 msg.message = 0;
12052 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */
12053 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16));
12054 else /* workaround for a missing QS_RAWINPUT support */
12056 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N',
12057 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12058 ret, msg.message, msg.wParam);
12059 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE);
12060
12061 qstatus = GetQueueStatus(qs_all_input);
12062 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
12063 "wrong qstatus %08x\n", qstatus);
12064
12065 msg.message = 0;
12066 if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */
12067 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16));
12068 else /* workaround for a missing QS_RAWINPUT support */
12070 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N',
12071 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n",
12072 ret, msg.message, msg.wParam);
12073 ok_sequence(WmKeyUpSkippedSeq, "WmKeyUpSkippedSeq", FALSE);
12074
12075 qstatus = GetQueueStatus(qs_all_input);
12076 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
12077 "wrong qstatus %08x\n", qstatus);
12078
12079 msg.message = 0;
12080 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE);
12081 ok(!ret,
12082 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12083 msg.message);
12084 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
12085
12086 qstatus = GetQueueStatus(qs_all_input);
12087 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
12088 "wrong qstatus %08x\n", qstatus);
12089
12090 msg.message = 0;
12091 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
12092 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
12093 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
12094 ret, msg.message, msg.wParam);
12095 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
12096
12097 qstatus = GetQueueStatus(qs_all_input);
12098 ok(qstatus == 0,
12099 "wrong qstatus %08x\n", qstatus);
12100
12101 msg.message = 0;
12102 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
12103 ok(!ret,
12104 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12105 msg.message);
12106 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
12107
12108 qstatus = GetQueueStatus(qs_all_input);
12109 ok(qstatus == 0,
12110 "wrong qstatus %08x\n", qstatus);
12111
12112 /* test whether presence of the quit flag in the queue affects
12113 * the queue state
12114 */
12115 PostQuitMessage(0x1234abcd);
12116
12117 qstatus = GetQueueStatus(qs_all_input);
12119 "wrong qstatus %08x\n", qstatus);
12120
12121 PostMessageA(info.hwnd, WM_USER, 0, 0);
12122
12123 qstatus = GetQueueStatus(qs_all_input);
12125 "wrong qstatus %08x\n", qstatus);
12126
12127 msg.message = 0;
12128 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
12129 ok(ret && msg.message == WM_USER,
12130 "got %d and %04x instead of TRUE and WM_USER\n", ret, msg.message);
12131 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
12132
12133 qstatus = GetQueueStatus(qs_all_input);
12134 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
12135 "wrong qstatus %08x\n", qstatus);
12136
12137 msg.message = 0;
12138 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
12139 ok(ret && msg.message == WM_QUIT,
12140 "got %d and %04x instead of TRUE and WM_QUIT\n", ret, msg.message);
12141 ok(msg.wParam == 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg.wParam);
12142 ok(msg.lParam == 0, "got lParam %08lx instead of 0\n", msg.lParam);
12143 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
12144
12145 qstatus = GetQueueStatus(qs_all_input);
12146todo_wine {
12147 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
12148 "wrong qstatus %08x\n", qstatus);
12149}
12150
12151 msg.message = 0;
12152 ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
12153 ok(!ret,
12154 "PeekMessageA should have returned FALSE instead of msg %04x\n",
12155 msg.message);
12156 ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
12157
12158 qstatus = GetQueueStatus(qs_all_input);
12159 ok(qstatus == 0,
12160 "wrong qstatus %08x\n", qstatus);
12161
12162 /* some GetMessage tests */
12163
12164 keybd_event('N', 0, 0, 0);
12165 qstatus = GetQueueStatus(qs_all_input);
12166 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus);
12167
12168 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
12169 qstatus = GetQueueStatus(qs_all_input);
12170 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
12171
12172 if (qstatus)
12173 {
12174 ret = GetMessageA( &msg, 0, 0, 0 );
12175 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
12176 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
12177 ret, msg.message, msg.wParam);
12178 qstatus = GetQueueStatus(qs_all_input);
12179 ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus);
12180 }
12181
12182 if (qstatus)
12183 {
12184 ret = GetMessageA( &msg, 0, 0, 0 );
12185 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N',
12186 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12187 ret, msg.message, msg.wParam);
12188 ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE);
12189 qstatus = GetQueueStatus(qs_all_input);
12190 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
12191 }
12192
12193 keybd_event('N', 0, 0, 0);
12194 qstatus = GetQueueStatus(qs_all_input);
12195 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus);
12196
12197 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
12198 qstatus = GetQueueStatus(qs_all_input);
12199 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
12200
12201 if (qstatus & (QS_KEY << 16))
12202 {
12204 ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N',
12205 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12206 ret, msg.message, msg.wParam);
12207 ok_sequence(WmKeyDownWasDownSkippedSeq, "WmKeyDownWasDownSkippedSeq", FALSE);
12208 qstatus = GetQueueStatus(qs_all_input);
12209 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);
12210 }
12211
12212 if (qstatus)
12213 {
12214 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR );
12215 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
12216 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
12217 ret, msg.message, msg.wParam);
12218 qstatus = GetQueueStatus(qs_all_input);
12219 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
12220 }
12221
12222 keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
12223 qstatus = GetQueueStatus(qs_all_input);
12224 ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus);
12225
12226 PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
12227 qstatus = GetQueueStatus(qs_all_input);
12228 ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
12229
12230 trace("signalling to send message\n");
12231 SetEvent(info.hevent[EV_SENDMSG]);
12233 qstatus = GetQueueStatus(qs_all_input);
12235 "wrong qstatus %08x\n", qstatus);
12236
12237 if (qstatus & (QS_KEY << 16))
12238 {
12240 ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N',
12241 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
12242 ret, msg.message, msg.wParam);
12243 ok_sequence(WmUserKeyUpSkippedSeq, "WmUserKeyUpSkippedSeq", FALSE);
12244 qstatus = GetQueueStatus(qs_all_input);
12245 ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);
12246 }
12247
12248 if (qstatus)
12249 {
12250 ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR );
12251 ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
12252 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
12253 ret, msg.message, msg.wParam);
12254 qstatus = GetQueueStatus(qs_all_input);
12255 ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
12256 }
12257
12259 ret = PeekMessageA(&msg, (HWND)-1, 0, 0, PM_NOREMOVE);
12260 ok(ret == TRUE, "wrong ret %d\n", ret);
12261 ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
12262 ret = GetMessageA(&msg, (HWND)-1, 0, 0);
12263 ok(ret == TRUE, "wrong ret %d\n", ret);
12264 ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
12265
12267 ret = PeekMessageA(&msg, (HWND)1, 0, 0, PM_NOREMOVE);
12268 ok(ret == TRUE, "wrong ret %d\n", ret);
12269 ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
12270 ret = GetMessageA(&msg, (HWND)1, 0, 0);
12271 ok(ret == TRUE, "wrong ret %d\n", ret);
12272 ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
12273
12275 ret = PeekMessageA(&msg, (HWND)0xffff, 0, 0, PM_NOREMOVE);
12276 ok(ret == TRUE, "wrong ret %d\n", ret);
12277 ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
12278 ret = GetMessageA(&msg, (HWND)0xffff, 0, 0);
12279 ok(ret == TRUE, "wrong ret %d\n", ret);
12280 ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
12281
12282done:
12283 trace("signalling to exit\n");
12284 SetEvent(info.hevent[EV_STOP]);
12285
12286 WaitForSingleObject(hthread, INFINITE);
12287
12288 CloseHandle(hthread);
12289 CloseHandle(info.hevent[0]);
12290 CloseHandle(info.hevent[1]);
12291 CloseHandle(info.hevent[2]);
12292
12293 DestroyWindow(info.hwnd);
12294}
12295
12296static void wait_move_event(HWND hwnd, int x, int y)
12297{
12298 MSG msg;
12299 DWORD time;
12300 BOOL ret;
12301
12302 time = GetTickCount();
12303 while (GetTickCount() - time < 200) {
12305 if (ret && msg.pt.x > x && msg.pt.y > y) break;
12307 else Sleep( GetTickCount() - time );
12308 }
12309}
12310
12311#define STEP 5
12312static void test_PeekMessage2(void)
12313{
12314 HWND hwnd;
12315 BOOL ret;
12316 MSG msg;
12317 UINT message;
12318 DWORD time1, time2, time3;
12319 int x1, y1, x2, y2, x3, y3;
12320 POINT pos;
12321
12322 time1 = time2 = time3 = 0;
12323 x1 = y1 = x2 = y2 = x3 = y3 = 0;
12324
12325 /* Initialise window and make sure it is ready for events */
12326 hwnd = CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW,
12327 10, 10, 800, 800, NULL, NULL, NULL, NULL);
12328 assert(hwnd);
12329 trace("Window for test_PeekMessage2 %p\n", hwnd);
12332 SetFocus(hwnd);
12333 GetCursorPos(&pos);
12334 SetCursorPos(100, 100);
12336 flush_events();
12337
12338 /* Do initial mousemove, wait until we can see it
12339 and then do our test peek with PM_NOREMOVE. */
12341 wait_move_event(hwnd, 100-STEP, 100-STEP);
12342
12344 if (!ret)
12345 {
12346 skip( "queuing mouse events not supported\n" );
12347 goto done;
12348 }
12349 else
12350 {
12351 trace("1st move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y);
12352 message = msg.message;
12353 time1 = msg.time;
12354 x1 = msg.pt.x;
12355 y1 = msg.pt.y;
12356 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message);
12357 }
12358
12359 /* Allow time to advance a bit, and then simulate the user moving their
12360 * mouse around. After that we peek again with PM_NOREMOVE.
12361 * Although the previous mousemove message was never removed, the
12362 * mousemove we now peek should reflect the recent mouse movements
12363 * because the input queue will merge the move events. */
12364 Sleep(100);
12367
12369 ok(ret, "no message available\n");
12370 if (ret) {
12371 trace("2nd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y);
12372 message = msg.message;
12373 time2 = msg.time;
12374 x2 = msg.pt.x;
12375 y2 = msg.pt.y;
12376 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message);
12377 ok(time2 > time1, "message time not advanced: %x %x\n", time1, time2);
12378 ok(x2 != x1 && y2 != y1, "coords not changed: (%d %d) (%d %d)\n", x1, y1, x2, y2);
12379 }
12380
12381 /* Have another go, to drive the point home */
12382 Sleep(100);
12385
12387 ok(ret, "no message available\n");
12388 if (ret) {
12389 trace("3rd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y);
12390 message = msg.message;
12391 time3 = msg.time;
12392 x3 = msg.pt.x;
12393 y3 = msg.pt.y;
12394 ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message);
12395 ok(time3 > time2, "message time not advanced: %x %x\n", time2, time3);
12396 ok(x3 != x2 && y3 != y2, "coords not changed: (%d %d) (%d %d)\n", x2, y2, x3, y3);
12397 }
12398
12399done:
12401 SetCursorPos(pos.x, pos.y);
12402 flush_events();
12403}
12404
12405static void test_PeekMessage3(void)
12406{
12407 HWND hwnd;
12408 BOOL ret;
12409 MSG msg;
12410
12411 hwnd = CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW,
12412 10, 10, 800, 800, NULL, NULL, NULL, NULL);
12413 ok(hwnd != NULL, "expected hwnd != NULL\n");
12414 flush_events();
12415
12416 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
12417 * were already seen. */
12418
12419 SetTimer(hwnd, 1, 0, NULL);
12420 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE));
12421 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12422 PostMessageA(hwnd, WM_USER, 0, 0);
12423 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE);
12424 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12425 ret = GetMessageA(&msg, NULL, 0, 0);
12426 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12427 ret = GetMessageA(&msg, NULL, 0, 0);
12428 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12429 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12430 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12431
12432 SetTimer(hwnd, 1, 0, NULL);
12433 while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE));
12434 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12435 PostMessageA(hwnd, WM_USER, 0, 0);
12436 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
12437 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12438 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
12439 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12440 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12441 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12442
12443 /* It doesn't matter if a message range is specified or not. */
12444
12445 SetTimer(hwnd, 1, 0, NULL);
12447 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12448 PostMessageA(hwnd, WM_USER, 0, 0);
12449 ret = GetMessageA(&msg, NULL, 0, 0);
12450 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12451 ret = GetMessageA(&msg, NULL, 0, 0);
12452 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12453 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12454 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12455
12456 /* But not if the post messages were added before the PeekMessage() call. */
12457
12458 PostMessageA(hwnd, WM_USER, 0, 0);
12459 SetTimer(hwnd, 1, 0, NULL);
12461 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12462 ret = GetMessageA(&msg, NULL, 0, 0);
12463 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12464 ret = GetMessageA(&msg, NULL, 0, 0);
12465 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12466 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12467 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12468
12469 /* More complicated test with multiple messages. */
12470
12471 PostMessageA(hwnd, WM_USER, 0, 0);
12472 SetTimer(hwnd, 1, 0, NULL);
12474 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12475 PostMessageA(hwnd, WM_USER + 1, 0, 0);
12476 ret = GetMessageA(&msg, NULL, 0, 0);
12477 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12478 ret = GetMessageA(&msg, NULL, 0, 0);
12479 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12480 ret = GetMessageA(&msg, NULL, 0, 0);
12481 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message);
12482 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12483 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12484
12485 /* Newer messages are still returned when specifying a message range. */
12486
12487 SetTimer(hwnd, 1, 0, NULL);
12489 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12490 PostMessageA(hwnd, WM_USER + 1, 0, 0);
12491 PostMessageA(hwnd, WM_USER, 0, 0);
12493 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12495 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message);
12496 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
12497 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12498 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
12499 ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message);
12500 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
12501 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12502 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12503 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12504
12505 /* Also works for posted messages, but the situation is a bit different,
12506 * because both messages are in the same queue. */
12507
12508 PostMessageA(hwnd, WM_TIMER, 0, 0);
12510 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12511 PostMessageA(hwnd, WM_USER, 0, 0);
12512 ret = GetMessageA(&msg, NULL, 0, 0);
12513 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12514 ret = GetMessageA(&msg, NULL, 0, 0);
12515 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12516 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12517 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12518
12519 PostMessageA(hwnd, WM_USER, 0, 0);
12520 PostMessageA(hwnd, WM_TIMER, 0, 0);
12522 ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12523 ret = GetMessageA(&msg, NULL, 0, 0);
12524 ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
12525 ret = GetMessageA(&msg, NULL, 0, 0);
12526 ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
12527 ret = PeekMessageA(&msg, NULL, 0, 0, 0);
12528 ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
12529
12531 flush_events();
12532}
12533
12535{
12536 struct recvd_message msg;
12537
12538 if (ignore_message( message )) return 0;
12539
12540 msg.hwnd = hwnd;
12541 msg.message = message;
12542 msg.flags = sent|wparam|lparam;
12543 msg.wParam = wp;
12544 msg.lParam = lp;
12545 msg.descr = "dialog";
12546 add_message(&msg);
12547
12548 switch (message)
12549 {
12550 case WM_INITDIALOG:
12551 PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678);
12552 PostMessageA(hwnd, WM_USER, 0xdead, 0xbeef);
12553 return 0;
12554
12555 case WM_GETDLGCODE:
12556 return 0;
12557
12558 case WM_USER:
12559 EndDialog(hwnd, 0);
12560 break;
12561 }
12562
12563 return 1;
12564}
12565
12566static const struct message WmQuitDialogSeq[] = {
12567 { HCBT_CREATEWND, hook },
12568 { WM_SETFONT, sent },
12569 { WM_INITDIALOG, sent },
12570 { WM_CHANGEUISTATE, sent|optional },
12571 { HCBT_DESTROYWND, hook },
12572 { 0x0090, sent|optional }, /* Vista */
12573 { WM_DESTROY, sent },
12574 { WM_NCDESTROY, sent },
12575 { 0 }
12576};
12577
12578static const struct message WmStopQuitSeq[] = {
12580 { WM_CLOSE, posted },
12581 { WM_QUIT, posted|wparam|lparam, 0x1234, 0 },
12582 { 0 }
12583};
12584
12585static void test_quit_message(void)
12586{
12587 MSG msg;
12588 BOOL ret;
12589
12590 /* test using PostQuitMessage */
12591 flush_events();
12592 PostQuitMessage(0xbeef);
12593
12594 msg.message = 0;
12595 ret = PeekMessageA(&msg, 0, 0, 0, PM_QS_SENDMESSAGE);
12596 ok(!ret, "got %x message\n", msg.message);
12597
12598 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE);
12599 ok(ret, "PeekMessage failed with error %d\n", GetLastError());
12600 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
12601 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam);
12602
12604 ok(ret, "PostMessage failed with error %d\n", GetLastError());
12605
12606 ret = GetMessageA(&msg, NULL, 0, 0);
12607 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError());
12608 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
12609
12610 /* note: WM_QUIT message received after WM_USER message */
12611 ret = GetMessageA(&msg, NULL, 0, 0);
12612 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError());
12613 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
12614 ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam);
12615
12616 ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
12617 ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" );
12618
12619 /* now test with PostThreadMessage - different behaviour! */
12621
12622 ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE);
12623 ok(ret, "PeekMessage failed with error %d\n", GetLastError());
12624 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
12625 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam);
12626
12628 ok(ret, "PostMessage failed with error %d\n", GetLastError());
12629
12630 /* note: we receive the WM_QUIT message first this time */
12631 ret = GetMessageA(&msg, NULL, 0, 0);
12632 ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError());
12633 ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
12634 ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam);
12635
12636 ret = GetMessageA(&msg, NULL, 0, 0);
12637 ok(ret > 0, "GetMessage failed with error %d\n", GetLastError());
12638 ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
12639
12640 flush_events();
12642 ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc, 0);
12643 ok(ret == 1, "expected 1, got %d\n", ret);