2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004, 2005 Dmitry Timoshkov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define _WIN32_WINNT 0x0500 /* For WM_CHANGEUISTATE */
34 #include "wine/test.h"
36 #define MDI_FIRST_CHILD_ID 2004
38 /* undocumented SWP flags - from SDK 3.1 */
39 #define SWP_NOCLIENTSIZE 0x0800
40 #define SWP_NOCLIENTMOVE 0x1000
42 #define WND_PARENT_ID 1
43 #define WND_POPUP_ID 2
44 #define WND_CHILD_ID 3
46 static BOOL test_DestroyWindow_flag
;
47 static HWINEVENTHOOK hEvent_hook
;
49 static HWND (WINAPI
*pGetAncestor
)(HWND
,UINT
);
52 FIXME: add tests for these
53 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
54 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
55 WS_THICKFRAME: thick border
56 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
57 WS_BORDER (default for overlapped windows): single black border
58 none (default for child (and popup?) windows): no border
75 UINT message
; /* the WM_* code */
76 msg_flags_t flags
; /* message props */
77 WPARAM wParam
; /* expected value of wParam */
78 LPARAM lParam
; /* expected value of lParam */
81 /* Empty message sequence */
82 static const struct message WmEmptySeq
[] =
86 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
87 static const struct message WmCreateOverlappedSeq
[] = {
88 { HCBT_CREATEWND
, hook
},
89 { WM_GETMINMAXINFO
, sent
},
90 { WM_NCCREATE
, sent
},
91 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
92 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
94 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
97 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
98 * for a not visible overlapped window.
100 static const struct message WmSWP_ShowOverlappedSeq
[] = {
101 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
102 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
103 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
104 { WM_GETTEXT
, sent
|defwinproc
|optional
},
105 { WM_ERASEBKGND
, sent
|optional
},
106 { HCBT_ACTIVATE
, hook
},
107 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
108 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
109 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
110 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
111 { WM_NCACTIVATE
, sent
|wparam
, 1 },
112 { WM_GETTEXT
, sent
|defwinproc
|optional
},
113 { WM_ACTIVATE
, sent
|wparam
, 1 },
114 { HCBT_SETFOCUS
, hook
},
115 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
116 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
117 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
118 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
119 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
120 { WM_GETTEXT
, sent
|defwinproc
|optional
},
121 { WM_ERASEBKGND
, sent
|optional
},
122 /* Win9x adds SWP_NOZORDER below */
123 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
124 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
125 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
126 { WM_ERASEBKGND
, sent
|optional
},
129 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
130 * for a visible overlapped window.
132 static const struct message WmSWP_HideOverlappedSeq
[] = {
133 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
134 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
135 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
139 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
140 * for a visible overlapped window.
142 static const struct message WmSWP_ResizeSeq
[] = {
143 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOMOVE
},
144 { WM_GETMINMAXINFO
, sent
|defwinproc
},
145 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
146 { WM_NCPAINT
, sent
|optional
},
147 { WM_GETTEXT
, sent
|defwinproc
|optional
},
148 { WM_ERASEBKGND
, sent
|optional
},
149 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
150 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
151 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
152 { WM_NCPAINT
, sent
|optional
},
153 { WM_GETTEXT
, sent
|defwinproc
|optional
},
154 { WM_ERASEBKGND
, sent
|optional
},
155 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
159 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
160 * for a visible popup window.
162 static const struct message WmSWP_ResizePopupSeq
[] = {
163 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOMOVE
},
164 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
165 { WM_NCPAINT
, sent
|optional
},
166 { WM_GETTEXT
, sent
|defwinproc
|optional
},
167 { WM_ERASEBKGND
, sent
|optional
},
168 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
169 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
170 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
171 { WM_NCPAINT
, sent
|optional
},
172 { WM_GETTEXT
, sent
|defwinproc
|optional
},
173 { WM_ERASEBKGND
, sent
|optional
},
174 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
178 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
179 * for a visible overlapped window.
181 static const struct message WmSWP_MoveSeq
[] = {
182 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
},
183 { WM_NCPAINT
, sent
|optional
},
184 { WM_GETTEXT
, sent
|defwinproc
|optional
},
185 { WM_ERASEBKGND
, sent
|optional
},
186 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
},
187 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
188 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
192 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
193 SWP_NOZORDER|SWP_FRAMECHANGED)
194 * for a visible overlapped window with WS_CLIPCHILDREN style set.
196 static const struct message WmSWP_FrameChanged_clip
[] = {
197 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
},
198 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
199 { WM_NCPAINT
, sent
|parent
}, /* wparam != 1 */
200 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
201 { WM_NCPAINT
, sent
}, /* wparam != 1 */
202 { WM_ERASEBKGND
, sent
},
203 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
207 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
208 SWP_NOZORDER|SWP_FRAMECHANGED)
209 * for a visible overlapped window.
211 static const struct message WmSWP_FrameChangedDeferErase
[] = {
212 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
},
213 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
214 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
215 { WM_PAINT
, sent
|parent
},
216 { WM_NCPAINT
, sent
|beginpaint
|parent
}, /* wparam != 1 */
218 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
219 { WM_ERASEBKGND
, sent
|beginpaint
},
223 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
224 SWP_NOZORDER|SWP_FRAMECHANGED)
225 * for a visible overlapped window without WS_CLIPCHILDREN style set.
227 static const struct message WmSWP_FrameChanged_noclip
[] = {
228 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
},
229 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
230 { WM_NCPAINT
, sent
|parent
}, /* wparam != 1 */
231 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
232 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
234 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
235 { WM_ERASEBKGND
, sent
|beginpaint
},
239 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
240 static const struct message WmShowOverlappedSeq
[] = {
241 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
242 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
243 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
244 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
245 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
246 { WM_GETTEXT
, sent
|defwinproc
|optional
},
247 { WM_ERASEBKGND
, sent
|optional
},
248 { HCBT_ACTIVATE
, hook
},
249 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
250 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
251 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
252 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
253 { WM_NCACTIVATE
, sent
|wparam
, 1 },
254 { WM_GETTEXT
, sent
|defwinproc
|optional
},
255 { WM_ACTIVATE
, sent
|wparam
, 1 },
256 { HCBT_SETFOCUS
, hook
},
257 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
258 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
259 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
260 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
261 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
262 { WM_GETTEXT
, sent
|defwinproc
|optional
},
263 { WM_ERASEBKGND
, sent
|optional
},
264 /* Win9x adds SWP_NOZORDER below */
265 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
266 { WM_NCCALCSIZE
, sent
|optional
},
267 { WM_NCPAINT
, sent
|optional
},
268 { WM_ERASEBKGND
, sent
|optional
},
269 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
270 * messages. Does that mean that CreateWindow doesn't set initial
271 * window dimensions for overlapped windows?
278 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
279 static const struct message WmShowMaxOverlappedSeq
[] = {
280 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
281 { WM_GETMINMAXINFO
, sent
},
282 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|0x8000 },
283 { WM_GETMINMAXINFO
, sent
|defwinproc
},
284 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
285 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
286 { HCBT_ACTIVATE
, hook
},
287 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
288 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
289 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
290 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
291 { WM_NCACTIVATE
, sent
|wparam
, 1 },
292 { WM_GETTEXT
, sent
|defwinproc
|optional
},
293 { WM_ACTIVATE
, sent
|wparam
, 1 },
294 { HCBT_SETFOCUS
, hook
},
295 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
296 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
297 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
298 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
299 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
300 { WM_GETTEXT
, sent
|defwinproc
|optional
},
301 { WM_ERASEBKGND
, sent
|optional
},
302 /* Win9x adds SWP_NOZORDER below */
303 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
304 { WM_MOVE
, sent
|defwinproc
},
305 { WM_SIZE
, sent
|defwinproc
},
306 { WM_NCCALCSIZE
, sent
|optional
},
307 { WM_NCPAINT
, sent
|optional
},
308 { WM_ERASEBKGND
, sent
|optional
},
309 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
310 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
313 /* ShowWindow(SW_HIDE) for a visible overlapped window */
314 static const struct message WmHideOverlappedSeq
[] = {
315 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
316 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
317 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
318 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
321 { WM_NCACTIVATE
, sent
|wparam
, 0 },
322 { WM_ACTIVATE
, sent
|wparam
, 0 },
323 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
324 { WM_KILLFOCUS
, sent
|wparam
, 0 },
325 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
326 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
329 /* DestroyWindow for a visible overlapped window */
330 static const struct message WmDestroyOverlappedSeq
[] = {
331 { HCBT_DESTROYWND
, hook
},
332 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
333 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
334 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
335 { WM_NCACTIVATE
, sent
|wparam
, 0 },
336 { WM_ACTIVATE
, sent
|wparam
, 0 },
337 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
338 { WM_KILLFOCUS
, sent
|wparam
, 0 },
339 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
340 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
341 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
342 { WM_DESTROY
, sent
},
343 { WM_NCDESTROY
, sent
},
346 /* CreateWindow (for a child popup window, not initially visible) */
347 static const struct message WmCreateChildPopupSeq
[] = {
348 { HCBT_CREATEWND
, hook
},
349 { WM_NCCREATE
, sent
},
350 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
352 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
357 /* CreateWindow (for a popup window, not initially visible,
358 * which sets WS_VISIBLE in WM_CREATE handler)
360 static const struct message WmCreateInvisiblePopupSeq
[] = {
361 { HCBT_CREATEWND
, hook
},
362 { WM_NCCREATE
, sent
},
363 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
365 { WM_STYLECHANGING
, sent
},
366 { WM_STYLECHANGED
, sent
},
367 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
372 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
373 * for a popup window with WS_VISIBLE style set
375 static const struct message WmShowVisiblePopupSeq_2
[] = {
376 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
379 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
380 * for a popup window with WS_VISIBLE style set
382 static const struct message WmShowVisiblePopupSeq_3
[] = {
383 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
384 { HCBT_ACTIVATE
, hook
},
385 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
386 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
387 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
388 { WM_NCACTIVATE
, sent
|wparam
, 1 },
389 { WM_ACTIVATE
, sent
|wparam
, 1 },
390 { HCBT_SETFOCUS
, hook
},
391 { WM_KILLFOCUS
, sent
|parent
},
392 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
393 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
394 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
395 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
396 { WM_SETFOCUS
, sent
|defwinproc
},
399 /* CreateWindow (for child window, not initially visible) */
400 static const struct message WmCreateChildSeq
[] = {
401 { HCBT_CREATEWND
, hook
},
402 { WM_NCCREATE
, sent
},
403 /* child is inserted into parent's child list after WM_NCCREATE returns */
404 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
406 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
409 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
412 /* CreateWindow (for maximized child window, not initially visible) */
413 static const struct message WmCreateMaximizedChildSeq
[] = {
414 { HCBT_CREATEWND
, hook
},
415 { WM_NCCREATE
, sent
},
416 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
418 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
421 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
422 { WM_GETMINMAXINFO
, sent
},
423 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
424 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
425 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|0x8000 },
426 { WM_SIZE
, sent
|defwinproc
},
427 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
428 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
431 /* CreateWindow (for a child window, initially visible) */
432 static const struct message WmCreateVisibleChildSeq
[] = {
433 { HCBT_CREATEWND
, hook
},
434 { WM_NCCREATE
, sent
},
435 /* child is inserted into parent's child list after WM_NCCREATE returns */
436 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
437 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
439 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
442 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
443 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
444 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
},
445 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
446 { WM_ERASEBKGND
, sent
|parent
|optional
},
447 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
448 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
451 /* ShowWindow(SW_SHOW) for a not visible child window */
452 static const struct message WmShowChildSeq
[] = {
453 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
454 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
455 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
456 { WM_ERASEBKGND
, sent
|parent
|optional
},
457 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
460 /* ShowWindow(SW_HIDE) for a visible child window */
461 static const struct message WmHideChildSeq
[] = {
462 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
463 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
464 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
465 { WM_ERASEBKGND
, sent
|parent
|optional
},
466 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
469 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
470 * for a not visible child window
472 static const struct message WmShowChildSeq_2
[] = {
473 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
474 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
475 { WM_CHILDACTIVATE
, sent
},
476 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
479 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
480 * for a not visible child window
482 static const struct message WmShowChildSeq_3
[] = {
483 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
484 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
485 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
488 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
489 * for a visible child window with a caption
491 static const struct message WmShowChildSeq_4
[] = {
492 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
493 { WM_CHILDACTIVATE
, sent
},
496 /* ShowWindow(SW_SHOW) for child with invisible parent */
497 static const struct message WmShowChildInvisibleParentSeq
[] = {
498 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
501 /* ShowWindow(SW_HIDE) for child with invisible parent */
502 static const struct message WmHideChildInvisibleParentSeq
[] = {
503 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
506 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
507 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
508 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
},
509 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
510 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
513 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
514 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
515 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
516 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
517 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
520 /* DestroyWindow for a visible child window */
521 static const struct message WmDestroyChildSeq
[] = {
522 { HCBT_DESTROYWND
, hook
},
523 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
524 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
525 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
526 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
527 { WM_ERASEBKGND
, sent
|parent
|optional
},
528 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
529 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
530 { WM_KILLFOCUS
, sent
},
531 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
532 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
533 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
534 { WM_SETFOCUS
, sent
|parent
},
535 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
536 { WM_DESTROY
, sent
},
537 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
538 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
539 { WM_NCDESTROY
, sent
},
542 /* Moving the mouse in nonclient area */
543 static const struct message WmMouseMoveInNonClientAreaSeq
[] = { /* FIXME: add */
544 { WM_NCHITTEST
, sent
},
545 { WM_SETCURSOR
, sent
},
546 { WM_NCMOUSEMOVE
, posted
},
549 /* Moving the mouse in client area */
550 static const struct message WmMouseMoveInClientAreaSeq
[] = { /* FIXME: add */
551 { WM_NCHITTEST
, sent
},
552 { WM_SETCURSOR
, sent
},
553 { WM_MOUSEMOVE
, posted
},
556 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
557 static const struct message WmDragTitleBarSeq
[] = { /* FIXME: add */
558 { WM_NCLBUTTONDOWN
, sent
|wparam
, HTCAPTION
},
559 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_MOVE
+2 },
560 { WM_GETMINMAXINFO
, sent
|defwinproc
},
561 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
562 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
563 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
564 { WM_MOVE
, sent
|defwinproc
},
565 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
568 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
569 static const struct message WmDragThickBordersBarSeq
[] = { /* FIXME: add */
570 { WM_NCLBUTTONDOWN
, sent
|wparam
, 0xd },
571 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, 0xf004 },
572 { WM_GETMINMAXINFO
, sent
|defwinproc
},
573 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
574 { WM_SIZING
, sent
|defwinproc
|wparam
, 4}, /* one for each mouse movement */
575 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, 0 },
576 { WM_GETMINMAXINFO
, sent
|defwinproc
},
577 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
578 { WM_NCPAINT
, sent
|defwinproc
|wparam
, 1 },
579 { WM_GETTEXT
, sent
|defwinproc
},
580 { WM_ERASEBKGND
, sent
|defwinproc
},
581 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, 0 },
582 { WM_MOVE
, sent
|defwinproc
},
583 { WM_SIZE
, sent
|defwinproc
},
584 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
587 /* Resizing child window with MoveWindow (32) */
588 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
589 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
590 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
591 { WM_ERASEBKGND
, sent
|optional
},
592 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
593 { WM_MOVE
, sent
|defwinproc
},
594 { WM_SIZE
, sent
|defwinproc
},
595 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
598 /* Clicking on inactive button */
599 static const struct message WmClickInactiveButtonSeq
[] = { /* FIXME: add */
600 { WM_NCHITTEST
, sent
},
601 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_LBUTTONDOWN
},
602 { WM_MOUSEACTIVATE
, sent
},
603 { WM_MOUSEACTIVATE
, sent
|parent
|defwinproc
},
604 { WM_SETCURSOR
, sent
},
605 { WM_SETCURSOR
, sent
|parent
|defwinproc
},
606 { WM_LBUTTONDOWN
, posted
},
607 { WM_KILLFOCUS
, posted
|parent
},
608 { WM_SETFOCUS
, posted
},
609 { WM_CTLCOLORBTN
, posted
|parent
},
610 { BM_SETSTATE
, posted
},
611 { WM_CTLCOLORBTN
, posted
|parent
},
612 { WM_LBUTTONUP
, posted
},
613 { BM_SETSTATE
, posted
},
614 { WM_CTLCOLORBTN
, posted
|parent
},
615 { WM_COMMAND
, posted
|parent
},
618 /* Reparenting a button (16/32) */
619 /* The last child (button) reparented gets topmost for its new parent. */
620 static const struct message WmReparentButtonSeq
[] = { /* FIXME: add */
621 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
622 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
623 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
624 { WM_ERASEBKGND
, sent
|parent
},
625 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
626 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOZORDER
},
627 { WM_CHILDACTIVATE
, sent
},
628 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOZORDER
},
629 { WM_MOVE
, sent
|defwinproc
},
630 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
633 /* Creation of a custom dialog (32) */
634 static const struct message WmCreateCustomDialogSeq
[] = {
635 { HCBT_CREATEWND
, hook
},
636 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
637 { WM_GETMINMAXINFO
, sent
},
638 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
639 { WM_NCCREATE
, sent
},
640 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
641 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
642 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
643 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
645 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
646 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
647 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
648 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
649 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
650 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
651 { HCBT_ACTIVATE
, hook
},
652 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
654 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
656 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
657 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
659 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
661 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
662 { WM_NCACTIVATE
, sent
|wparam
, 1 },
663 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
664 { WM_GETTEXT
, sent
|optional
|defwinproc
},
665 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
666 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
667 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
668 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
669 { WM_GETTEXT
, sent
|optional
|defwinproc
},
670 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
671 { WM_ACTIVATE
, sent
|wparam
, 1 },
672 { WM_KILLFOCUS
, sent
|parent
},
673 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
674 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
675 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
676 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
677 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
678 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
679 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
680 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
681 { WM_SETFOCUS
, sent
},
682 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
683 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
684 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
685 { WM_NCPAINT
, sent
|wparam
, 1 },
686 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
687 { WM_GETTEXT
, sent
|optional
|defwinproc
},
688 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
689 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
690 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
691 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
692 { WM_GETTEXT
, sent
|optional
|defwinproc
},
693 { WM_ERASEBKGND
, sent
},
694 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
695 { WM_CTLCOLORDLG
, sent
|defwinproc
},
696 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
697 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
698 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
699 { WM_GETTEXT
, sent
|optional
},
700 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
701 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
702 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
703 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
704 { WM_GETTEXT
, sent
|optional
},
705 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
706 { WM_NCCALCSIZE
, sent
|optional
},
707 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
708 { WM_NCPAINT
, sent
|optional
},
709 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
710 { WM_GETTEXT
, sent
|optional
|defwinproc
},
711 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
712 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
713 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
714 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
715 { WM_GETTEXT
, sent
|optional
|defwinproc
},
716 { WM_ERASEBKGND
, sent
|optional
},
717 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
718 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
720 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
724 /* Calling EndDialog for a custom dialog (32) */
725 static const struct message WmEndCustomDialogSeq
[] = {
726 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
727 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
728 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
729 { WM_GETTEXT
, sent
|optional
},
730 { HCBT_ACTIVATE
, hook
},
731 { WM_NCACTIVATE
, sent
|wparam
, 0 },
732 { WM_GETTEXT
, sent
|optional
|defwinproc
},
733 { WM_GETTEXT
, sent
|optional
|defwinproc
},
734 { WM_ACTIVATE
, sent
|wparam
, 0 },
735 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
736 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
737 { HCBT_SETFOCUS
, hook
},
738 { WM_KILLFOCUS
, sent
},
739 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
740 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
741 { WM_IME_NOTIFY
, sent
|optional
},
742 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
743 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
746 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
747 static const struct message WmShowCustomDialogSeq
[] = {
748 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
749 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
750 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
751 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
752 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
753 { HCBT_ACTIVATE
, hook
},
754 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
756 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
757 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
759 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
760 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
761 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
762 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
763 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
764 { WM_NCACTIVATE
, sent
|wparam
, 1 },
765 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
766 { WM_ACTIVATE
, sent
|wparam
, 1 },
768 { WM_KILLFOCUS
, sent
|parent
},
769 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
770 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
771 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
772 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
773 { WM_IME_NOTIFY
, sent
|optional
|defwinproc
},
774 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
775 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
776 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
777 { WM_SETFOCUS
, sent
},
778 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
779 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
780 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
781 { WM_NCPAINT
, sent
|wparam
, 1 },
782 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
783 { WM_ERASEBKGND
, sent
},
784 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
785 { WM_CTLCOLORDLG
, sent
|defwinproc
},
787 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
788 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
791 /* Creation and destruction of a modal dialog (32) */
792 static const struct message WmModalDialogSeq
[] = {
793 { WM_CANCELMODE
, sent
|parent
},
794 { HCBT_SETFOCUS
, hook
},
795 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
796 { WM_KILLFOCUS
, sent
|parent
},
797 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
798 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
799 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
800 { HCBT_CREATEWND
, hook
},
801 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
802 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
803 { WM_SETFONT
, sent
},
804 { WM_INITDIALOG
, sent
},
805 { WM_CHANGEUISTATE
, sent
|optional
},
806 { WM_SHOWWINDOW
, sent
},
807 { HCBT_ACTIVATE
, hook
},
808 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
809 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
810 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
811 { WM_NCACTIVATE
, sent
|wparam
, 1 },
812 { WM_GETTEXT
, sent
|optional
},
813 { WM_ACTIVATE
, sent
|wparam
, 1 },
814 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOACTIVATE
},
815 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
816 { WM_NCPAINT
, sent
},
817 { WM_GETTEXT
, sent
|optional
},
818 { WM_ERASEBKGND
, sent
},
819 { WM_CTLCOLORDLG
, sent
},
820 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
821 { WM_GETTEXT
, sent
|optional
},
822 { WM_NCCALCSIZE
, sent
|optional
},
823 { WM_NCPAINT
, sent
|optional
},
824 { WM_GETTEXT
, sent
|optional
},
825 { WM_ERASEBKGND
, sent
|optional
},
826 { WM_CTLCOLORDLG
, sent
|optional
},
827 { WM_PAINT
, sent
|optional
},
828 { WM_CTLCOLORBTN
, sent
},
829 { WM_ENTERIDLE
, sent
|parent
|optional
},
830 { WM_ENTERIDLE
, sent
|parent
|optional
},
831 { WM_ENTERIDLE
, sent
|parent
|optional
},
832 { WM_ENTERIDLE
, sent
|parent
|optional
},
833 { WM_ENTERIDLE
, sent
|parent
|optional
},
834 { WM_ENTERIDLE
, sent
|parent
|optional
},
835 { WM_ENTERIDLE
, sent
|parent
|optional
},
836 { WM_ENTERIDLE
, sent
|parent
|optional
},
837 { WM_ENTERIDLE
, sent
|parent
|optional
},
838 { WM_ENTERIDLE
, sent
|parent
|optional
},
839 { WM_ENTERIDLE
, sent
|parent
|optional
},
840 { WM_ENTERIDLE
, sent
|parent
|optional
},
841 { WM_ENTERIDLE
, sent
|parent
|optional
},
842 { WM_ENTERIDLE
, sent
|parent
|optional
},
843 { WM_ENTERIDLE
, sent
|parent
|optional
},
844 { WM_ENTERIDLE
, sent
|parent
|optional
},
845 { WM_ENTERIDLE
, sent
|parent
|optional
},
846 { WM_ENTERIDLE
, sent
|parent
|optional
},
847 { WM_ENTERIDLE
, sent
|parent
|optional
},
848 { WM_ENTERIDLE
, sent
|parent
|optional
},
850 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
851 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
852 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOACTIVATE
},
853 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
854 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
855 { WM_GETTEXT
, sent
|optional
},
856 { HCBT_ACTIVATE
, hook
},
857 { WM_NCACTIVATE
, sent
|wparam
, 0 },
858 { WM_GETTEXT
, sent
|optional
},
859 { WM_ACTIVATE
, sent
|wparam
, 0 },
860 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
861 { WM_WINDOWPOSCHANGING
, sent
|optional
},
862 { HCBT_SETFOCUS
, hook
},
863 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
864 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
865 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
866 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
867 { HCBT_DESTROYWND
, hook
},
868 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
869 { WM_DESTROY
, sent
},
870 { WM_NCDESTROY
, sent
},
873 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
874 static const struct message WmCreateModalDialogResizeSeq
[] = { /* FIXME: add */
875 /* (inside dialog proc, handling WM_INITDIALOG) */
876 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
877 { WM_NCCALCSIZE
, sent
},
878 { WM_NCACTIVATE
, sent
|parent
|wparam
, 0 },
879 { WM_GETTEXT
, sent
|defwinproc
},
880 { WM_ACTIVATE
, sent
|parent
|wparam
, 0 },
881 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
882 { WM_WINDOWPOSCHANGING
, sent
|parent
},
883 { WM_NCACTIVATE
, sent
|wparam
, 1 },
884 { WM_ACTIVATE
, sent
|wparam
, 1 },
885 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
886 { WM_SIZE
, sent
|defwinproc
},
887 /* (setting focus) */
888 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
889 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
890 { WM_NCPAINT
, sent
},
891 { WM_GETTEXT
, sent
|defwinproc
},
892 { WM_ERASEBKGND
, sent
},
893 { WM_CTLCOLORDLG
, sent
|defwinproc
},
894 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
896 /* (bunch of WM_CTLCOLOR* for each control) */
897 { WM_PAINT
, sent
|parent
},
898 { WM_ENTERIDLE
, sent
|parent
|wparam
, 0 },
899 { WM_SETCURSOR
, sent
|parent
},
902 /* SetMenu for NonVisible windows with size change*/
903 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
904 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
905 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
906 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
907 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
},
908 { WM_MOVE
, sent
|defwinproc
},
909 { WM_SIZE
, sent
|defwinproc
},
910 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
911 { WM_GETTEXT
, sent
|optional
},
912 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
915 /* SetMenu for NonVisible windows with no size change */
916 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
917 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
918 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
919 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
920 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
923 /* SetMenu for Visible windows with size change */
924 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
925 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
926 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
927 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
928 { WM_NCPAINT
, sent
}, /* wparam != 1 */
929 { WM_GETTEXT
, sent
|defwinproc
|optional
},
930 { WM_ERASEBKGND
, sent
|optional
},
931 { WM_ACTIVATE
, sent
|optional
},
932 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
933 { WM_MOVE
, sent
|defwinproc
},
934 { WM_SIZE
, sent
|defwinproc
},
935 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
936 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
937 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
938 { WM_ERASEBKGND
, sent
|optional
},
941 /* SetMenu for Visible windows with no size change */
942 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
943 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
944 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
945 { WM_NCPAINT
, sent
}, /* wparam != 1 */
946 { WM_GETTEXT
, sent
|defwinproc
|optional
},
947 { WM_ERASEBKGND
, sent
|optional
},
948 { WM_ACTIVATE
, sent
|optional
},
949 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
950 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
953 /* DrawMenuBar for a visible window */
954 static const struct message WmDrawMenuBarSeq
[] =
956 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
957 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
958 { WM_NCPAINT
, sent
}, /* wparam != 1 */
959 { WM_GETTEXT
, sent
|defwinproc
|optional
},
960 { WM_ERASEBKGND
, sent
|optional
},
961 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
962 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
966 static const struct message WmSetRedrawFalseSeq
[] =
968 { WM_SETREDRAW
, sent
|wparam
, 0 },
972 static const struct message WmSetRedrawTrueSeq
[] =
974 { WM_SETREDRAW
, sent
|wparam
, 1 },
978 static const struct message WmEnableWindowSeq_1
[] =
980 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
981 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
982 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
986 static const struct message WmEnableWindowSeq_2
[] =
988 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
989 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
993 static const struct message WmGetScrollRangeSeq
[] =
995 { SBM_GETRANGE
, sent
},
998 static const struct message WmGetScrollInfoSeq
[] =
1000 { SBM_GETSCROLLINFO
, sent
},
1003 static const struct message WmSetScrollRangeSeq
[] =
1005 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1006 sends SBM_SETSCROLLINFO.
1008 { SBM_SETSCROLLINFO
, sent
},
1011 /* SetScrollRange for a window without a non-client area */
1012 static const struct message WmSetScrollRangeHSeq_empty
[] =
1014 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 0 },
1017 static const struct message WmSetScrollRangeVSeq_empty
[] =
1019 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 0 },
1022 static const struct message WmSetScrollRangeHVSeq
[] =
1024 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
1025 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1026 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1027 { WM_ERASEBKGND
, sent
|optional
},
1028 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1029 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1032 /* SetScrollRange for a window with a non-client area */
1033 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
1035 { WM_WINDOWPOSCHANGING
, sent
, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER*/ },
1036 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1037 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1038 { WM_NCPAINT
, sent
|optional
},
1039 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1040 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1041 { WM_ERASEBKGND
, sent
|optional
},
1042 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
1043 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
1044 { WM_SIZE
, sent
|defwinproc
},
1045 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1046 { WM_GETTEXT
, sent
|optional
},
1047 { WM_GETTEXT
, sent
|optional
},
1048 { WM_GETTEXT
, sent
|optional
},
1049 { WM_GETTEXT
, sent
|optional
},
1052 /* test if we receive the right sequence of messages */
1053 /* after calling ShowWindow( SW_SHOWNA) */
1054 static const struct message WmSHOWNAChildInvisParInvis
[] = {
1055 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1058 static const struct message WmSHOWNAChildVisParInvis
[] = {
1059 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1062 static const struct message WmSHOWNAChildVisParVis
[] = {
1063 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1064 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
},
1067 static const struct message WmSHOWNAChildInvisParVis
[] = {
1068 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1069 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1070 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1071 { WM_ERASEBKGND
, sent
|optional
},
1072 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1075 static const struct message WmSHOWNATopVisible
[] = {
1076 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1077 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1080 static const struct message WmSHOWNATopInvisible
[] = {
1081 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1082 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1083 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1084 { WM_NCPAINT
, sent
|wparam
, 1 },
1085 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1086 { WM_ERASEBKGND
, sent
|optional
},
1087 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1088 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1089 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1090 { WM_ERASEBKGND
, sent
|optional
},
1096 static int after_end_dialog
;
1097 static int sequence_cnt
, sequence_size
;
1098 static struct message
* sequence
;
1099 static int log_all_parent_messages
;
1101 static void add_message(const struct message
*msg
)
1106 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof (struct message
) );
1108 if (sequence_cnt
== sequence_size
)
1111 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof (struct message
) );
1115 sequence
[sequence_cnt
].message
= msg
->message
;
1116 sequence
[sequence_cnt
].flags
= msg
->flags
;
1117 sequence
[sequence_cnt
].wParam
= msg
->wParam
;
1118 sequence
[sequence_cnt
].lParam
= msg
->lParam
;
1123 static void flush_sequence(void)
1125 HeapFree(GetProcessHeap(), 0, sequence
);
1127 sequence_cnt
= sequence_size
= 0;
1130 #define ok_sequence( exp, contx, todo) \
1131 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
1134 static void ok_sequence_(const struct message
*expected
, const char *context
, int todo
,
1135 const char *file
, int line
)
1137 static const struct message end_of_sequence
= { 0, 0, 0, 0 };
1138 const struct message
*actual
;
1141 add_message(&end_of_sequence
);
1145 while (expected
->message
&& actual
->message
)
1147 trace_( file
, line
)("expected %04x - actual %04x\n", expected
->message
, actual
->message
);
1149 if (expected
->message
== actual
->message
)
1151 if (expected
->flags
& wparam
)
1153 if (expected
->wParam
!= actual
->wParam
&& todo
)
1157 ok_( file
, line
) (FALSE
,
1158 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1159 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
1163 ok_( file
, line
) (expected
->wParam
== actual
->wParam
,
1164 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
1165 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
1167 if (expected
->flags
& lparam
)
1168 ok_( file
, line
) (expected
->lParam
== actual
->lParam
,
1169 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
1170 context
, expected
->message
, expected
->lParam
, actual
->lParam
);
1171 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
1172 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
1173 context
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
1174 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
1175 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
1176 context
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
1177 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
1178 "%s: the msg 0x%04x should have been %s\n",
1179 context
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
1180 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
1181 "%s: the msg 0x%04x was expected in %s\n",
1182 context
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
1183 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
1184 "%s: the msg 0x%04x should have been sent by a hook\n",
1185 context
, expected
->message
);
1186 ok_( file
, line
) ((expected
->flags
& winevent_hook
) == (actual
->flags
& winevent_hook
),
1187 "%s: the msg 0x%04x should have been sent by a winevent hook\n",
1188 context
, expected
->message
);
1192 /* silently drop winevent messages if there is no support for them */
1193 else if ((expected
->flags
& optional
) || ((expected
->flags
& winevent_hook
) && !hEvent_hook
))
1199 ok_( file
, line
) (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1200 context
, expected
->message
, actual
->message
);
1207 ok_( file
, line
) (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
1208 context
, expected
->message
, actual
->message
);
1214 /* skip all optional trailing messages */
1215 while (expected
->message
&& ((expected
->flags
& optional
) ||
1216 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
1222 if (expected
->message
|| actual
->message
) {
1224 ok_( file
, line
) (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1225 context
, expected
->message
, actual
->message
);
1231 if (expected
->message
|| actual
->message
)
1232 ok_( file
, line
) (FALSE
, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
1233 context
, expected
->message
, actual
->message
);
1235 if( todo
&& !failcount
) /* succeeded yet marked todo */
1237 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
1243 /******************************** MDI test **********************************/
1245 /* CreateWindow for MDI frame window, initially visible */
1246 static const struct message WmCreateMDIframeSeq
[] = {
1247 { HCBT_CREATEWND
, hook
},
1248 { WM_GETMINMAXINFO
, sent
},
1249 { WM_NCCREATE
, sent
},
1250 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1251 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1252 { WM_CREATE
, sent
},
1253 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1254 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1255 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1256 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1257 { HCBT_ACTIVATE
, hook
},
1258 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1259 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1260 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1261 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* Win9x */
1262 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
1263 { WM_NCACTIVATE
, sent
|wparam
, 1 },
1264 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1265 { WM_ACTIVATE
, sent
|wparam
, 1 },
1266 { HCBT_SETFOCUS
, hook
},
1267 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1268 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1269 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
1270 /* Win9x adds SWP_NOZORDER below */
1271 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
1276 /* DestroyWindow for MDI frame window, initially visible */
1277 static const struct message WmDestroyMDIframeSeq
[] = {
1278 { HCBT_DESTROYWND
, hook
},
1279 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1280 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1281 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1282 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1283 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
1284 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
1285 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
1286 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1287 { WM_DESTROY
, sent
},
1288 { WM_NCDESTROY
, sent
},
1291 /* CreateWindow for MDI client window, initially visible */
1292 static const struct message WmCreateMDIclientSeq
[] = {
1293 { HCBT_CREATEWND
, hook
},
1294 { WM_NCCREATE
, sent
},
1295 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1296 { WM_CREATE
, sent
},
1297 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1300 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
1301 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1302 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
},
1303 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1304 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOZORDER
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1307 /* DestroyWindow for MDI client window, initially visible */
1308 static const struct message WmDestroyMDIclientSeq
[] = {
1309 { HCBT_DESTROYWND
, hook
},
1310 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
1311 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1312 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1313 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1314 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1315 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1316 { WM_DESTROY
, sent
},
1317 { WM_NCDESTROY
, sent
},
1320 /* CreateWindow for MDI child window, initially visible */
1321 static const struct message WmCreateMDIchildVisibleSeq
[] = {
1322 { HCBT_CREATEWND
, hook
},
1323 { WM_NCCREATE
, sent
},
1324 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1325 { WM_CREATE
, sent
},
1326 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1329 /* Win2k sends wparam set to
1330 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1331 * while Win9x doesn't bother to set child window id according to
1332 * CLIENTCREATESTRUCT.idFirstChild
1334 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1335 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1336 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1337 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1338 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1339 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1340 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1341 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1342 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1344 /* Win9x: message sequence terminates here. */
1346 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1347 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1348 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1349 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1350 { WM_SETFOCUS
, sent
}, /* in MDI client */
1351 { HCBT_SETFOCUS
, hook
},
1352 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1353 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1354 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1355 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1356 { WM_SETFOCUS
, sent
|defwinproc
},
1357 { WM_MDIACTIVATE
, sent
|defwinproc
},
1360 /* DestroyWindow for MDI child window, initially visible */
1361 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
1362 { HCBT_DESTROYWND
, hook
},
1363 /* Win2k sends wparam set to
1364 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1365 * while Win9x doesn't bother to set child window id according to
1366 * CLIENTCREATESTRUCT.idFirstChild
1368 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1369 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1370 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1371 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1372 { WM_ERASEBKGND
, sent
|parent
|optional
},
1373 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1375 /* { WM_DESTROY, sent }
1376 * Win9x: message sequence terminates here.
1379 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1380 { WM_KILLFOCUS
, sent
},
1381 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1382 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1383 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1384 { WM_SETFOCUS
, sent
}, /* in MDI client */
1386 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1387 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1388 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1389 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1390 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1391 { WM_SETFOCUS
, sent
}, /* in MDI client */
1393 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1395 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1396 { WM_KILLFOCUS
, sent
},
1397 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1398 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1399 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1400 { WM_SETFOCUS
, sent
}, /* in MDI client */
1402 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1403 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1404 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1405 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1406 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1407 { WM_SETFOCUS
, sent
}, /* in MDI client */
1409 { WM_DESTROY
, sent
},
1411 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
1412 { WM_KILLFOCUS
, sent
},
1413 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1414 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1415 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1416 { WM_SETFOCUS
, sent
}, /* in MDI client */
1418 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
1419 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1420 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1421 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1422 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1423 { WM_SETFOCUS
, sent
}, /* in MDI client */
1425 { WM_NCDESTROY
, sent
},
1428 /* CreateWindow for MDI child window, initially invisible */
1429 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
1430 { HCBT_CREATEWND
, hook
},
1431 { WM_NCCREATE
, sent
},
1432 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1433 { WM_CREATE
, sent
},
1434 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1437 /* Win2k sends wparam set to
1438 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1439 * while Win9x doesn't bother to set child window id according to
1440 * CLIENTCREATESTRUCT.idFirstChild
1442 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1445 /* DestroyWindow for MDI child window, initially invisible */
1446 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
1447 { HCBT_DESTROYWND
, hook
},
1448 /* Win2k sends wparam set to
1449 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1450 * while Win9x doesn't bother to set child window id according to
1451 * CLIENTCREATESTRUCT.idFirstChild
1453 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1454 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1455 { WM_DESTROY
, sent
},
1456 { WM_NCDESTROY
, sent
},
1459 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
1460 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
1461 { HCBT_CREATEWND
, hook
},
1462 { WM_NCCREATE
, sent
},
1463 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1464 { WM_CREATE
, sent
},
1465 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1468 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1469 { WM_GETMINMAXINFO
, sent
},
1470 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1471 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1472 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1473 { WM_SIZE
, sent
|defwinproc
},
1475 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1476 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1477 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1478 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1479 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1480 /* Win2k sends wparam set to
1481 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1482 * while Win9x doesn't bother to set child window id according to
1483 * CLIENTCREATESTRUCT.idFirstChild
1485 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1486 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1487 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1488 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1489 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1490 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1491 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1492 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1493 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1495 /* Win9x: message sequence terminates here. */
1497 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1498 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1499 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1500 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1501 { WM_SETFOCUS
, sent
}, /* in MDI client */
1502 { HCBT_SETFOCUS
, hook
},
1503 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1504 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1505 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1506 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1507 { WM_SETFOCUS
, sent
|defwinproc
},
1508 { WM_MDIACTIVATE
, sent
|defwinproc
},
1510 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1511 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1512 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1513 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1516 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
1517 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
1518 /* restore the 1st MDI child */
1519 { WM_SETREDRAW
, sent
|wparam
, 0 },
1520 { HCBT_MINMAX
, hook
},
1521 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1522 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1523 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1524 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1525 { WM_SIZE
, sent
|defwinproc
},
1527 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1528 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1529 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1530 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1531 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1532 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
1533 /* create the 2nd MDI child */
1534 { HCBT_CREATEWND
, hook
},
1535 { WM_NCCREATE
, sent
},
1536 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1537 { WM_CREATE
, sent
},
1538 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1541 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1542 { WM_GETMINMAXINFO
, sent
},
1543 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1544 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1545 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1546 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1547 { WM_SIZE
, sent
|defwinproc
},
1549 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1550 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1551 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1552 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1553 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1554 /* Win2k sends wparam set to
1555 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1556 * while Win9x doesn't bother to set child window id according to
1557 * CLIENTCREATESTRUCT.idFirstChild
1559 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1560 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1561 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1562 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1563 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1564 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1565 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1566 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1568 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1569 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1571 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1573 /* Win9x: message sequence terminates here. */
1575 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1576 { HCBT_SETFOCUS
, hook
},
1577 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
1578 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
1579 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1580 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1581 { WM_SETFOCUS
, sent
}, /* in MDI client */
1582 { HCBT_SETFOCUS
, hook
},
1583 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1584 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1585 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1586 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1587 { WM_SETFOCUS
, sent
|defwinproc
},
1589 { WM_MDIACTIVATE
, sent
|defwinproc
},
1591 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1592 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1593 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1594 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1597 /* WM_MDICREATE MDI child window, initially visible and maximized */
1598 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
1599 { WM_MDICREATE
, sent
},
1600 { HCBT_CREATEWND
, hook
},
1601 { WM_NCCREATE
, sent
},
1602 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1603 { WM_CREATE
, sent
},
1604 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1607 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1608 { WM_GETMINMAXINFO
, sent
},
1609 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|0x8000 },
1610 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1611 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1612 { WM_SIZE
, sent
|defwinproc
},
1615 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1616 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1617 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1618 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1619 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1621 /* Win2k sends wparam set to
1622 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
1623 * while Win9x doesn't bother to set child window id according to
1624 * CLIENTCREATESTRUCT.idFirstChild
1626 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
1627 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1628 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1630 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1632 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1633 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
1634 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1636 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1637 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1639 /* Win9x: message sequence terminates here. */
1641 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1642 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
1643 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1644 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1645 { WM_SETFOCUS
, sent
}, /* in MDI client */
1646 { HCBT_SETFOCUS
, hook
},
1647 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1648 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1649 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1650 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1651 { WM_SETFOCUS
, sent
|defwinproc
},
1653 { WM_MDIACTIVATE
, sent
|defwinproc
},
1656 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1657 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1658 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1659 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1662 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1663 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1664 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1665 { WM_MOVE
, sent
|defwinproc
},
1666 { WM_SIZE
, sent
|defwinproc
},
1669 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1670 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1671 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1675 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1676 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1677 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1678 { WM_SIZE
, sent
|defwinproc
},
1680 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1681 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
1682 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1686 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
1687 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
1688 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
1689 { HCBT_SYSCOMMAND
, hook
},
1690 { WM_CLOSE
, sent
|defwinproc
},
1691 { WM_MDIDESTROY
, sent
}, /* in MDI client */
1693 /* bring the 1st MDI child to top */
1694 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
1695 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
1697 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1699 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
1700 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
1701 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
1703 /* maximize the 1st MDI child */
1704 { HCBT_MINMAX
, hook
},
1705 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1706 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|0x8000 },
1707 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1708 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
1709 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1710 { WM_SIZE
, sent
|defwinproc
},
1712 /* restore the 2nd MDI child */
1713 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
1714 { HCBT_MINMAX
, hook
},
1715 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOZORDER
|0x8000 },
1716 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
1718 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1720 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1721 { WM_SIZE
, sent
|defwinproc
},
1723 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1725 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
1727 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1728 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1729 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1730 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1731 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1733 /* bring the 1st MDI child to top */
1734 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1735 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1736 { HCBT_SETFOCUS
, hook
},
1737 { WM_KILLFOCUS
, sent
|defwinproc
},
1738 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
1739 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1740 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1741 { WM_SETFOCUS
, sent
}, /* in MDI client */
1742 { HCBT_SETFOCUS
, hook
},
1743 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1744 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1745 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1746 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1747 { WM_SETFOCUS
, sent
|defwinproc
},
1748 { WM_MDIACTIVATE
, sent
|defwinproc
},
1749 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1751 /* apparently ShowWindow(SW_SHOW) on an MDI client */
1752 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1753 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1754 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1755 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1756 { WM_MDIREFRESHMENU
, sent
},
1758 { HCBT_DESTROYWND
, hook
},
1759 /* Win2k sends wparam set to
1760 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1761 * while Win9x doesn't bother to set child window id according to
1762 * CLIENTCREATESTRUCT.idFirstChild
1764 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1765 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
1766 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1767 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1768 { WM_ERASEBKGND
, sent
|parent
|optional
},
1769 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1771 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1772 { WM_DESTROY
, sent
|defwinproc
},
1773 { WM_NCDESTROY
, sent
|defwinproc
},
1776 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
1777 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
1778 { WM_MDIDESTROY
, sent
}, /* in MDI client */
1779 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1780 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1781 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1782 { WM_ERASEBKGND
, sent
|parent
|optional
},
1783 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1785 { HCBT_SETFOCUS
, hook
},
1786 { WM_KILLFOCUS
, sent
},
1787 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1788 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1789 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1790 { WM_SETFOCUS
, sent
}, /* in MDI client */
1791 { HCBT_SETFOCUS
, hook
},
1792 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1793 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1794 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1795 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1796 { WM_SETFOCUS
, sent
},
1799 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1800 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1801 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1802 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1805 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1806 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1807 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1808 { WM_MOVE
, sent
|defwinproc
},
1809 { WM_SIZE
, sent
|defwinproc
},
1812 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1813 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1814 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1818 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1819 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1820 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
1821 { WM_SIZE
, sent
|defwinproc
},
1824 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1825 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1826 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1827 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1830 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1831 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1832 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1833 { WM_MOVE
, sent
|defwinproc
},
1834 { WM_SIZE
, sent
|defwinproc
},
1837 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1838 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1839 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1843 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1844 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1845 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
1846 { WM_SIZE
, sent
|defwinproc
},
1847 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1848 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
1849 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1850 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1851 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
1852 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1855 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1856 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1857 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1858 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1860 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1861 { WM_MDIACTIVATE
, sent
},
1863 { HCBT_MINMAX
, hook
},
1864 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|0x8000 },
1865 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1867 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1869 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1870 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
|0x8000 },
1871 { WM_SIZE
, sent
|defwinproc
},
1874 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1875 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
1876 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1877 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1880 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1881 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1882 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1883 { WM_MOVE
, sent
|defwinproc
},
1884 { WM_SIZE
, sent
|defwinproc
},
1887 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOZORDER
},
1888 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1889 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTMOVE
},
1891 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1892 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
1893 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1895 { HCBT_SETFOCUS
, hook
},
1896 { WM_KILLFOCUS
, sent
},
1897 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1898 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1899 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1900 { WM_SETFOCUS
, sent
}, /* in MDI client */
1902 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
1904 { HCBT_DESTROYWND
, hook
},
1905 /* Win2k sends wparam set to
1906 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
1907 * while Win9x doesn't bother to set child window id according to
1908 * CLIENTCREATESTRUCT.idFirstChild
1910 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
1912 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1913 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1914 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1915 { WM_ERASEBKGND
, sent
|parent
|optional
},
1916 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1918 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1919 { WM_DESTROY
, sent
},
1920 { WM_NCDESTROY
, sent
},
1923 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
1924 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
1925 { HCBT_MINMAX
, hook
},
1926 { WM_GETMINMAXINFO
, sent
},
1927 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|0x8000 },
1928 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1929 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1930 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1932 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1933 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
1934 { HCBT_SETFOCUS
, hook
},
1935 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
1936 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1937 { WM_SETFOCUS
, sent
}, /* in MDI client */
1938 { HCBT_SETFOCUS
, hook
},
1939 { WM_KILLFOCUS
, sent
}, /* in MDI client */
1940 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
1941 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1942 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1943 { WM_SETFOCUS
, sent
|defwinproc
},
1944 { WM_MDIACTIVATE
, sent
|defwinproc
},
1945 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1946 { WM_SIZE
, sent
|defwinproc
},
1948 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1949 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1950 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1951 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1952 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1955 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
1956 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
1957 { HCBT_MINMAX
, hook
},
1958 { WM_GETMINMAXINFO
, sent
},
1959 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1960 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1961 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1962 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1963 { WM_SIZE
, sent
|defwinproc
},
1965 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1966 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1967 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1968 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1969 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1972 /* ShowWindow(SW_RESTORE) for a visible MDI child window */
1973 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
1974 { HCBT_MINMAX
, hook
},
1975 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|0x8000 },
1976 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1977 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1978 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1979 { WM_SIZE
, sent
|defwinproc
},
1981 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1982 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1983 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1984 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
1985 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
1988 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
1989 static const struct message WmRestoreMDIchildInisibleSeq
[] = {
1990 { HCBT_MINMAX
, hook
},
1991 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|0x8000 },
1992 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1993 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1994 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
1995 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|0x8000 },
1996 { WM_SIZE
, sent
|defwinproc
},
1998 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
},
1999 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2000 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2001 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2002 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2006 static HWND mdi_client
;
2007 static WNDPROC old_mdi_client_proc
;
2009 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2013 /* do not log painting messages */
2014 if (message
!= WM_PAINT
&&
2015 message
!= WM_ERASEBKGND
&&
2016 message
!= WM_NCPAINT
&&
2017 message
!= WM_NCHITTEST
&&
2018 message
!= WM_GETTEXT
&&
2019 message
!= WM_MDIGETACTIVE
&&
2020 message
!= WM_GETICON
&&
2021 message
!= WM_DEVICECHANGE
)
2023 trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2027 case WM_WINDOWPOSCHANGING
:
2028 case WM_WINDOWPOSCHANGED
:
2030 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
2032 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2033 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2034 winpos
->hwnd
, winpos
->hwndInsertAfter
,
2035 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
2037 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2038 * in the high word for internal purposes
2040 wParam
= winpos
->flags
& 0xffff;
2045 msg
.message
= message
;
2046 msg
.flags
= sent
|wparam
|lparam
;
2047 msg
.wParam
= wParam
;
2048 msg
.lParam
= lParam
;
2052 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
2055 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2057 static long defwndproc_counter
= 0;
2061 /* do not log painting messages */
2062 if (message
!= WM_PAINT
&&
2063 message
!= WM_ERASEBKGND
&&
2064 message
!= WM_NCPAINT
&&
2065 message
!= WM_NCHITTEST
&&
2066 message
!= WM_GETTEXT
&&
2067 message
!= WM_GETICON
&&
2068 message
!= WM_DEVICECHANGE
)
2070 trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2074 case WM_WINDOWPOSCHANGING
:
2075 case WM_WINDOWPOSCHANGED
:
2077 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
2079 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2080 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2081 winpos
->hwnd
, winpos
->hwndInsertAfter
,
2082 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
2084 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2085 * in the high word for internal purposes
2087 wParam
= winpos
->flags
& 0xffff;
2091 case WM_MDIACTIVATE
:
2093 HWND active
, client
= GetParent(hwnd
);
2095 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
2097 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
2098 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
2100 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
2105 msg
.message
= message
;
2106 msg
.flags
= sent
|wparam
|lparam
;
2107 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2108 msg
.wParam
= wParam
;
2109 msg
.lParam
= lParam
;
2113 defwndproc_counter
++;
2114 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
2115 defwndproc_counter
--;
2120 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2122 static long defwndproc_counter
= 0;
2126 /* do not log painting messages */
2127 if (message
!= WM_PAINT
&&
2128 message
!= WM_ERASEBKGND
&&
2129 message
!= WM_NCPAINT
&&
2130 message
!= WM_NCHITTEST
&&
2131 message
!= WM_GETTEXT
&&
2132 message
!= WM_GETICON
&&
2133 message
!= WM_DEVICECHANGE
)
2135 trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2139 case WM_WINDOWPOSCHANGING
:
2140 case WM_WINDOWPOSCHANGED
:
2142 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
2144 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2145 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2146 winpos
->hwnd
, winpos
->hwndInsertAfter
,
2147 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
2149 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2150 * in the high word for internal purposes
2152 wParam
= winpos
->flags
& 0xffff;
2157 msg
.message
= message
;
2158 msg
.flags
= sent
|wparam
|lparam
;
2159 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
2160 msg
.wParam
= wParam
;
2161 msg
.lParam
= lParam
;
2165 defwndproc_counter
++;
2166 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
2167 defwndproc_counter
--;
2172 static BOOL
mdi_RegisterWindowClasses(void)
2177 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
2180 cls
.hInstance
= GetModuleHandleA(0);
2182 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
2183 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
2184 cls
.lpszMenuName
= NULL
;
2185 cls
.lpszClassName
= "MDI_frame_class";
2186 if (!RegisterClassA(&cls
)) return FALSE
;
2188 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
2189 cls
.lpszClassName
= "MDI_child_class";
2190 if (!RegisterClassA(&cls
)) return FALSE
;
2192 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
2193 old_mdi_client_proc
= cls
.lpfnWndProc
;
2194 cls
.hInstance
= GetModuleHandleA(0);
2195 cls
.lpfnWndProc
= mdi_client_hook_proc
;
2196 cls
.lpszClassName
= "MDI_client_class";
2197 if (!RegisterClassA(&cls
)) assert(0);
2202 static void test_mdi_messages(void)
2204 MDICREATESTRUCTA mdi_cs
;
2205 CLIENTCREATESTRUCT client_cs
;
2206 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
2208 HMENU hMenu
= CreateMenu();
2210 assert(mdi_RegisterWindowClasses());
2214 trace("creating MDI frame window\n");
2215 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
2216 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
2217 WS_MAXIMIZEBOX
| WS_VISIBLE
,
2218 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
2219 GetDesktopWindow(), hMenu
,
2220 GetModuleHandleA(0), NULL
);
2222 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", TRUE
);
2224 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2225 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
2227 trace("creating MDI client window\n");
2228 client_cs
.hWindowMenu
= 0;
2229 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
2230 mdi_client
= CreateWindowExA(0, "MDI_client_class",
2232 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
2234 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
2236 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
2238 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2239 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
2241 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2242 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
2243 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
2248 trace("creating invisible MDI child window\n");
2249 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
2251 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
2252 mdi_client
, 0, GetModuleHandleA(0), NULL
);
2256 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
2257 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
2259 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
2260 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
2262 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2263 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2265 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2266 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
2267 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
2269 ShowWindow(mdi_child
, SW_HIDE
);
2270 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
2273 ShowWindow(mdi_child
, SW_SHOW
);
2274 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
2276 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
2277 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
2279 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2280 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2282 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2283 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
2284 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
2286 DestroyWindow(mdi_child
);
2289 trace("creating visible MDI child window\n");
2290 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
2291 WS_CHILD
| WS_VISIBLE
,
2292 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
2293 mdi_client
, 0, GetModuleHandleA(0), NULL
);
2295 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
2297 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
2298 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
2300 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2301 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2303 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2304 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2305 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
2308 DestroyWindow(mdi_child
);
2309 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
2311 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2312 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2314 /* Win2k: MDI client still returns a just destroyed child as active
2315 * Win9x: MDI client returns 0
2317 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2318 ok(active_child
== mdi_child
|| /* win2k */
2319 !active_child
, /* win9x */
2320 "wrong active MDI child %p\n", active_child
);
2321 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
2325 trace("creating invisible MDI child window\n");
2326 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
2328 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
2329 mdi_client
, 0, GetModuleHandleA(0), NULL
);
2331 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
2333 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
2334 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
2336 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2337 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2339 /* Win2k: MDI client still returns a just destroyed child as active
2340 * Win9x: MDI client returns mdi_child2
2342 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2343 ok(active_child
== mdi_child
|| /* win2k */
2344 active_child
== mdi_child2
, /* win9x */
2345 "wrong active MDI child %p\n", active_child
);
2346 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
2349 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
2350 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", TRUE
);
2352 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
2353 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
2355 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2356 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
2357 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2360 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2361 ok(GetFocus() == mdi_child2
|| /* win2k */
2362 GetFocus() == 0, /* win9x */
2363 "wrong focus window %p\n", GetFocus());
2368 ShowWindow(mdi_child2
, SW_HIDE
);
2369 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
2371 ShowWindow(mdi_child2
, SW_RESTORE
);
2372 ok_sequence(WmRestoreMDIchildInisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", TRUE
);
2375 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
2376 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
2378 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2379 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
2380 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
2386 ShowWindow(mdi_child2
, SW_HIDE
);
2387 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
2389 ShowWindow(mdi_child2
, SW_SHOW
);
2390 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
2392 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2393 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2395 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
2396 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", TRUE
);
2398 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2399 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2401 ShowWindow(mdi_child2
, SW_RESTORE
);
2402 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):MDI child", TRUE
);
2404 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2405 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2410 ShowWindow(mdi_child2
, SW_HIDE
);
2411 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
2413 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2414 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2416 DestroyWindow(mdi_child2
);
2417 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
2419 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2420 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2422 /* test for maximized MDI children */
2423 trace("creating maximized visible MDI child window 1\n");
2424 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
2425 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
2426 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
2427 mdi_client
, 0, GetModuleHandleA(0), NULL
);
2429 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
2430 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
2432 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2433 ok(GetFocus() == mdi_child
|| /* win2k */
2434 GetFocus() == 0, /* win9x */
2435 "wrong focus window %p\n", GetFocus());
2437 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2438 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2439 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2442 trace("creating maximized visible MDI child window 2\n");
2443 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
2444 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
2445 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
2446 mdi_client
, 0, GetModuleHandleA(0), NULL
);
2448 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
2449 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
2450 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
2452 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2453 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
2455 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2456 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
2457 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2460 trace("destroying maximized visible MDI child window 2\n");
2461 DestroyWindow(mdi_child2
);
2462 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
2464 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
2466 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2467 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2469 /* Win2k: MDI client still returns a just destroyed child as active
2470 * Win9x: MDI client returns 0
2472 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2473 ok(active_child
== mdi_child2
|| /* win2k */
2474 !active_child
, /* win9x */
2475 "wrong active MDI child %p\n", active_child
);
2478 ShowWindow(mdi_child
, SW_MAXIMIZE
);
2479 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
2482 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2483 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2485 trace("re-creating maximized visible MDI child window 2\n");
2486 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
2487 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
2488 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
2489 mdi_client
, 0, GetModuleHandleA(0), NULL
);
2491 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
2492 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
2493 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
2495 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2496 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
2498 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2499 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
2500 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2503 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
2504 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
2505 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
2507 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
2508 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2509 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2511 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2512 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2513 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2516 DestroyWindow(mdi_child
);
2517 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
2519 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2520 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
2522 /* Win2k: MDI client still returns a just destroyed child as active
2523 * Win9x: MDI client returns 0
2525 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2526 ok(active_child
== mdi_child
|| /* win2k */
2527 !active_child
, /* win9x */
2528 "wrong active MDI child %p\n", active_child
);
2530 /* end of test for maximized MDI children */
2532 mdi_cs
.szClass
= "MDI_child_Class";
2533 mdi_cs
.szTitle
= "MDI child";
2534 mdi_cs
.hOwner
= GetModuleHandleA(0);
2537 mdi_cs
.cx
= CW_USEDEFAULT
;
2538 mdi_cs
.cy
= CW_USEDEFAULT
;
2539 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
2541 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
2542 ok(mdi_child
!= 0, "MDI child creation failed\n");
2543 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
2545 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
2547 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2548 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2550 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
2551 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
2552 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
2554 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2555 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
2556 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
2559 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
2560 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
2562 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
2563 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
2564 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
2569 DestroyWindow(mdi_client
);
2570 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
2572 DestroyWindow(mdi_frame
);
2573 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
2575 /************************* End of MDI test **********************************/
2577 static void test_WM_SETREDRAW(HWND hwnd
)
2579 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2583 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
2584 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
2586 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
2587 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
2590 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
2591 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
2593 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
2594 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
2596 /* restore original WS_VISIBLE state */
2597 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
2602 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2606 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
2608 /* explicitly ignore WM_GETICON message */
2609 if (message
== WM_GETICON
) return 0;
2613 case WM_WINDOWPOSCHANGING
:
2614 case WM_WINDOWPOSCHANGED
:
2616 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
2618 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2619 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2620 winpos
->hwnd
, winpos
->hwndInsertAfter
,
2621 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
2623 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2624 * in the high word for internal purposes
2626 wParam
= winpos
->flags
& 0xffff;
2631 msg
.message
= message
;
2632 msg
.flags
= sent
|wparam
|lparam
;
2633 msg
.wParam
= wParam
;
2634 msg
.lParam
= lParam
;
2637 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
2638 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
2642 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
2644 DWORD style
, exstyle
;
2648 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2649 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2650 /* do not be confused by WS_DLGFRAME set */
2651 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
2653 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
2654 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
2656 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
2657 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2658 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
2659 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
2661 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
2663 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2664 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
2665 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
2667 /* a subsequent call should do nothing */
2668 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
2669 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2670 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2674 trace("Ignore GetScrollRange error below if you are on Win9x\n");
2675 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
2676 ok( ret
, "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
2677 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2678 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
2679 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
2682 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
2684 DWORD style
, exstyle
;
2688 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
2689 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2690 /* do not be confused by WS_DLGFRAME set */
2691 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
2693 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
2694 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
2696 si
.cbSize
= sizeof(si
);
2697 si
.fMask
= SIF_RANGE
;
2700 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
2701 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
2702 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
2704 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
2706 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2707 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
2708 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
2710 /* a subsequent call should do nothing */
2711 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
2712 if (style
& WS_HSCROLL
)
2713 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2714 else if (style
& WS_VSCROLL
)
2715 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2717 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2719 si
.fMask
= SIF_PAGE
;
2721 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
2722 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2726 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
2727 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2729 si
.fMask
= SIF_RANGE
;
2730 si
.nMin
= 0xdeadbeef;
2731 si
.nMax
= 0xdeadbeef;
2732 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
2733 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
2734 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
2735 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
2736 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
2739 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
2740 static void test_scroll_messages(HWND hwnd
)
2748 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
2749 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
2750 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
2751 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2752 /* values of min and max are undefined */
2755 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
2756 ok( ret
, "SetScrollRange error %ld\n", GetLastError());
2757 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2758 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2763 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
2764 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
2765 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
2766 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2767 /* values of min and max are undefined */
2770 si
.cbSize
= sizeof(si
);
2771 si
.fMask
= SIF_RANGE
;
2774 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2775 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2776 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2779 si
.fMask
= SIF_PAGE
;
2781 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2782 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2783 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2788 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
2789 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
2790 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2793 si
.fMask
= SIF_RANGE
;
2794 si
.nMin
= 0xdeadbeef;
2795 si
.nMax
= 0xdeadbeef;
2796 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
2797 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
2798 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
2799 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
2800 /* values of min and max are undefined */
2803 /* set WS_HSCROLL */
2804 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
2805 /* clear WS_HSCROLL */
2806 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
2808 /* set WS_HSCROLL */
2809 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
2810 /* clear WS_HSCROLL */
2811 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
2813 /* set WS_VSCROLL */
2814 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
2815 /* clear WS_VSCROLL */
2816 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
2818 /* set WS_VSCROLL */
2819 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
2820 /* clear WS_VSCROLL */
2821 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
2824 static void test_showwindow(void)
2828 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2829 100, 100, 200, 200, 0, 0, 0, NULL
);
2830 ok (hwnd
!= 0, "Failed to create overlapped window\n");
2831 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
2832 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
2833 ok (hchild
!= 0, "Failed to create child\n");
2836 /* ShowWindow( SW_SHOWNA) for invisible top level window */
2837 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
2838 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
2839 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", TRUE
);
2842 /* ShowWindow( SW_SHOWNA) for now visible top level window */
2843 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
2844 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
2845 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
2847 /* back to invisible */
2848 ShowWindow(hchild
, SW_HIDE
);
2849 ShowWindow(hwnd
, SW_HIDE
);
2851 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
2852 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
2853 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
2854 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", TRUE
);
2856 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
2857 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
2859 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
2860 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
2861 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", TRUE
);
2863 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
2864 ShowWindow( hwnd
, SW_SHOW
);
2866 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
2867 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
2868 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
2871 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
2872 ShowWindow( hchild
, SW_HIDE
);
2874 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
2875 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
2876 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
2880 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
2881 DestroyWindow(hchild
);
2882 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
2884 DestroyWindow(hwnd
);
2888 static void test_sys_menu(HWND hwnd
)
2893 /* test existing window without CS_NOCLOSE style */
2894 hmenu
= GetSystemMenu(hwnd
, FALSE
);
2895 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
2897 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
2898 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
2899 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
2901 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
2902 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
2904 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
2905 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
2906 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
2908 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
2909 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
2911 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
2912 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
2913 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
2915 /* test new window with CS_NOCLOSE style */
2916 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
2917 100, 100, 200, 200, 0, 0, 0, NULL
);
2918 ok (hwnd
!= 0, "Failed to create overlapped window\n");
2920 hmenu
= GetSystemMenu(hwnd
, FALSE
);
2921 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
2923 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
2924 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
2926 DestroyWindow(hwnd
);
2929 /* test if we receive the right sequence of messages */
2930 static void test_messages(void)
2932 HWND hwnd
, hparent
, hchild
;
2933 HWND hchild2
, hbutton
;
2940 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
2941 100, 100, 200, 200, 0, 0, 0, NULL
);
2942 ok (hwnd
!= 0, "Failed to create overlapped window\n");
2943 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
2945 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
2946 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
2947 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
2949 /* test WM_SETREDRAW on a not visible top level window */
2950 test_WM_SETREDRAW(hwnd
);
2952 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2953 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
2954 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
2956 ok(GetActiveWindow() == hwnd
, "window should be active\n");
2957 ok(GetFocus() == hwnd
, "window should have input focus\n");
2958 ShowWindow(hwnd
, SW_HIDE
);
2959 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", TRUE
);
2961 ShowWindow(hwnd
, SW_SHOW
);
2962 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
2964 ShowWindow(hwnd
, SW_HIDE
);
2965 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", TRUE
);
2967 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
2968 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
2970 ShowWindow(hwnd
, SW_RESTORE
);
2971 /* FIXME: add ok_sequence() here */
2974 ShowWindow(hwnd
, SW_SHOW
);
2975 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
2977 ok(GetActiveWindow() == hwnd
, "window should be active\n");
2978 ok(GetFocus() == hwnd
, "window should have input focus\n");
2979 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
2980 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
2981 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
2982 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
2984 /* test WM_SETREDRAW on a visible top level window */
2985 ShowWindow(hwnd
, SW_SHOW
);
2986 test_WM_SETREDRAW(hwnd
);
2988 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
2989 test_scroll_messages(hwnd
);
2991 /* test resizing and moving */
2992 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOACTIVATE
);
2993 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
2994 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOZORDER
|SWP_NOACTIVATE
);
2995 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
2997 /* popups don't get WM_GETMINMAXINFO */
2998 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
2999 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
3001 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOACTIVATE
);
3002 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
3004 test_sys_menu(hwnd
);
3007 DestroyWindow(hwnd
);
3008 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
3010 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
3011 100, 100, 200, 200, 0, 0, 0, NULL
);
3012 ok (hparent
!= 0, "Failed to create parent window\n");
3015 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
3016 0, 0, 10, 10, hparent
, 0, 0, NULL
);
3017 ok (hchild
!= 0, "Failed to create child window\n");
3018 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", TRUE
);
3019 DestroyWindow(hchild
);
3022 /* visible child window with a caption */
3023 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
3024 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
3025 0, 0, 10, 10, hparent
, 0, 0, NULL
);
3026 ok (hchild
!= 0, "Failed to create child window\n");
3027 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
3029 trace("testing scroll APIs on a visible child window %p\n", hchild
);
3030 test_scroll_messages(hchild
);
3032 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
3033 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
3035 DestroyWindow(hchild
);
3038 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
3039 0, 0, 10, 10, hparent
, 0, 0, NULL
);
3040 ok (hchild
!= 0, "Failed to create child window\n");
3041 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
3043 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
3044 100, 100, 50, 50, hparent
, 0, 0, NULL
);
3045 ok (hchild2
!= 0, "Failed to create child2 window\n");
3048 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
3049 0, 100, 50, 50, hchild
, 0, 0, NULL
);
3050 ok (hbutton
!= 0, "Failed to create button window\n");
3052 /* test WM_SETREDRAW on a not visible child window */
3053 test_WM_SETREDRAW(hchild
);
3055 ShowWindow(hchild
, SW_SHOW
);
3056 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
3058 ShowWindow(hchild
, SW_HIDE
);
3059 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
3061 ShowWindow(hchild
, SW_SHOW
);
3062 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
3064 /* test WM_SETREDRAW on a visible child window */
3065 test_WM_SETREDRAW(hchild
);
3067 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
3068 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
3070 ShowWindow(hchild
, SW_HIDE
);
3072 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
3073 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
3075 ShowWindow(hchild
, SW_HIDE
);
3077 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
3078 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
3080 /* DestroyWindow sequence below expects that a child has focus */
3084 DestroyWindow(hchild
);
3085 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
3086 DestroyWindow(hchild2
);
3087 DestroyWindow(hbutton
);
3090 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
3091 0, 0, 100, 100, hparent
, 0, 0, NULL
);
3092 ok (hchild
!= 0, "Failed to create child popup window\n");
3093 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
3094 DestroyWindow(hchild
);
3096 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
3098 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
3099 0, 0, 100, 100, hparent
, 0, 0, NULL
);
3100 ok (hchild
!= 0, "Failed to create popup window\n");
3101 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
3102 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
3103 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
3105 ShowWindow(hchild
, SW_SHOW
);
3106 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
3108 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
3109 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
3111 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
3112 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
3113 DestroyWindow(hchild
);
3115 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
3116 * changes nothing in message sequences.
3119 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
3120 0, 0, 100, 100, hparent
, 0, 0, NULL
);
3121 ok (hchild
!= 0, "Failed to create popup window\n");
3122 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
3123 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
3124 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
3126 ShowWindow(hchild
, SW_SHOW
);
3127 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
3129 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
3130 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
3131 DestroyWindow(hchild
);
3134 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
3135 0, 0, 100, 100, hparent
, 0, 0, NULL
);
3136 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
3137 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
3140 trace("testing scroll APIs on a visible dialog %p\n", hwnd);
3141 test_scroll_messages(hwnd);
3145 after_end_dialog
= 1;
3146 EndDialog( hwnd
, 0 );
3147 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
3149 DestroyWindow(hwnd
);
3150 after_end_dialog
= 0;
3152 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
,
3153 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
3154 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
3156 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
3157 ShowWindow(hwnd
, SW_SHOW
);
3158 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
3159 DestroyWindow(hwnd
);
3162 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
3163 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
3165 /* test showing child with hidden parent */
3166 ShowWindow( hparent
, SW_HIDE
);
3169 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
3170 0, 0, 10, 10, hparent
, 0, 0, NULL
);
3171 ok (hchild
!= 0, "Failed to create child window\n");
3172 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
3174 ShowWindow( hchild
, SW_SHOW
);
3175 ok_sequence(WmShowChildInvisibleParentSeq
, "ShowWindow:show child with invisible parent", TRUE
);
3176 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
3177 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
3179 ShowWindow( hchild
, SW_HIDE
);
3180 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", TRUE
);
3181 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
3182 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
3184 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
3185 ok_sequence(WmShowChildInvisibleParentSeq_2
, "SetWindowPos:show child with invisible parent", FALSE
);
3186 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
3187 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
3189 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
3190 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
3191 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
3192 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
3194 DestroyWindow(hchild
);
3195 DestroyWindow(hparent
);
3198 /* Message sequence for SetMenu */
3199 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a window without a menu\n");
3200 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
3202 hmenu
= CreateMenu();
3203 ok (hmenu
!= 0, "Failed to create menu\n");
3204 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
3205 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
3206 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
3207 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
3208 ok (SetMenu(hwnd
, 0), "SetMenu\n");
3209 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
3210 ok (SetMenu(hwnd
, 0), "SetMenu\n");
3211 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
3212 ShowWindow(hwnd
, SW_SHOW
);
3213 UpdateWindow( hwnd
);
3214 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3216 ok (SetMenu(hwnd
, 0), "SetMenu\n");
3217 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
3218 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
3219 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
3221 UpdateWindow( hwnd
);
3222 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3224 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
3225 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3226 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
3228 DestroyWindow(hwnd
);
3231 /* Message sequence for EnableWindow */
3232 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
3233 100, 100, 200, 200, 0, 0, 0, NULL
);
3234 ok (hparent
!= 0, "Failed to create parent window\n");
3235 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
3236 0, 0, 10, 10, hparent
, 0, 0, NULL
);
3237 ok (hchild
!= 0, "Failed to create child window\n");
3242 EnableWindow(hparent
, FALSE
);
3243 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
3245 EnableWindow(hparent
, TRUE
);
3246 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(TRUE)", FALSE
);
3248 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3251 /* MsgWaitForMultipleObjects test */
3252 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
3253 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
3255 PostMessageA(hparent
, WM_USER
, 0, 0);
3257 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
3258 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
3260 ok(PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
3261 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
3263 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
3264 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
3265 /* end of MsgWaitForMultipleObjects test */
3267 /* the following test causes an exception in user.exe under win9x */
3268 if (!PostMessageW( hparent
, WM_USER
, 0, 0 )) return;
3269 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
3270 /* PeekMessage(NULL) fails, but still removes the message */
3271 SetLastError(0xdeadbeef);
3272 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
3273 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
3274 GetLastError() == 0xdeadbeef, /* NT4 */
3275 "last error is %ld\n", GetLastError() );
3276 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
3277 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
3279 DestroyWindow(hchild
);
3280 DestroyWindow(hparent
);
3286 /****************** button message test *************************/
3287 static const struct message WmSetFocusButtonSeq
[] =
3289 { HCBT_SETFOCUS
, hook
},
3290 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3291 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3292 { WM_SETFOCUS
, sent
|wparam
, 0 },
3293 { WM_CTLCOLORBTN
, sent
|defwinproc
},
3296 static const struct message WmKillFocusButtonSeq
[] =
3298 { HCBT_SETFOCUS
, hook
},
3299 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3300 { WM_KILLFOCUS
, sent
|wparam
, 0 },
3301 { WM_CTLCOLORBTN
, sent
|defwinproc
},
3302 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3305 static const struct message WmSetFocusStaticSeq
[] =
3307 { HCBT_SETFOCUS
, hook
},
3308 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3309 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3310 { WM_SETFOCUS
, sent
|wparam
, 0 },
3311 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
3314 static const struct message WmKillFocusStaticSeq
[] =
3316 { HCBT_SETFOCUS
, hook
},
3317 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3318 { WM_KILLFOCUS
, sent
|wparam
, 0 },
3319 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
3320 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3323 static const struct message WmLButtonDownSeq
[] =
3325 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
3326 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
3327 { HCBT_SETFOCUS
, hook
},
3328 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3329 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3330 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
3331 { WM_CTLCOLORBTN
, sent
|defwinproc
},
3332 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
3333 { WM_CTLCOLORBTN
, sent
|defwinproc
},
3334 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3337 static const struct message WmLButtonUpSeq
[] =
3339 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
3340 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
3341 { WM_CTLCOLORBTN
, sent
|defwinproc
},
3342 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3343 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
3344 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
3348 static WNDPROC old_button_proc
;
3350 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3352 static long defwndproc_counter
= 0;
3356 trace("button: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
3358 /* explicitly ignore WM_GETICON message */
3359 if (message
== WM_GETICON
) return 0;
3361 msg
.message
= message
;
3362 msg
.flags
= sent
|wparam
|lparam
;
3363 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3364 msg
.wParam
= wParam
;
3365 msg
.lParam
= lParam
;
3368 if (message
== BM_SETSTATE
)
3369 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
3371 defwndproc_counter
++;
3372 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
3373 defwndproc_counter
--;
3378 static void subclass_button(void)
3382 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
3384 old_button_proc
= cls
.lpfnWndProc
;
3386 cls
.hInstance
= GetModuleHandle(0);
3387 cls
.lpfnWndProc
= button_hook_proc
;
3388 cls
.lpszClassName
= "my_button_class";
3389 if (!RegisterClassA(&cls
)) assert(0);
3392 static void test_button_messages(void)
3398 const struct message
*setfocus
;
3399 const struct message
*killfocus
;
3401 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
3402 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
3403 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
3404 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
3405 { BS_CHECKBOX
, DLGC_BUTTON
,
3406 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
3407 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
3408 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
3409 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
3410 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
3411 { BS_3STATE
, DLGC_BUTTON
,
3412 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
3413 { BS_AUTO3STATE
, DLGC_BUTTON
,
3414 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
3415 { BS_GROUPBOX
, DLGC_STATIC
,
3416 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
3417 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
3418 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
},
3419 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
3420 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
},
3421 { BS_OWNERDRAW
, DLGC_BUTTON
,
3422 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
}
3430 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
3432 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
,
3433 0, 0, 50, 14, 0, 0, 0, NULL
);
3434 ok(hwnd
!= 0, "Failed to create button window\n");
3436 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
3437 ok(dlg_code
== button
[i
].dlg_code
, "%d: wrong dlg_code %08lx\n", i
, dlg_code
);
3439 ShowWindow(hwnd
, SW_SHOW
);
3444 trace("button style %08lx\n", button
[i
].style
);
3446 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
3449 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
3451 DestroyWindow(hwnd
);
3454 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_PUSHBUTTON
| WS_POPUP
| WS_VISIBLE
,
3455 0, 0, 50, 14, 0, 0, 0, NULL
);
3456 ok(hwnd
!= 0, "Failed to create button window\n");
3461 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
3462 ok_sequence(WmLButtonDownSeq
, "WM_LBUTTONDOWN on a button", FALSE
);
3464 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
3465 ok_sequence(WmLButtonUpSeq
, "WM_LBUTTONUP on a button", FALSE
);
3466 DestroyWindow(hwnd
);
3469 /************* painting message test ********************/
3471 void dump_region(HRGN hrgn
)
3474 RGNDATA
*data
= NULL
;
3479 printf( "null region\n" );
3482 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
3483 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
3484 GetRegionData( hrgn
, size
, data
);
3485 printf("%ld rects:", data
->rdh
.nCount
);
3486 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
3487 printf( " (%ld,%ld)-(%ld,%ld)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
3489 HeapFree( GetProcessHeap(), 0, data
);
3492 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
3496 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
3497 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
3499 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
3500 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
3501 if (ret
== NULLREGION
)
3503 ok( !hrgn
, "Update region shouldn't be empty\n" );
3507 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
3509 ok( 0, "Regions are different\n" );
3510 if (winetest_debug
> 0)
3512 printf( "Update region: " );
3513 dump_region( update
);
3514 printf( "Wanted region: " );
3515 dump_region( hrgn
);
3519 GetRgnBox( update
, &r1
);
3520 GetUpdateRect( hwnd
, &r2
, FALSE
);
3521 ok( r1
.left
== r2
.left
&& r1
.top
== r2
.top
&& r1
.right
== r2
.right
&& r1
.bottom
== r2
.bottom
,
3522 "Rectangles are different: %ld,%ld-%ld,%ld / %ld,%ld-%ld,%ld\n",
3523 r1
.left
, r1
.top
, r1
.right
, r1
.bottom
, r2
.left
, r2
.top
, r2
.right
, r2
.bottom
);
3525 DeleteObject( tmp
);
3526 DeleteObject( update
);
3529 static const struct message WmInvalidateRgn
[] = {
3530 { WM_NCPAINT
, sent
},
3531 { WM_GETTEXT
, sent
|defwinproc
|optional
},
3535 static const struct message WmGetUpdateRect
[] = {
3536 { WM_NCPAINT
, sent
},
3537 { WM_GETTEXT
, sent
|defwinproc
|optional
},
3542 static const struct message WmInvalidateFull
[] = {
3543 { WM_NCPAINT
, sent
|wparam
, 1 },
3544 { WM_GETTEXT
, sent
|defwinproc
|optional
},
3548 static const struct message WmInvalidateErase
[] = {
3549 { WM_NCPAINT
, sent
|wparam
, 1 },
3550 { WM_GETTEXT
, sent
|defwinproc
|optional
},
3551 { WM_ERASEBKGND
, sent
},
3555 static const struct message WmInvalidatePaint
[] = {
3557 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
3558 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
3562 static const struct message WmInvalidateErasePaint
[] = {
3564 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
3565 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
3566 { WM_ERASEBKGND
, sent
|beginpaint
},
3570 static const struct message WmInvalidateErasePaint2
[] = {
3572 { WM_NCPAINT
, sent
|beginpaint
},
3573 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
3574 { WM_ERASEBKGND
, sent
|beginpaint
},
3578 static const struct message WmErase
[] = {
3579 { WM_ERASEBKGND
, sent
},
3583 static const struct message WmPaint
[] = {
3588 static const struct message WmParentOnlyPaint
[] = {
3589 { WM_PAINT
, sent
|parent
},
3593 static const struct message WmInvalidateParent
[] = {
3594 { WM_NCPAINT
, sent
|parent
},
3595 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
3596 { WM_ERASEBKGND
, sent
|parent
},
3600 static const struct message WmInvalidateParentChild
[] = {
3601 { WM_NCPAINT
, sent
|parent
},
3602 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
3603 { WM_ERASEBKGND
, sent
|parent
},
3604 { WM_NCPAINT
, sent
},
3605 { WM_GETTEXT
, sent
|defwinproc
|optional
},
3606 { WM_ERASEBKGND
, sent
},
3610 static const struct message WmInvalidateParentChild2
[] = {
3611 { WM_ERASEBKGND
, sent
|parent
},
3612 { WM_NCPAINT
, sent
},
3613 { WM_GETTEXT
, sent
|defwinproc
|optional
},
3614 { WM_ERASEBKGND
, sent
},
3618 static const struct message WmParentPaint
[] = {
3619 { WM_PAINT
, sent
|parent
},
3624 static const struct message WmParentPaintNc
[] = {
3625 { WM_PAINT
, sent
|parent
},
3627 { WM_NCPAINT
, sent
|beginpaint
},
3628 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
3629 { WM_ERASEBKGND
, sent
|beginpaint
},
3633 static const struct message WmChildPaintNc
[] = {
3635 { WM_NCPAINT
, sent
|beginpaint
},
3636 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
3637 { WM_ERASEBKGND
, sent
|beginpaint
},
3641 static const struct message WmParentErasePaint
[] = {
3642 { WM_PAINT
, sent
|parent
},
3643 { WM_NCPAINT
, sent
|parent
|beginpaint
},
3644 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
3645 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
3647 { WM_NCPAINT
, sent
|beginpaint
},
3648 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
3649 { WM_ERASEBKGND
, sent
|beginpaint
},
3653 static const struct message WmParentOnlyNcPaint
[] = {
3654 { WM_PAINT
, sent
|parent
},
3655 { WM_NCPAINT
, sent
|parent
|beginpaint
},
3656 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
3660 static const struct message WmSetParentStyle
[] = {
3661 { WM_STYLECHANGING
, sent
|parent
},
3662 { WM_STYLECHANGED
, sent
|parent
},
3666 static void test_paint_messages(void)
3671 HWND hparent
, hchild
;
3672 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
3673 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
3674 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
3675 100, 100, 200, 200, 0, 0, 0, NULL
);
3676 ok (hwnd
!= 0, "Failed to create overlapped window\n");
3678 ShowWindow( hwnd
, SW_SHOW
);
3679 UpdateWindow( hwnd
);
3681 /* try to flush pending X expose events */
3682 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
3683 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3685 check_update_rgn( hwnd
, 0 );
3686 SetRectRgn( hrgn
, 10, 10, 20, 20 );
3687 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
3688 check_update_rgn( hwnd
, hrgn
);
3689 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
3690 RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
3691 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
3692 check_update_rgn( hwnd
, hrgn
);
3693 /* validate everything */
3694 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
3695 check_update_rgn( hwnd
, 0 );
3696 /* now with frame */
3697 SetRectRgn( hrgn
, -5, -5, 20, 20 );
3699 /* flush pending messages */
3700 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3703 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3704 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
3706 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
3707 check_update_rgn( hwnd
, hrgn
);
3710 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
3711 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
3714 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
3715 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
3717 GetClientRect( hwnd
, &rect
);
3718 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
3719 check_update_rgn( hwnd
, hrgn
);
3722 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
3723 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
3726 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
3727 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
3728 check_update_rgn( hwnd
, 0 );
3731 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
3732 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
3733 check_update_rgn( hwnd
, 0 );
3736 SetRectRgn( hrgn
, 0, 0, 100, 100 );
3737 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
3738 SetRectRgn( hrgn
, 0, 0, 50, 100 );
3739 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
3740 SetRectRgn( hrgn
, 50, 0, 100, 100 );
3741 check_update_rgn( hwnd
, hrgn
);
3742 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
3743 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
3744 check_update_rgn( hwnd
, 0 );
3747 SetRectRgn( hrgn
, 0, 0, 100, 100 );
3748 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
3749 SetRectRgn( hrgn
, 0, 0, 100, 50 );
3750 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
3751 ok_sequence( WmErase
, "Erase", FALSE
);
3752 SetRectRgn( hrgn
, 0, 50, 100, 100 );
3753 check_update_rgn( hwnd
, hrgn
);
3756 SetRectRgn( hrgn
, 0, 0, 100, 100 );
3757 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
3758 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3759 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
3760 ok_sequence( WmPaint
, "Paint", FALSE
);
3763 SetRectRgn( hrgn
, -4, -4, -2, -2 );
3764 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3765 SetRectRgn( hrgn
, -200, -200, -198, -198 );
3766 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
3767 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
3770 SetRectRgn( hrgn
, -4, -4, -2, -2 );
3771 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3772 SetRectRgn( hrgn
, -4, -4, -3, -3 );
3773 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
3774 SetRectRgn( hrgn
, 0, 0, 1, 1 );
3775 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
3776 ok_sequence( WmPaint
, "Paint", FALSE
);
3779 SetRectRgn( hrgn
, -4, -4, -1, -1 );
3780 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3781 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
3782 /* make sure no WM_PAINT was generated */
3783 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3784 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
3787 SetRectRgn( hrgn
, -4, -4, -1, -1 );
3788 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
3789 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
3791 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
3793 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
3794 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
3795 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
3796 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
3797 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
3798 /* this will send WM_NCPAINT and validate the non client area */
3799 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
3800 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
3802 DispatchMessage( &msg
);
3804 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
3806 DestroyWindow( hwnd
);
3808 /* now test with a child window */
3810 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
3811 100, 100, 200, 200, 0, 0, 0, NULL
);
3812 ok (hparent
!= 0, "Failed to create parent window\n");
3814 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
3815 10, 10, 100, 100, hparent
, 0, 0, NULL
);
3816 ok (hchild
!= 0, "Failed to create child window\n");
3818 ShowWindow( hparent
, SW_SHOW
);
3819 UpdateWindow( hparent
);
3820 UpdateWindow( hchild
);
3821 /* try to flush pending X expose events */
3822 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
3823 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3826 log_all_parent_messages
++;
3828 SetRect( &rect
, 0, 0, 50, 50 );
3829 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3830 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
3831 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
3833 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3835 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
3836 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
3837 check_update_rgn( hchild
, hrgn
);
3838 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3839 check_update_rgn( hparent
, hrgn
);
3840 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3841 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
3842 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
3843 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
3845 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3846 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
3848 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
3849 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3850 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
3851 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
3852 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
3854 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
3855 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
3856 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
3858 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
3860 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
3861 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3862 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
3864 /* flush all paint messages */
3865 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3868 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
3869 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
3870 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3871 check_update_rgn( hparent
, hrgn
);
3872 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
3873 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3874 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3875 check_update_rgn( hparent
, hrgn
);
3877 /* flush all paint messages */
3878 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3879 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
3882 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
3883 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3884 SetRectRgn( hrgn
, 0, 0, 50, 50 );
3885 check_update_rgn( hparent
, hrgn
);
3886 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
3887 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3888 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
3889 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
3890 check_update_rgn( hparent
, hrgn
);
3891 /* flush all paint messages */
3892 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3895 /* same as above but parent gets completely validated */
3896 SetRect( &rect
, 20, 20, 30, 30 );
3897 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3898 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3899 check_update_rgn( hparent
, hrgn
);
3900 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
3901 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3902 check_update_rgn( hparent
, 0 ); /* no update region */
3903 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3904 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
3906 /* make sure RDW_VALIDATE on child doesn't have the same effect */
3908 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3909 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3910 check_update_rgn( hparent
, hrgn
);
3911 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
3912 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3913 check_update_rgn( hparent
, hrgn
);
3915 /* same as above but normal WM_PAINT doesn't validate parent */
3917 SetRect( &rect
, 20, 20, 30, 30 );
3918 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3919 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3920 check_update_rgn( hparent
, hrgn
);
3921 /* no WM_PAINT in child while parent still pending */
3922 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3923 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
3924 while (PeekMessage( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3925 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
3928 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
3929 /* no WM_PAINT in child while parent still pending */
3930 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3931 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
3932 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
3933 /* now that parent is valid child should get WM_PAINT */
3934 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3935 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
3936 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3937 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
3939 /* same thing with WS_CLIPCHILDREN in parent */
3941 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
3942 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
3943 /* changing style invalidates non client area, but we need to invalidate something else to see it */
3944 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
3945 ok_sequence( WmEmptySeq
, "No message", FALSE
);
3946 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
3947 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
3950 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
3951 SetRectRgn( hrgn
, 20, 20, 30, 30 );
3952 check_update_rgn( hparent
, hrgn
);
3953 /* no WM_PAINT in child while parent still pending */
3954 while (PeekMessage( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3955 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
3956 /* WM_PAINT in parent first */
3957 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3958 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
3960 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
3962 SetRect( &rect
, 0, 0, 30, 30 );
3963 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
3964 SetRectRgn( hrgn
, 0, 0, 30, 30 );
3965 check_update_rgn( hparent
, hrgn
);
3966 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3967 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
3969 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3971 SetRect( &rect
, -10, 0, 30, 30 );
3972 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
3973 SetRect( &rect
, 0, 0, 20, 20 );
3974 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
3975 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
3976 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
3978 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
3980 SetRect( &rect
, -10, 0, 30, 30 );
3981 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
3982 SetRect( &rect
, 0, 0, 100, 100 );
3983 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
3984 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
3985 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
3986 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
3987 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
3989 /* test RDW_INTERNALPAINT behavior */
3992 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
3993 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3994 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
3996 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
3997 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
3998 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
4000 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
4001 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4002 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
4004 assert( GetWindowLong(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
);
4005 UpdateWindow( hparent
);
4006 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4008 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
4009 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
4010 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
4011 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4012 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4013 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
4015 UpdateWindow( hparent
);
4016 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4018 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
4019 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
4020 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
4021 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4022 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4023 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
4025 SetWindowLong( hparent
, GWL_STYLE
, GetWindowLong(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
4026 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
4027 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
4028 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4029 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
4031 assert( !(GetWindowLong(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
) );
4032 UpdateWindow( hparent
);
4033 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4035 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
4036 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
4037 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
4038 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4039 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4040 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
4042 UpdateWindow( hparent
);
4043 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4045 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
4046 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
4047 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
4048 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
4049 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
4050 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
4052 log_all_parent_messages
--;
4053 DestroyWindow( hparent
);
4054 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
4056 DeleteObject( hrgn
);
4057 DeleteObject( hrgn2
);
4066 static DWORD WINAPI
thread_proc(void *param
)
4069 struct wnd_event
*wnd_event
= (struct wnd_event
*)param
;
4071 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
4072 100, 100, 200, 200, 0, 0, 0, NULL
);
4073 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
4075 SetEvent(wnd_event
->event
);
4077 while (GetMessage(&msg
, 0, 0, 0))
4079 TranslateMessage(&msg
);
4080 DispatchMessage(&msg
);
4083 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
4088 static void test_interthread_messages(void)
4095 int len
, expected_len
;
4096 struct wnd_event wnd_event
;
4099 wnd_event
.event
= CreateEventW(NULL
, 0, 0, NULL
);
4100 if (!wnd_event
.event
)
4102 trace("skipping interthread message test under win9x\n");
4106 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
4107 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
4109 ok(WaitForSingleObject(wnd_event
.event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
4111 CloseHandle(wnd_event
.event
);
4113 SetLastError(0xdeadbeef);
4114 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeded\n");
4115 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error code %ld\n", GetLastError());
4117 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
4118 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
4120 expected_len
= lstrlenA("window caption text");
4121 memset(buf
, 0, sizeof(buf
));
4122 SetLastError(0xdeadbeef);
4123 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
4124 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
4125 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
4127 msg
.hwnd
= wnd_event
.hwnd
;
4128 msg
.message
= WM_GETTEXT
;
4129 msg
.wParam
= sizeof(buf
);
4130 msg
.lParam
= (LPARAM
)buf
;
4131 memset(buf
, 0, sizeof(buf
));
4132 SetLastError(0xdeadbeef);
4133 len
= DispatchMessageA(&msg
);
4134 ok(!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
,
4135 "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %ld\n", len
, GetLastError());
4137 /* the following test causes an exception in user.exe under win9x */
4138 msg
.hwnd
= wnd_event
.hwnd
;
4139 msg
.message
= WM_TIMER
;
4141 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
4142 SetLastError(0xdeadbeef);
4143 len
= DispatchMessageA(&msg
);
4144 ok(!len
&& GetLastError() == 0xdeadbeef,
4145 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len
, GetLastError());
4147 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
4148 ok( ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
4150 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
4151 CloseHandle(hThread
);
4153 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
4157 static const struct message WmVkN
[] = {
4158 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
4159 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
4160 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
4161 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
4162 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
4163 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
4166 static const struct message WmShiftVkN
[] = {
4167 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
4168 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
4169 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
4170 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
4171 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
4172 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
4173 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
4174 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
4175 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
4176 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
4179 static const struct message WmCtrlVkN
[] = {
4180 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
4181 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
4182 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
4183 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
4184 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
4185 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
4186 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
4187 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
4188 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4189 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4192 static const struct message WmCtrlVkN_2
[] = {
4193 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
4194 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
4195 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
4196 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
4197 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
4198 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
4199 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4200 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4203 static const struct message WmAltVkN
[] = {
4204 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
4205 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
4206 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
4207 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
4208 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
4209 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
4210 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
4211 { HCBT_SYSCOMMAND
, hook
},
4212 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4213 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
4214 { WM_INITMENU
, sent
|defwinproc
},
4215 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
4216 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
4217 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
4218 { WM_CAPTURECHANGED
, sent
|defwinproc
},
4219 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
4220 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
4221 { WM_EXITMENULOOP
, sent
|defwinproc
},
4222 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
4223 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
4224 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
4225 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
4226 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
4227 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
4230 static const struct message WmAltVkN_2
[] = {
4231 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
4232 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
4233 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
4234 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
4235 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
4236 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
4237 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
4238 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
4241 static const struct message WmCtrlAltVkN
[] = {
4242 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
4243 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
4244 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
4245 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
4246 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
4247 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
4248 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
4249 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
4250 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
4251 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
4252 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4253 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4256 static const struct message WmCtrlShiftVkN
[] = {
4257 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
4258 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
4259 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
4260 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
4261 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
4262 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
4263 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
4264 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
4265 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
4266 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
4267 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4268 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4271 static const struct message WmCtrlAltShiftVkN
[] = {
4272 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
4273 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
4274 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
4275 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
4276 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
4277 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
4278 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
4279 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
4280 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
4281 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
4282 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
4283 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
4284 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
4285 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
4286 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4287 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
4290 static const struct message WmAltPressRelease
[] = {
4291 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
4292 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
4293 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
4294 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
4295 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
4296 { HCBT_SYSCOMMAND
, hook
},
4297 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4298 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
4299 { WM_INITMENU
, sent
|defwinproc
},
4300 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
4301 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
) },
4302 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
4304 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
4305 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
4306 { WM_CAPTURECHANGED
, sent
|defwinproc
},
4307 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
4308 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
4309 { WM_EXITMENULOOP
, sent
|defwinproc
},
4310 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
4311 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
4314 static const struct message WmAltMouseButton
[] = {
4315 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
4316 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
4317 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
4318 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
4319 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
, 0 },
4320 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
, 0 },
4321 { WM_LBUTTONUP
, wparam
, 0, 0 },
4322 { WM_LBUTTONUP
, sent
|wparam
, 0, 0 },
4323 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
4324 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
4328 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
4332 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
4334 struct message log_msg
;
4336 trace("accel: %p, %04x, %08x, %08lx\n", msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
4338 /* ignore some unwanted messages */
4339 if (msg
.message
== WM_MOUSEMOVE
||
4340 msg
.message
== WM_GETICON
||
4341 msg
.message
== WM_DEVICECHANGE
)
4344 log_msg
.message
= msg
.message
;
4345 log_msg
.flags
= wparam
|lparam
;
4346 log_msg
.wParam
= msg
.wParam
;
4347 log_msg
.lParam
= msg
.lParam
;
4348 add_message(&log_msg
);
4350 if (!hAccel
|| !TranslateAccelerator(hwnd
, hAccel
, &msg
))
4352 TranslateMessage(&msg
);
4353 DispatchMessage(&msg
);
4358 static void test_accelerators(void)
4363 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
4364 100, 100, 200, 200, 0, 0, 0, NULL
);
4370 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
4372 state
= GetKeyState(VK_SHIFT
);
4373 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
4374 state
= GetKeyState(VK_CAPITAL
);
4375 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
4377 hAccel
= LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1));
4378 assert(hAccel
!= 0);
4380 pump_msg_loop(hwnd
, 0);
4383 trace("testing VK_N press/release\n");
4385 keybd_event('N', 0, 0, 0);
4386 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4387 pump_msg_loop(hwnd
, hAccel
);
4388 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
4390 trace("testing Shift+VK_N press/release\n");
4392 keybd_event(VK_SHIFT
, 0, 0, 0);
4393 keybd_event('N', 0, 0, 0);
4394 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4395 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
4396 pump_msg_loop(hwnd
, hAccel
);
4397 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
4399 trace("testing Ctrl+VK_N press/release\n");
4401 keybd_event(VK_CONTROL
, 0, 0, 0);
4402 keybd_event('N', 0, 0, 0);
4403 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4404 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
4405 pump_msg_loop(hwnd
, hAccel
);
4406 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
4408 trace("testing Alt+VK_N press/release\n");
4410 keybd_event(VK_MENU
, 0, 0, 0);
4411 keybd_event('N', 0, 0, 0);
4412 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4413 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4414 pump_msg_loop(hwnd
, hAccel
);
4415 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
4417 trace("testing Ctrl+Alt+VK_N press/release 1\n");
4419 keybd_event(VK_CONTROL
, 0, 0, 0);
4420 keybd_event(VK_MENU
, 0, 0, 0);
4421 keybd_event('N', 0, 0, 0);
4422 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4423 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4424 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
4425 pump_msg_loop(hwnd
, hAccel
);
4426 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
4428 ret
= DestroyAcceleratorTable(hAccel
);
4429 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
4431 hAccel
= LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(2));
4432 assert(hAccel
!= 0);
4434 trace("testing VK_N press/release\n");
4436 keybd_event('N', 0, 0, 0);
4437 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4438 pump_msg_loop(hwnd
, hAccel
);
4439 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
4441 trace("testing Shift+VK_N press/release\n");
4443 keybd_event(VK_SHIFT
, 0, 0, 0);
4444 keybd_event('N', 0, 0, 0);
4445 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4446 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
4447 pump_msg_loop(hwnd
, hAccel
);
4448 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
4450 trace("testing Ctrl+VK_N press/release 2\n");
4452 keybd_event(VK_CONTROL
, 0, 0, 0);
4453 keybd_event('N', 0, 0, 0);
4454 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4455 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
4456 pump_msg_loop(hwnd
, hAccel
);
4457 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
4459 trace("testing Alt+VK_N press/release 2\n");
4461 keybd_event(VK_MENU
, 0, 0, 0);
4462 keybd_event('N', 0, 0, 0);
4463 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4464 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4465 pump_msg_loop(hwnd
, hAccel
);
4466 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
4468 trace("testing Ctrl+Alt+VK_N press/release 2\n");
4470 keybd_event(VK_CONTROL
, 0, 0, 0);
4471 keybd_event(VK_MENU
, 0, 0, 0);
4472 keybd_event('N', 0, 0, 0);
4473 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4474 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4475 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
4476 pump_msg_loop(hwnd
, hAccel
);
4477 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
4479 trace("testing Ctrl+Shift+VK_N press/release\n");
4481 keybd_event(VK_CONTROL
, 0, 0, 0);
4482 keybd_event(VK_SHIFT
, 0, 0, 0);
4483 keybd_event('N', 0, 0, 0);
4484 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4485 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
4486 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
4487 pump_msg_loop(hwnd
, hAccel
);
4488 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
4490 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
4492 keybd_event(VK_CONTROL
, 0, 0, 0);
4493 keybd_event(VK_MENU
, 0, 0, 0);
4494 keybd_event(VK_SHIFT
, 0, 0, 0);
4495 keybd_event('N', 0, 0, 0);
4496 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
4497 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
4498 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4499 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
4500 pump_msg_loop(hwnd
, hAccel
);
4501 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
4503 ret
= DestroyAcceleratorTable(hAccel
);
4504 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
4506 trace("testing Alt press/release\n");
4508 keybd_event(VK_MENU
, 0, 0, 0);
4509 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4510 keybd_event(VK_MENU
, 0, 0, 0);
4511 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4512 pump_msg_loop(hwnd
, 0);
4513 /* this test doesn't pass in Wine for managed windows */
4514 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
4516 trace("testing Alt+MouseButton press/release\n");
4517 /* first, move mouse pointer inside of the window client area */
4518 GetClientRect(hwnd
, &rc
);
4519 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
4520 rc
.left
+= (rc
.right
- rc
.left
)/2;
4521 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
4522 SetCursorPos(rc
.left
, rc
.top
);
4524 pump_msg_loop(hwnd
, 0);
4526 keybd_event(VK_MENU
, 0, 0, 0);
4527 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
4528 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
4529 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
4530 pump_msg_loop(hwnd
, 0);
4531 ok_sequence(WmAltMouseButton
, "Alt+MouseButton press/release", FALSE
);
4533 DestroyWindow(hwnd
);
4536 /************* window procedures ********************/
4538 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4540 static long defwndproc_counter
= 0;
4541 static long beginpaint_counter
= 0;
4545 trace("%p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
4547 /* explicitly ignore WM_GETICON message */
4548 if (message
== WM_GETICON
) return 0;
4554 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4555 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
4556 "wrong WS_DISABLED state: %d != %d\n", wParam
, !(style
& WS_DISABLED
));
4560 case WM_CAPTURECHANGED
:
4561 if (test_DestroyWindow_flag
)
4563 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4564 if (style
& WS_CHILD
)
4565 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
4566 else if (style
& WS_POPUP
)
4567 lParam
= WND_POPUP_ID
;
4569 lParam
= WND_PARENT_ID
;
4577 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
4578 capture
= GetCapture();
4581 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
4582 trace("current capture %p, releasing...\n", capture
);
4589 ok(pGetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
4590 if (test_DestroyWindow_flag
)
4592 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4593 if (style
& WS_CHILD
)
4594 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
4595 else if (style
& WS_POPUP
)
4596 lParam
= WND_POPUP_ID
;
4598 lParam
= WND_PARENT_ID
;
4602 /* test_accelerators() depends on this */
4609 case WM_DEVICECHANGE
:
4612 case WM_WINDOWPOSCHANGING
:
4613 case WM_WINDOWPOSCHANGED
:
4615 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
4617 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4618 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4619 winpos
->hwnd
, winpos
->hwndInsertAfter
,
4620 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
4622 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4623 * in the high word for internal purposes
4625 wParam
= winpos
->flags
& 0xffff;
4630 msg
.message
= message
;
4631 msg
.flags
= sent
|wparam
|lparam
;
4632 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4633 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
4634 msg
.wParam
= wParam
;
4635 msg
.lParam
= lParam
;
4638 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
4640 HWND parent
= GetParent(hwnd
);
4642 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
4644 GetClientRect(parent
, &rc
);
4645 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
4647 trace("ptReserved = (%ld,%ld)\n"
4648 "ptMaxSize = (%ld,%ld)\n"
4649 "ptMaxPosition = (%ld,%ld)\n"
4650 "ptMinTrackSize = (%ld,%ld)\n"
4651 "ptMaxTrackSize = (%ld,%ld)\n",
4652 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
4653 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
4654 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
4655 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
4656 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
4658 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
4659 minmax
->ptMaxSize
.x
, rc
.right
);
4660 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
4661 minmax
->ptMaxSize
.y
, rc
.bottom
);
4664 if (message
== WM_PAINT
)
4667 beginpaint_counter
++;
4668 BeginPaint( hwnd
, &ps
);
4669 beginpaint_counter
--;
4670 EndPaint( hwnd
, &ps
);
4674 defwndproc_counter
++;
4675 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
4676 defwndproc_counter
--;
4681 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4683 static long defwndproc_counter
= 0;
4687 trace("popup: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
4689 /* explicitly ignore WM_GETICON message */
4690 if (message
== WM_GETICON
) return 0;
4692 msg
.message
= message
;
4693 msg
.flags
= sent
|wparam
|lparam
;
4694 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4695 msg
.wParam
= wParam
;
4696 msg
.lParam
= lParam
;
4699 if (message
== WM_CREATE
)
4701 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
4702 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4705 defwndproc_counter
++;
4706 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
4707 defwndproc_counter
--;
4712 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4714 static long defwndproc_counter
= 0;
4715 static long beginpaint_counter
= 0;
4719 trace("parent: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
4721 /* explicitly ignore WM_GETICON message */
4722 if (message
== WM_GETICON
) return 0;
4724 if (log_all_parent_messages
||
4725 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
4726 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
4727 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
4728 message
== WM_IME_SETCONTEXT
)
4735 INT ret
= GetClipBox((HDC
)wParam
, &rc
);
4737 trace("WM_ERASEBKGND: GetClipBox()=%d, (%ld,%ld-%ld,%ld)\n",
4738 ret
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
4742 case WM_WINDOWPOSCHANGING
:
4743 case WM_WINDOWPOSCHANGED
:
4745 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
4747 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4748 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4749 winpos
->hwnd
, winpos
->hwndInsertAfter
,
4750 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
4752 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4753 * in the high word for internal purposes
4755 wParam
= winpos
->flags
& 0xffff;
4760 msg
.message
= message
;
4761 msg
.flags
= sent
|parent
|wparam
|lparam
;
4762 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4763 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
4764 msg
.wParam
= wParam
;
4765 msg
.lParam
= lParam
;
4769 if (message
== WM_PAINT
)
4772 beginpaint_counter
++;
4773 BeginPaint( hwnd
, &ps
);
4774 beginpaint_counter
--;
4775 EndPaint( hwnd
, &ps
);
4779 defwndproc_counter
++;
4780 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
4781 defwndproc_counter
--;
4786 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4788 static long defwndproc_counter
= 0;
4792 trace("dialog: %p, %04x, %08x, %08lx\n", hwnd
, message
, wParam
, lParam
);
4794 /* explicitly ignore WM_GETICON message */
4795 if (message
== WM_GETICON
) return 0;
4797 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
4798 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
4799 if (after_end_dialog
)
4800 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
4802 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
4806 case WM_WINDOWPOSCHANGING
:
4807 case WM_WINDOWPOSCHANGED
:
4809 WINDOWPOS
*winpos
= (WINDOWPOS
*)lParam
;
4811 trace("%s\n", (message
== WM_WINDOWPOSCHANGING
) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
4812 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
4813 winpos
->hwnd
, winpos
->hwndInsertAfter
,
4814 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
, winpos
->flags
);
4816 /* Log only documented flags, win2k uses 0x1000 and 0x2000
4817 * in the high word for internal purposes
4819 wParam
= winpos
->flags
& 0xffff;
4824 msg
.message
= message
;
4825 msg
.flags
= sent
|wparam
|lparam
;
4826 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4827 msg
.wParam
= wParam
;
4828 msg
.lParam
= lParam
;
4831 defwndproc_counter
++;
4832 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
4833 defwndproc_counter
--;
4838 static BOOL
RegisterWindowClasses(void)
4843 cls
.lpfnWndProc
= MsgCheckProcA
;
4846 cls
.hInstance
= GetModuleHandleA(0);
4848 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
4849 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
4850 cls
.lpszMenuName
= NULL
;
4851 cls
.lpszClassName
= "TestWindowClass";
4852 if(!RegisterClassA(&cls
)) return FALSE
;
4854 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
4855 cls
.lpszClassName
= "TestPopupClass";
4856 if(!RegisterClassA(&cls
)) return FALSE
;
4858 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
4859 cls
.lpszClassName
= "TestParentClass";
4860 if(!RegisterClassA(&cls
)) return FALSE
;
4862 cls
.lpfnWndProc
= DefWindowProcA
;
4863 cls
.lpszClassName
= "SimpleWindowClass";
4864 if(!RegisterClassA(&cls
)) return FALSE
;
4866 cls
.style
= CS_NOCLOSE
;
4867 cls
.lpszClassName
= "NoCloseWindowClass";
4868 if(!RegisterClassA(&cls
)) return FALSE
;
4870 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
4872 cls
.hInstance
= GetModuleHandleA(0);
4873 cls
.hbrBackground
= 0;
4874 cls
.lpfnWndProc
= TestDlgProcA
;
4875 cls
.lpszClassName
= "TestDialogClass";
4876 if(!RegisterClassA(&cls
)) return FALSE
;
4881 static HHOOK hCBT_hook
;
4882 static DWORD cbt_hook_thread_id
;
4884 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
4886 static const char *CBT_code_name
[10] = {
4893 "HCBT_CLICKSKIPPED",
4897 const char *code_name
= (nCode
>= 0 && nCode
<= HCBT_SETFOCUS
) ? CBT_code_name
[nCode
] : "Unknown";
4901 trace("CBT: %d (%s), %08x, %08lx\n", nCode
, code_name
, wParam
, lParam
);
4903 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
4905 if (nCode
== HCBT_SYSCOMMAND
)
4909 msg
.message
= nCode
;
4910 msg
.flags
= hook
|wparam
|lparam
;
4911 msg
.wParam
= wParam
;
4912 msg
.lParam
= lParam
;
4915 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
4918 if (nCode
== HCBT_DESTROYWND
)
4920 if (test_DestroyWindow_flag
)
4922 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
4923 if (style
& WS_CHILD
)
4924 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
4925 else if (style
& WS_POPUP
)
4926 lParam
= WND_POPUP_ID
;
4928 lParam
= WND_PARENT_ID
;
4932 /* Log also SetFocus(0) calls */
4933 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
4935 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
4937 if (!lstrcmpiA(buf
, "TestWindowClass") ||
4938 !lstrcmpiA(buf
, "TestParentClass") ||
4939 !lstrcmpiA(buf
, "TestPopupClass") ||
4940 !lstrcmpiA(buf
, "SimpleWindowClass") ||
4941 !lstrcmpiA(buf
, "TestDialogClass") ||
4942 !lstrcmpiA(buf
, "MDI_frame_class") ||
4943 !lstrcmpiA(buf
, "MDI_client_class") ||
4944 !lstrcmpiA(buf
, "MDI_child_class") ||
4945 !lstrcmpiA(buf
, "my_button_class") ||
4946 !lstrcmpiA(buf
, "static") ||
4947 !lstrcmpiA(buf
, "#32770"))
4951 msg
.message
= nCode
;
4952 msg
.flags
= hook
|wparam
|lparam
;
4953 msg
.wParam
= wParam
;
4954 msg
.lParam
= lParam
;
4958 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
4961 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
4971 trace("WEH:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
4972 hevent
, event
, hwnd
, object_id
, child_id
, thread_id
, event_time
);
4974 ok(thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
4976 /* ignore mouse cursor events */
4977 if (object_id
== OBJID_CURSOR
) return;
4979 if (!hwnd
|| GetClassNameA(hwnd
, buf
, sizeof(buf
)))
4982 !lstrcmpiA(buf
, "TestWindowClass") ||
4983 !lstrcmpiA(buf
, "TestParentClass") ||
4984 !lstrcmpiA(buf
, "TestPopupClass") ||
4985 !lstrcmpiA(buf
, "SimpleWindowClass") ||
4986 !lstrcmpiA(buf
, "TestDialogClass") ||
4987 !lstrcmpiA(buf
, "MDI_frame_class") ||
4988 !lstrcmpiA(buf
, "MDI_client_class") ||
4989 !lstrcmpiA(buf
, "MDI_child_class") ||
4990 !lstrcmpiA(buf
, "my_button_class") ||
4991 !lstrcmpiA(buf
, "static") ||
4992 !lstrcmpiA(buf
, "#32770"))
4996 msg
.message
= event
;
4997 msg
.flags
= winevent_hook
|wparam
|lparam
;
4998 msg
.wParam
= object_id
;
4999 msg
.lParam
= child_id
;
5005 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
5006 static const WCHAR wszAnsi
[] = {'U',0};
5008 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
5012 case CB_FINDSTRINGEXACT
:
5013 trace("String: %p\n", (LPCWSTR
)lParam
);
5014 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
5016 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
5020 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
5023 static void test_message_conversion(void)
5025 static const WCHAR wszMsgConversionClass
[] =
5026 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
5033 cls
.lpfnWndProc
= MsgConversionProcW
;
5036 cls
.hInstance
= GetModuleHandleW(NULL
);
5038 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
5039 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
5040 cls
.lpszMenuName
= NULL
;
5041 cls
.lpszClassName
= wszMsgConversionClass
;
5042 /* this call will fail on Win9x, but that doesn't matter as this test is
5043 * meaningless on those platforms */
5044 if(!RegisterClassW(&cls
)) return;
5046 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
5047 100, 100, 200, 200, 0, 0, 0, NULL
);
5048 ok(hwnd
!= NULL
, "Window creation failed\n");
5052 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
5053 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5054 ok(lRes
== 0, "String should have been converted\n");
5055 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5056 ok(lRes
== 1, "String shouldn't have been converted\n");
5060 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
5061 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5062 ok(lRes
== 1, "String shouldn't have been converted\n");
5063 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5064 ok(lRes
== 1, "String shouldn't have been converted\n");
5066 /* Synchronous messages */
5068 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5069 ok(lRes
== 0, "String should have been converted\n");
5070 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5071 ok(lRes
== 1, "String shouldn't have been converted\n");
5073 /* Asynchronous messages */
5076 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5077 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5078 "PostMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5080 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5081 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5082 "PostMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5084 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5085 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5086 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5088 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5089 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5090 "PosThreadtMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5092 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5093 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5094 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5096 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
5097 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5098 "SendNotifyMessage on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5100 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
5101 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5102 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5104 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
5105 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
5106 "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes
, GetLastError());
5109 typedef struct _thread_info
5116 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT id
, DWORD dwTime
)
5120 #define TIMER_ID 0x19
5122 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
5124 thread_info
*info
= x
;
5127 r
= KillTimer(info
->hWnd
, 0x19);
5128 ok(r
,"KillTimer failed in thread\n");
5129 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
5130 ok(r
,"SetTimer failed in thread\n");
5131 ok(r
==TIMER_ID
,"SetTimer id different\n");
5132 r
= SetEvent(info
->handles
[0]);
5133 ok(r
,"SetEvent failed in thread\n");
5137 static void test_timers(void)
5142 info
.hWnd
= CreateWindow ("TestWindowClass", NULL
,
5143 WS_OVERLAPPEDWINDOW
,
5144 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5147 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
5148 ok(info
.id
, "SetTimer failed\n");
5149 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
5150 info
.handles
[0] = CreateEvent(NULL
,0,0,NULL
);
5151 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
5153 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
5155 WaitForSingleObject(info
.handles
[1], INFINITE
);
5157 CloseHandle(info
.handles
[0]);
5158 CloseHandle(info
.handles
[1]);
5160 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
5162 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
5165 /* Various win events with arbitrary parameters */
5166 static const struct message WmWinEventsSeq
[] = {
5167 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
5168 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
5169 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
5170 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
5171 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
5172 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
5173 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
5174 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
5175 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
5176 /* our win event hook ignores OBJID_CURSOR events */
5177 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
5178 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
5179 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
5180 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
5181 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
5182 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
5183 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
5184 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
5185 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
5186 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
5187 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
5188 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
5189 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
5190 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
5193 static const struct message WmWinEventCaretSeq
[] = {
5194 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
5195 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
5196 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
5197 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
5200 static const struct message WmWinEventCaretSeq_2
[] = {
5201 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
5202 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
5203 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
5206 static const struct message WmWinEventAlertSeq
[] = {
5207 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
5210 static const struct message WmWinEventAlertSeq_2
[] = {
5211 /* create window in the thread proc */
5212 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
5213 /* our test event */
5214 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
5217 static const struct message WmGlobalHookSeq_1
[] = {
5218 /* create window in the thread proc */
5219 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
5220 /* our test events */
5221 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
5222 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
5225 static const struct message WmGlobalHookSeq_2
[] = {
5226 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
5227 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
5228 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
5229 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
5233 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
5243 trace("WEH_2:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
5244 hevent
, event
, hwnd
, object_id
, child_id
, thread_id
, event_time
);
5246 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
5248 if (!lstrcmpiA(buf
, "TestWindowClass") ||
5249 !lstrcmpiA(buf
, "static"))
5253 msg
.message
= event
;
5254 msg
.flags
= winevent_hook
|wparam
|lparam
;
5255 msg
.wParam
= object_id
;
5256 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
5262 static HHOOK hCBT_global_hook
;
5263 static DWORD cbt_global_hook_thread_id
;
5265 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
5270 trace("CBT_2: %d, %08x, %08lx\n", nCode
, wParam
, lParam
);
5272 if (nCode
== HCBT_SYSCOMMAND
)
5276 msg
.message
= nCode
;
5277 msg
.flags
= hook
|wparam
|lparam
;
5278 msg
.wParam
= wParam
;
5279 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
5282 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
5285 /* Log also SetFocus(0) calls */
5286 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
5288 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
5290 if (!lstrcmpiA(buf
, "TestWindowClass") ||
5291 !lstrcmpiA(buf
, "static"))
5295 msg
.message
= nCode
;
5296 msg
.flags
= hook
|wparam
|lparam
;
5297 msg
.wParam
= wParam
;
5298 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
5302 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
5305 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
5309 HANDLE hevent
= *(HANDLE
*)param
;
5310 HMODULE user32
= GetModuleHandleA("user32.dll");
5311 FARPROC pNotifyWinEvent
= GetProcAddress(user32
, "NotifyWinEvent");
5313 assert(pNotifyWinEvent
);
5315 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
5317 trace("created thread window %p\n", hwnd
);
5319 *(HWND
*)param
= hwnd
;
5322 /* this event should be received only by our new hook proc,
5323 * an old one does not expect an event from another thread.
5325 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
5328 while (GetMessage(&msg
, 0, 0, 0))
5330 TranslateMessage(&msg
);
5331 DispatchMessage(&msg
);
5336 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
5340 HANDLE hevent
= *(HANDLE
*)param
;
5343 /* these events should be received only by our new hook proc,
5344 * an old one does not expect an event from another thread.
5347 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
5349 trace("created thread window %p\n", hwnd
);
5351 *(HWND
*)param
= hwnd
;
5353 /* Windows doesn't like when a thread plays games with the focus,
5354 that leads to all kinds of misbehaviours and failures to activate
5355 a window. So, better keep next lines commented out.
5359 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
5360 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
5364 while (GetMessage(&msg
, 0, 0, 0))
5366 TranslateMessage(&msg
);
5367 DispatchMessage(&msg
);
5372 static void test_winevents(void)
5378 HANDLE hthread
, hevent
;
5380 HWINEVENTHOOK hhook
;
5381 const struct message
*events
= WmWinEventsSeq
;
5382 HMODULE user32
= GetModuleHandleA("user32.dll");
5383 FARPROC pSetWinEventHook
= GetProcAddress(user32
, "SetWinEventHook");
5384 FARPROC pUnhookWinEvent
= GetProcAddress(user32
, "UnhookWinEvent");
5385 FARPROC pNotifyWinEvent
= GetProcAddress(user32
, "NotifyWinEvent");
5387 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
5388 WS_OVERLAPPEDWINDOW
,
5389 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5393 /****** start of global hook test *************/
5394 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
5395 assert(hCBT_global_hook
);
5397 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
5399 hwnd2
= (HWND
)hevent
;
5401 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
5402 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
5404 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5406 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
5409 /* this one should be received only by old hook proc */
5410 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
5411 /* this one should be received only by old hook proc */
5412 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
5414 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
5416 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
5417 ok( ret
, "UnhookWindowsHookEx error %ld\n", GetLastError());
5419 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
5420 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5421 CloseHandle(hthread
);
5422 CloseHandle(hevent
);
5423 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
5424 /****** end of global hook test *************/
5426 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
5428 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
5434 #if 0 /* this test doesn't pass under Win9x */
5435 /* win2k ignores events with hwnd == 0 */
5436 SetLastError(0xdeadbeef);
5437 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
5438 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
5439 GetLastError() == 0xdeadbeef, /* Win9x */
5440 "unexpected error %ld\n", GetLastError());
5441 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
5444 for (i
= 0; i
< sizeof(WmWinEventsSeq
)/sizeof(WmWinEventsSeq
[0]); i
++)
5445 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
5447 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
5449 /****** start of event filtering test *************/
5450 hhook
= (HWINEVENTHOOK
)pSetWinEventHook(
5451 EVENT_OBJECT_SHOW
, /* 0x8002 */
5452 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
5453 GetModuleHandleA(0), win_event_global_hook_proc
,
5454 GetCurrentProcessId(), 0,
5455 WINEVENT_INCONTEXT
);
5456 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
5458 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
5460 hwnd2
= (HWND
)hevent
;
5462 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
5463 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
5465 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5467 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
5470 /* this one should be received only by old hook proc */
5471 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
5472 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
5473 /* this one should be received only by old hook proc */
5474 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
5476 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
5478 ret
= pUnhookWinEvent(hhook
);
5479 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
5481 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
5482 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5483 CloseHandle(hthread
);
5484 CloseHandle(hevent
);
5485 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
5486 /****** end of event filtering test *************/
5488 /****** start of out of context event test *************/
5489 hhook
= (HWINEVENTHOOK
)pSetWinEventHook(
5490 EVENT_MIN
, EVENT_MAX
,
5491 0, win_event_global_hook_proc
,
5492 GetCurrentProcessId(), 0,
5493 WINEVENT_OUTOFCONTEXT
);
5494 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
5496 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
5498 hwnd2
= (HWND
)hevent
;
5502 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
5503 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
5505 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5507 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
5508 /* process pending winevent messages */
5509 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
5510 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
5513 /* this one should be received only by old hook proc */
5514 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
5515 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
5516 /* this one should be received only by old hook proc */
5517 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
5519 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
5520 /* process pending winevent messages */
5521 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
5522 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
5524 ret
= pUnhookWinEvent(hhook
);
5525 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
5527 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
5528 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5529 CloseHandle(hthread
);
5530 CloseHandle(hevent
);
5531 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
5532 /****** end of out of context event test *************/
5534 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
5537 static void test_set_hook(void)
5541 HWINEVENTHOOK hwinevent_hook
;
5542 HMODULE user32
= GetModuleHandleA("user32.dll");
5543 FARPROC pSetWinEventHook
= GetProcAddress(user32
, "SetWinEventHook");
5544 FARPROC pUnhookWinEvent
= GetProcAddress(user32
, "UnhookWinEvent");
5546 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
5547 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
5548 UnhookWindowsHookEx(hhook
);
5550 #if 0 /* this test doesn't pass under Win9x: BUG! */
5551 SetLastError(0xdeadbeef);
5552 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
5553 ok(!hhook
, "global hook requires hModule != 0\n");
5554 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
5557 SetLastError(0xdeadbeef);
5558 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
5559 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
5560 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
|| /* Win2k */
5561 GetLastError() == 0xdeadbeef, /* Win9x */
5562 "unexpected error %ld\n", GetLastError());
5564 SetLastError(0xdeadbeef);
5565 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
5566 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
|| /* Win2k */
5567 GetLastError() == 0xdeadbeef, /* Win9x */
5568 "unexpected error %ld\n", GetLastError());
5570 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
5572 /* even process local incontext hooks require hmodule */
5573 SetLastError(0xdeadbeef);
5574 hwinevent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
5575 0, win_event_proc
, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
5576 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
5577 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
5578 GetLastError() == 0xdeadbeef, /* Win9x */
5579 "unexpected error %ld\n", GetLastError());
5581 /* even thread local incontext hooks require hmodule */
5582 SetLastError(0xdeadbeef);
5583 hwinevent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
5584 0, win_event_proc
, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
5585 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
5586 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
5587 GetLastError() == 0xdeadbeef, /* Win9x */
5588 "unexpected error %ld\n", GetLastError());
5590 #if 0 /* these 3 tests don't pass under Win9x */
5591 SetLastError(0xdeadbeef);
5592 hwinevent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(1, 0,
5593 0, win_event_proc
, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
5594 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
5595 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
5597 SetLastError(0xdeadbeef);
5598 hwinevent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(-1, 1,
5599 0, win_event_proc
, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
5600 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
5601 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
5603 SetLastError(0xdeadbeef);
5604 hwinevent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
5605 0, win_event_proc
, 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
5606 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
5607 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %ld\n", GetLastError());
5610 SetLastError(0xdeadbeef);
5611 hwinevent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(0, 0,
5612 0, win_event_proc
, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
5613 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
5614 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
5615 ret
= pUnhookWinEvent(hwinevent_hook
);
5616 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
5619 /* This call succeeds under win2k SP4, but fails under Wine.
5620 Does win2k test/use passed process id? */
5621 SetLastError(0xdeadbeef);
5622 hwinevent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
5623 0, win_event_proc
, 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
5624 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
5625 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
5626 ret
= pUnhookWinEvent(hwinevent_hook
);
5627 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
5630 SetLastError(0xdeadbeef);
5631 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
5632 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
5633 GetLastError() == 0xdeadbeef, /* Win9x */
5634 "unexpected error %ld\n", GetLastError());
5637 static const struct message ScrollWindowPaint1
[] = {
5639 { WM_ERASEBKGND
, sent
|beginpaint
},
5643 static const struct message ScrollWindowPaint2
[] = {
5648 static void test_scrollwindowex(void)
5651 RECT rect
={0,0,130,130};
5654 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
5655 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
5656 100, 100, 200, 200, 0, 0, 0, NULL
);
5657 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5658 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
5659 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
5660 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
5661 ok (hchild
!= 0, "Failed to create child\n");
5663 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
5666 /* scroll without the child window */
5667 trace("start scroll\n");
5668 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
5669 SW_ERASE
|SW_INVALIDATE
);
5670 ok_sequence(WmEmptySeq
, "ScrollWindowEx", 0);
5671 trace("end scroll\n");
5673 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
5674 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", 0);
5676 /* Now without the SW_ERASE flag */
5677 trace("start scroll\n");
5678 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
5679 ok_sequence(WmEmptySeq
, "ScrollWindowEx", 0);
5680 trace("end scroll\n");
5682 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
5683 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", 0);
5685 /* now scroll the child window as well */
5686 trace("start scroll\n");
5687 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
5688 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
5689 todo_wine
{ /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
5690 /* windows sometimes a WM_MOVE */
5691 ok_sequence(WmEmptySeq
, "ScrollWindowEx", 0);
5693 trace("end scroll\n");
5695 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
5696 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", 0);
5698 /* now scroll with ScrollWindow() */
5699 trace("start scroll with ScrollWindow\n");
5700 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
5701 trace("end scroll\n");
5703 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
5704 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", 0);
5706 ok(DestroyWindow(hchild
), "failed to destroy window\n");
5707 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
5711 static const struct message destroy_window_with_children
[] = {
5712 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
5713 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
5714 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
5715 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
5716 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
5717 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
5718 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
5719 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* parent */
5720 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
5721 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
5722 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
5723 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
5724 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
5725 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
5726 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
5727 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
5731 static void test_DestroyWindow(void)
5734 HWND parent
, child1
, child2
, child3
, child4
, test
;
5735 UINT child_id
= WND_CHILD_ID
+ 1;
5737 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5738 100, 100, 200, 200, 0, 0, 0, NULL
);
5739 assert(parent
!= 0);
5740 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
5741 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
5742 assert(child1
!= 0);
5743 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
5744 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
5745 assert(child2
!= 0);
5746 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
5747 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
5748 assert(child3
!= 0);
5749 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
5750 0, 0, 50, 50, parent
, 0, 0, NULL
);
5751 assert(child4
!= 0);
5753 /* test owner/parent of child2 */
5754 test
= GetParent(child2
);
5755 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
5756 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
5758 test
= pGetAncestor(child2
, GA_PARENT
);
5759 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
5761 test
= GetWindow(child2
, GW_OWNER
);
5762 ok(!test
, "wrong owner %p\n", test
);
5764 test
= SetParent(child2
, parent
);
5765 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
5767 /* test owner/parent of the parent */
5768 test
= GetParent(parent
);
5769 ok(!test
, "wrong parent %p\n", test
);
5771 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
5774 test
= pGetAncestor(parent
, GA_PARENT
);
5775 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
5777 test
= GetWindow(parent
, GW_OWNER
);
5778 ok(!test
, "wrong owner %p\n", test
);
5780 /* test owner/parent of child1 */
5781 test
= GetParent(child1
);
5782 ok(test
== parent
, "wrong parent %p\n", test
);
5783 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
5785 test
= pGetAncestor(child1
, GA_PARENT
);
5786 ok(test
== parent
, "wrong parent %p\n", test
);
5788 test
= GetWindow(child1
, GW_OWNER
);
5789 ok(!test
, "wrong owner %p\n", test
);
5791 /* test owner/parent of child2 */
5792 test
= GetParent(child2
);
5793 ok(test
== parent
, "wrong parent %p\n", test
);
5794 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
5796 test
= pGetAncestor(child2
, GA_PARENT
);
5797 ok(test
== parent
, "wrong parent %p\n", test
);
5799 test
= GetWindow(child2
, GW_OWNER
);
5800 ok(!test
, "wrong owner %p\n", test
);
5802 /* test owner/parent of child3 */
5803 test
= GetParent(child3
);
5804 ok(test
== child1
, "wrong parent %p\n", test
);
5805 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
5807 test
= pGetAncestor(child3
, GA_PARENT
);
5808 ok(test
== child1
, "wrong parent %p\n", test
);
5810 test
= GetWindow(child3
, GW_OWNER
);
5811 ok(!test
, "wrong owner %p\n", test
);
5813 /* test owner/parent of child4 */
5814 test
= GetParent(child4
);
5815 ok(test
== parent
, "wrong parent %p\n", test
);
5816 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
5818 test
= pGetAncestor(child4
, GA_PARENT
);
5819 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
5821 test
= GetWindow(child4
, GW_OWNER
);
5822 ok(test
== parent
, "wrong owner %p\n", test
);
5826 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
5827 parent
, child1
, child2
, child3
, child4
);
5830 test
= GetCapture();
5831 ok(test
== child4
, "wrong capture window %p\n", test
);
5833 test_DestroyWindow_flag
= TRUE
;
5834 ret
= DestroyWindow(parent
);
5835 ok( ret
, "DestroyWindow() error %ld\n", GetLastError());
5836 test_DestroyWindow_flag
= FALSE
;
5837 ok_sequence(destroy_window_with_children
, "destroy window with children", 0);
5839 ok(!IsWindow(parent
), "parent still exists\n");
5840 ok(!IsWindow(child1
), "child1 still exists\n");
5841 ok(!IsWindow(child2
), "child2 still exists\n");
5842 ok(!IsWindow(child3
), "child3 still exists\n");
5843 ok(!IsWindow(child4
), "child4 still exists\n");
5845 test
= GetCapture();
5846 ok(!test
, "wrong capture window %p\n", test
);
5850 static const struct message WmDispatchPaint
[] = {
5851 { WM_NCPAINT
, sent
},
5852 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5853 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5854 { WM_ERASEBKGND
, sent
},
5858 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5860 if (message
== WM_PAINT
)
5862 trace( "Got WM_PAINT, ignoring\n" );
5865 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
5868 static void test_DispatchMessage(void)
5873 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5874 100, 100, 200, 200, 0, 0, 0, NULL
);
5875 ShowWindow( hwnd
, SW_SHOW
);
5876 UpdateWindow( hwnd
);
5877 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
5879 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
5881 SetRect( &rect
, -5, -5, 5, 5 );
5882 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
5884 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
5886 if (msg
.message
!= WM_PAINT
) DispatchMessage( &msg
);
5890 DispatchMessage( &msg
);
5891 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
5892 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
5893 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
5894 if (++count
> 10) break;
5897 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
5899 trace("now without DispatchMessage\n");
5901 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
5903 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
5905 if (msg
.message
!= WM_PAINT
) DispatchMessage( &msg
);
5908 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
5910 /* this will send WM_NCCPAINT just like DispatchMessage does */
5911 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
5912 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
5913 DeleteObject( hrgn
);
5914 GetClientRect( hwnd
, &rect
);
5915 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
5916 ok( !count
, "Got multiple WM_PAINTs\n" );
5917 if (++count
> 10) break;
5923 static const struct message WmUser
[] = {
5935 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
5937 struct thread_info
*info
= arg
;
5938 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
5939 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
, "unexpected error %ld\n", GetLastError());
5943 static void wait_for_thread( HANDLE thread
)
5945 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
5948 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage(&msg
);
5952 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
5954 if (message
== WM_USER
) Sleep(200);
5955 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
5958 static void test_SendMessageTimeout(void)
5962 struct thread_info info
;
5964 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5965 100, 100, 200, 200, 0, 0, 0, NULL
);
5966 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessage( &msg
);
5969 info
.timeout
= 1000;
5970 info
.ret
= 0xdeadbeef;
5971 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, NULL
);
5972 wait_for_thread( thread
);
5973 CloseHandle( thread
);
5974 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
5975 ok_sequence( WmUser
, "WmUser", FALSE
);
5978 info
.ret
= 0xdeadbeef;
5979 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, NULL
);
5980 Sleep(100); /* SendMessageTimeout should timeout here */
5981 wait_for_thread( thread
);
5982 CloseHandle( thread
);
5983 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
5984 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
5986 /* 0 means infinite timeout */
5988 info
.ret
= 0xdeadbeef;
5989 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, NULL
);
5991 wait_for_thread( thread
);
5992 CloseHandle( thread
);
5993 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
5994 ok_sequence( WmUser
, "WmUser", FALSE
);
5996 /* timeout is treated as signed despite the prototype */
5997 info
.timeout
= 0x7fffffff;
5998 info
.ret
= 0xdeadbeef;
5999 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, NULL
);
6001 wait_for_thread( thread
);
6002 CloseHandle( thread
);
6003 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
6004 ok_sequence( WmUser
, "WmUser", FALSE
);
6006 info
.timeout
= 0x80000000;
6007 info
.ret
= 0xdeadbeef;
6008 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, NULL
);
6010 wait_for_thread( thread
);
6011 CloseHandle( thread
);
6012 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
6013 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
6015 /* now check for timeout during message processing */
6016 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
6018 info
.ret
= 0xdeadbeef;
6019 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, NULL
);
6020 wait_for_thread( thread
);
6021 CloseHandle( thread
);
6022 /* we should timeout but still get the message */
6023 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
6024 ok_sequence( WmUser
, "WmUser", FALSE
);
6026 DestroyWindow( info
.hwnd
);
6033 HMODULE user32
= GetModuleHandleA("user32.dll");
6034 FARPROC pSetWinEventHook
= GetProcAddress(user32
, "SetWinEventHook");
6035 FARPROC pUnhookWinEvent
= GetProcAddress(user32
, "UnhookWinEvent");
6036 FARPROC pIsWinEventHookInstalled
= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
6037 pGetAncestor
= (void*) GetProcAddress(user32
, "GetAncestor");
6039 if (!RegisterWindowClasses()) assert(0);
6041 if (pSetWinEventHook
)
6043 hEvent_hook
= (HWINEVENTHOOK
)pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
6044 GetModuleHandleA(0),
6047 GetCurrentThreadId(),
6048 WINEVENT_INCONTEXT
);
6049 assert(hEvent_hook
);
6051 if (pIsWinEventHookInstalled
)
6054 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
6055 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
6059 cbt_hook_thread_id
= GetCurrentThreadId();
6060 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
6065 /* Fix message sequences before removing 3 lines below */
6066 ret
= pUnhookWinEvent(hEvent_hook
);
6067 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
6068 pUnhookWinEvent
= 0;
6071 test_scrollwindowex();
6073 test_mdi_messages();
6074 test_button_messages();
6075 test_paint_messages();
6076 test_interthread_messages();
6077 test_message_conversion();
6078 test_accelerators();
6081 test_DestroyWindow();
6082 test_DispatchMessage();
6083 test_SendMessageTimeout();
6085 UnhookWindowsHookEx(hCBT_hook
);
6086 if (pUnhookWinEvent
)
6088 ret
= pUnhookWinEvent(hEvent_hook
);
6089 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
6090 SetLastError(0xdeadbeef);
6091 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
6092 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
6093 GetLastError() == 0xdeadbeef, /* Win9x */
6094 "unexpected error %ld\n", GetLastError());