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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */
24 #define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */
38 #include "wine/test.h"
40 #define MDI_FIRST_CHILD_ID 2004
42 /* undocumented SWP flags - from SDK 3.1 */
43 #define SWP_NOCLIENTSIZE 0x0800
44 #define SWP_NOCLIENTMOVE 0x1000
45 #define SWP_STATECHANGED 0x8000
47 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
50 #define WM_KEYF1 0x004d
54 #define WM_SYSTIMER 0x0118
57 #define WND_PARENT_ID 1
58 #define WND_POPUP_ID 2
59 #define WND_CHILD_ID 3
61 #ifndef WM_LBTRACKPOINT
62 #define WM_LBTRACKPOINT 0x0131
67 #elif defined __x86_64__
71 #elif defined __aarch64__
77 static BOOL (WINAPI
*pActivateActCtx
)(HANDLE
,ULONG_PTR
*);
78 static HANDLE (WINAPI
*pCreateActCtxW
)(PCACTCTXW
);
79 static BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
,ULONG_PTR
);
80 static BOOL (WINAPI
*pGetCurrentActCtx
)(HANDLE
*);
81 static BOOL (WINAPI
*pQueryActCtxW
)(DWORD
,HANDLE
,void*,ULONG
,void*,SIZE_T
,SIZE_T
*);
82 static void (WINAPI
*pReleaseActCtx
)(HANDLE
);
84 /* encoded DRAWITEMSTRUCT into an LPARAM */
91 UINT type
: 4; /* ODT_* flags */
92 UINT ctl_id
: 4; /* Control ID */
93 UINT item_id
: 4; /* Menu item ID */
94 UINT action
: 4; /* ODA_* flags */
95 UINT state
: 16; /* ODS_* flags */
101 static BOOL test_DestroyWindow_flag
;
102 static HWINEVENTHOOK hEvent_hook
;
103 static HHOOK hKBD_hook
;
104 static HHOOK hCBT_hook
;
105 static DWORD cbt_hook_thread_id
;
107 static const WCHAR testWindowClassW
[] =
108 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
111 FIXME: add tests for these
112 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
113 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
114 WS_THICKFRAME: thick border
115 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
116 WS_BORDER (default for overlapped windows): single black border
117 none (default for child (and popup?) windows): no border
135 UINT message
; /* the WM_* code */
136 msg_flags_t flags
; /* message props */
137 WPARAM wParam
; /* expected value of wParam */
138 LPARAM lParam
; /* expected value of lParam */
139 WPARAM wp_mask
; /* mask for wParam checks */
140 LPARAM lp_mask
; /* mask for lParam checks */
143 struct recvd_message
{
144 UINT message
; /* the WM_* code */
145 msg_flags_t flags
; /* message props */
146 HWND hwnd
; /* window that received the message */
147 WPARAM wParam
; /* expected value of wParam */
148 LPARAM lParam
; /* expected value of lParam */
149 int line
; /* source line where logged */
150 const char *descr
; /* description for trace output */
151 char output
[512]; /* trace output */
154 /* Empty message sequence */
155 static const struct message WmEmptySeq
[] =
159 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
160 static const struct message WmCreateOverlappedSeq
[] = {
161 { HCBT_CREATEWND
, hook
},
162 { WM_GETMINMAXINFO
, sent
},
163 { WM_NCCREATE
, sent
},
164 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
165 { 0x0093, sent
|defwinproc
|optional
},
166 { 0x0094, sent
|defwinproc
|optional
},
167 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
169 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
172 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
173 * for a not visible overlapped window.
175 static const struct message WmSWP_ShowOverlappedSeq
[] = {
176 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
177 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
178 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
179 { WM_GETTEXT
, sent
|defwinproc
|optional
},
180 { WM_ERASEBKGND
, sent
|optional
},
181 { HCBT_ACTIVATE
, hook
},
182 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
183 { WM_NOTIFYFORMAT
, sent
|optional
},
184 { WM_QUERYUISTATE
, sent
|optional
},
185 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
186 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
187 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
188 { WM_NCACTIVATE
, sent
},
189 { WM_GETTEXT
, sent
|defwinproc
|optional
},
190 { WM_ACTIVATE
, sent
|wparam
, 1 },
191 { HCBT_SETFOCUS
, hook
},
192 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
193 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
194 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
195 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
196 { WM_GETTEXT
, sent
|optional
},
197 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
198 { WM_GETTEXT
, sent
|defwinproc
|optional
},
199 { WM_ERASEBKGND
, sent
|optional
},
200 /* Win9x adds SWP_NOZORDER below */
201 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
202 { WM_GETTEXT
, sent
|optional
},
203 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
204 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
205 { WM_ERASEBKGND
, sent
|optional
},
206 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
207 { WM_SYNCPAINT
, sent
|optional
},
208 { WM_GETTITLEBARINFOEX
, sent
|optional
},
209 { WM_PAINT
, sent
|optional
},
210 { WM_NCPAINT
, sent
|beginpaint
|optional
},
211 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
212 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
215 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
216 * for a visible overlapped window.
218 static const struct message WmSWP_HideOverlappedSeq
[] = {
219 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
220 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
221 { HCBT_ACTIVATE
, hook
|optional
},
222 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
223 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
224 { WM_NCACTIVATE
, sent
|optional
},
225 { WM_ACTIVATE
, sent
|optional
},
226 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
230 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
231 * for a visible overlapped window.
233 static const struct message WmSWP_ResizeSeq
[] = {
234 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
235 { WM_GETMINMAXINFO
, sent
|defwinproc
},
236 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
237 { WM_NCPAINT
, sent
|optional
},
238 { WM_GETTEXT
, sent
|defwinproc
|optional
},
239 { WM_ERASEBKGND
, sent
|optional
},
240 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
241 { WM_SIZE
, sent
|defwinproc
|optional
},
242 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
243 { WM_NCPAINT
, sent
|optional
},
244 { WM_GETTEXT
, sent
|defwinproc
|optional
},
245 { WM_ERASEBKGND
, sent
|optional
},
246 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
247 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
251 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
252 * for a visible popup window.
254 static const struct message WmSWP_ResizePopupSeq
[] = {
255 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
256 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* Win9x */
257 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
258 { WM_NCPAINT
, sent
|optional
},
259 { WM_GETTEXT
, sent
|defwinproc
|optional
},
260 { WM_ERASEBKGND
, sent
|optional
},
261 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
262 { WM_SIZE
, sent
|defwinproc
|wparam
|optional
, SIZE_RESTORED
},
263 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
264 { WM_NCPAINT
, sent
|optional
},
265 { WM_GETTEXT
, sent
|defwinproc
|optional
},
266 { WM_ERASEBKGND
, sent
|optional
},
267 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
271 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
272 * for a visible overlapped window.
274 static const struct message WmSWP_MoveSeq
[] = {
275 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
},
276 { WM_NCPAINT
, sent
|optional
},
277 { WM_GETTEXT
, sent
|defwinproc
|optional
},
278 { WM_ERASEBKGND
, sent
|optional
},
279 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
280 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
281 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
284 /* Resize with SetWindowPos(SWP_NOZORDER)
285 * for a visible overlapped window
286 * SWP_NOZORDER is stripped by the logging code
288 static const struct message WmSWP_ResizeNoZOrder
[] = {
289 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
},
290 { WM_GETMINMAXINFO
, sent
|defwinproc
},
291 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
292 { WM_NCPAINT
, sent
|optional
},
293 { WM_GETTEXT
, sent
|defwinproc
|optional
},
294 { WM_ERASEBKGND
, sent
|optional
},
295 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
, 0,
296 SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
297 { WM_MOVE
, sent
|defwinproc
|optional
},
298 { WM_SIZE
, sent
|defwinproc
|optional
},
299 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
300 { WM_NCPAINT
, sent
|optional
}, /* Win9x doesn't send it */
301 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
302 { WM_ERASEBKGND
, sent
|optional
}, /* Win9x doesn't send it */
303 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
304 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
308 /* Switch visible mdi children */
309 static const struct message WmSwitchChild
[] = {
310 /* Switch MDI child */
311 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
312 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 1st MDI child */
313 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
314 { WM_CHILDACTIVATE
, sent
},/* in the 1st MDI child */
315 /* Deactivate 2nd MDI child */
316 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
317 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
318 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
319 /* Preparing for maximize and maximize the 1st MDI child */
320 { WM_GETMINMAXINFO
, sent
|defwinproc
}, /* in the 1st MDI child */
321 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
}, /* in the 1st MDI child */
322 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
323 { WM_CHILDACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
324 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 1st MDI child */
325 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
}, /* in the 1st MDI child */
326 /* Lock redraw 2nd MDI child */
327 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
328 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
329 /* Restore 2nd MDI child */
330 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},/* in the 2nd MDI child */
331 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
332 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
333 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 2nd MDI child */
334 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
}, /* in the 2nd MDI child */
335 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
336 /* Redraw 2nd MDI child */
337 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
338 /* Redraw MDI frame */
339 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},/* in MDI frame */
340 { WM_NCCALCSIZE
, sent
|wparam
, 1 },/* in MDI frame */
341 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in MDI frame */
342 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in MDI frame */
343 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
344 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
345 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
346 { HCBT_SETFOCUS
, hook
},
347 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
348 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },/* in the 1st MDI child */
349 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
350 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
351 { WM_SETFOCUS
, sent
},/* in the MDI client */
352 { HCBT_SETFOCUS
, hook
},
353 { WM_KILLFOCUS
, sent
},/* in the MDI client */
354 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
355 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 }, /* in the 1st MDI child */
356 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
357 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
358 { WM_MDIACTIVATE
, sent
|defwinproc
},/* in the 1st MDI child */
359 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 1st MDI child */
363 /* Switch visible not maximized mdi children */
364 static const struct message WmSwitchNotMaximizedChild
[] = {
365 /* Switch not maximized MDI child */
366 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
367 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 2nd MDI child */
368 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
369 { WM_CHILDACTIVATE
, sent
},/* in the 2nd MDI child */
370 /* Deactivate 1st MDI child */
371 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
372 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
373 /* Activate 2nd MDI child */
374 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
}, /* in the 2nd MDI child */
375 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 2nd MDI child */
376 { HCBT_SETFOCUS
, hook
}, /* in the 1st MDI child */
377 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
378 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
379 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
380 { WM_SETFOCUS
, sent
, 0 }, /* in the MDI client */
381 { HCBT_SETFOCUS
, hook
},
382 { WM_KILLFOCUS
, sent
}, /* in the MDI client */
383 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
384 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
385 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
386 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
387 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 2nd MDI child */
392 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
393 SWP_NOZORDER|SWP_FRAMECHANGED)
394 * for a visible overlapped window with WS_CLIPCHILDREN style set.
396 static const struct message WmSWP_FrameChanged_clip
[] = {
397 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
398 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
399 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
400 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
401 { WM_ERASEBKGND
, sent
|parent
|optional
}, /* FIXME: remove optional once Wine is fixed */
402 { WM_NCPAINT
, sent
}, /* wparam != 1 */
403 { WM_ERASEBKGND
, sent
},
404 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
405 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
409 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
410 SWP_NOZORDER|SWP_FRAMECHANGED)
411 * for a visible overlapped window.
413 static const struct message WmSWP_FrameChangedDeferErase
[] = {
414 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
415 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
416 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
417 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
418 { WM_PAINT
, sent
|parent
|optional
},
419 { WM_NCPAINT
, sent
|beginpaint
|parent
|optional
}, /* wparam != 1 */
420 { WM_GETTEXT
, sent
|beginpaint
|parent
|defwinproc
|optional
},
422 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
423 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
427 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
428 SWP_NOZORDER|SWP_FRAMECHANGED)
429 * for a visible overlapped window without WS_CLIPCHILDREN style set.
431 static const struct message WmSWP_FrameChanged_noclip
[] = {
432 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
433 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
434 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
435 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
436 { WM_ERASEBKGND
, sent
|parent
|optional
},
437 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
438 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
440 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
441 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
445 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
446 static const struct message WmShowOverlappedSeq
[] = {
447 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
448 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
449 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
450 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
451 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
452 { WM_GETTEXT
, sent
|defwinproc
|optional
},
453 { WM_ERASEBKGND
, sent
|optional
},
454 { HCBT_ACTIVATE
, hook
|optional
},
455 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
456 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
457 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
458 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
459 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
460 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
461 { WM_GETTEXT
, sent
|defwinproc
|optional
},
462 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
463 { HCBT_SETFOCUS
, hook
|optional
},
464 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
465 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
466 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
467 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
468 { WM_GETTEXT
, sent
|optional
},
469 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
470 { WM_GETTEXT
, sent
|defwinproc
|optional
},
471 { WM_ERASEBKGND
, sent
|optional
},
472 /* Win9x adds SWP_NOZORDER below */
473 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
474 { WM_NCCALCSIZE
, sent
|optional
},
475 { WM_GETTEXT
, sent
|optional
},
476 { WM_NCPAINT
, sent
|optional
},
477 { WM_ERASEBKGND
, sent
|optional
},
478 { WM_SYNCPAINT
, sent
|optional
},
479 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
480 * messages. Does that mean that CreateWindow doesn't set initial
481 * window dimensions for overlapped windows?
486 { WM_PAINT
, sent
|optional
},
487 { WM_NCPAINT
, sent
|beginpaint
|optional
},
490 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
491 static const struct message WmShowMaxOverlappedSeq
[] = {
492 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
493 { WM_GETMINMAXINFO
, sent
},
494 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
495 { WM_GETMINMAXINFO
, sent
|defwinproc
},
496 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
497 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
498 { HCBT_ACTIVATE
, hook
|optional
},
499 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
500 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
501 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
502 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
503 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
504 { WM_GETTEXT
, sent
|defwinproc
|optional
},
505 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
506 { HCBT_SETFOCUS
, hook
|optional
},
507 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
508 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
509 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
510 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
511 { WM_GETTEXT
, sent
|optional
},
512 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
513 { WM_GETTEXT
, sent
|defwinproc
|optional
},
514 { WM_ERASEBKGND
, sent
|optional
},
515 /* Win9x adds SWP_NOZORDER below */
516 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
517 { WM_MOVE
, sent
|defwinproc
},
518 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
519 { WM_GETTEXT
, sent
|optional
},
520 { WM_NCCALCSIZE
, sent
|optional
},
521 { WM_NCPAINT
, sent
|optional
},
522 { WM_ERASEBKGND
, sent
|optional
},
523 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
524 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
525 { WM_SYNCPAINT
, sent
|optional
},
526 { WM_GETTITLEBARINFOEX
, sent
|optional
},
527 { WM_PAINT
, sent
|optional
},
528 { WM_NCPAINT
, sent
|beginpaint
|optional
},
529 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
532 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
533 static const struct message WmShowRestoreMaxOverlappedSeq
[] = {
534 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
535 { WM_GETTEXT
, sent
|optional
},
536 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
537 { WM_GETMINMAXINFO
, sent
|defwinproc
},
538 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
539 { WM_NCPAINT
, sent
|optional
},
540 { WM_GETTEXT
, sent
|defwinproc
|optional
},
541 { WM_ERASEBKGND
, sent
|optional
},
542 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
543 { WM_MOVE
, sent
|defwinproc
|optional
},
544 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
545 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
546 { WM_NCPAINT
, sent
|optional
},
547 { WM_ERASEBKGND
, sent
|optional
},
548 { WM_PAINT
, sent
|optional
},
549 { WM_GETTITLEBARINFOEX
, sent
|optional
},
550 { WM_NCPAINT
, sent
|beginpaint
|optional
},
551 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
554 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
555 static const struct message WmShowRestoreMinOverlappedSeq
[] = {
556 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
557 { WM_QUERYOPEN
, sent
|optional
},
558 { WM_GETTEXT
, sent
|optional
},
559 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
560 { WM_WINDOWPOSCHANGING
, sent
|optional
}, /* SWP_NOSIZE|SWP_NOMOVE */
561 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
562 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
563 { WM_MOVE
, sent
|optional
},
564 { WM_SIZE
, sent
|wparam
|optional
, SIZE_RESTORED
},
565 { WM_GETTEXT
, sent
|optional
},
566 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
|SWP_NOCOPYBITS
},
567 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
},
568 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
569 { HCBT_ACTIVATE
, hook
|optional
},
570 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
571 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
572 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
573 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
574 { WM_GETTEXT
, sent
|defwinproc
|optional
},
575 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
576 { HCBT_SETFOCUS
, hook
|optional
},
577 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
578 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
579 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
580 { WM_GETTEXT
, sent
|optional
},
581 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
582 { WM_GETTEXT
, sent
|defwinproc
|optional
},
583 { WM_ERASEBKGND
, sent
},
584 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_STATECHANGED
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
},
585 { WM_MOVE
, sent
|defwinproc
},
586 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
587 { HCBT_SETFOCUS
, hook
|optional
},
588 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
589 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
590 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
591 { WM_ERASEBKGND
, sent
|optional
},
592 { HCBT_SETFOCUS
, hook
|optional
},
593 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
594 { WM_ACTIVATE
, sent
|wparam
, 1 },
595 { WM_GETTEXT
, sent
|optional
},
596 { WM_PAINT
, sent
|optional
},
597 { WM_GETTITLEBARINFOEX
, sent
|optional
},
598 { WM_NCPAINT
, sent
|beginpaint
|optional
},
599 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
602 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
603 static const struct message WmShowMinOverlappedSeq
[] = {
604 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
605 { HCBT_SETFOCUS
, hook
|optional
},
606 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
607 { WM_KILLFOCUS
, sent
|optional
},
608 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
609 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
610 { WM_GETTEXT
, sent
|optional
},
611 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCOPYBITS
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
612 { WM_GETMINMAXINFO
, sent
|defwinproc
},
613 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
614 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
615 { WM_NCPAINT
, sent
|optional
},
616 { WM_GETTEXT
, sent
|defwinproc
|optional
},
617 { WM_WINDOWPOSCHANGED
, sent
},
618 { WM_MOVE
, sent
|defwinproc
},
619 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
620 { WM_NCCALCSIZE
, sent
|optional
},
621 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
622 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
623 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
624 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
625 { WM_GETTEXT
, sent
|defwinproc
|optional
},
626 { WM_ACTIVATE
, sent
|optional
},
627 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
629 /* Vista sometimes restores the window right away... */
630 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
631 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
632 { HCBT_MINMAX
, hook
|optional
|lparam
, 0, SW_RESTORE
},
633 { WM_QUERYOPEN
, sent
|optional
},
634 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
635 { WM_GETMINMAXINFO
, sent
|optional
|defwinproc
},
636 { WM_NCCALCSIZE
, sent
|optional
|wparam
, TRUE
},
637 { HCBT_ACTIVATE
, hook
|optional
},
638 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 1 },
639 { WM_NCACTIVATE
, sent
|optional
},
640 { WM_GETTEXT
, sent
|optional
},
641 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
642 { HCBT_SETFOCUS
, hook
|optional
},
643 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
644 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
645 { WM_SETFOCUS
, sent
|optional
},
646 { WM_NCPAINT
, sent
|optional
},
647 { WM_GETTEXT
, sent
|defwinproc
|optional
},
648 { WM_ERASEBKGND
, sent
|optional
},
649 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
650 { WM_MOVE
, sent
|defwinproc
|optional
},
651 { WM_SIZE
, sent
|defwinproc
|optional
|wparam
, SIZE_RESTORED
},
652 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
653 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
654 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
656 { WM_PAINT
, sent
|optional
},
657 { WM_NCPAINT
, sent
|beginpaint
|optional
},
658 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
661 /* ShowWindow(SW_HIDE) for a visible overlapped window */
662 static const struct message WmHideOverlappedSeq
[] = {
663 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
664 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
665 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
666 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
667 { WM_SIZE
, sent
|optional
}, /* XP doesn't send it */
668 { WM_MOVE
, sent
|optional
}, /* XP doesn't send it */
669 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
670 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
671 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
672 { HCBT_SETFOCUS
, hook
|optional
},
673 { WM_KILLFOCUS
, sent
|wparam
|optional
, 0 },
674 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
675 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
678 /* DestroyWindow for a visible overlapped window */
679 static const struct message WmDestroyOverlappedSeq
[] = {
680 { HCBT_DESTROYWND
, hook
},
681 { 0x0090, sent
|optional
},
682 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
683 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
684 { 0x0090, sent
|optional
},
685 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
686 { WM_NCACTIVATE
, sent
|optional
|wparam
, 0 },
687 { WM_ACTIVATE
, sent
|optional
},
688 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 0 },
689 { WM_KILLFOCUS
, sent
|optional
|wparam
, 0 },
690 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
691 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
692 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
693 { WM_DESTROY
, sent
},
694 { WM_NCDESTROY
, sent
},
697 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
698 static const struct message WmCreateMaxPopupSeq
[] = {
699 { HCBT_CREATEWND
, hook
},
700 { WM_NCCREATE
, sent
},
701 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
703 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
704 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
706 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
707 { WM_GETMINMAXINFO
, sent
},
708 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
709 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
710 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
711 { WM_MOVE
, sent
|defwinproc
},
712 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
713 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
714 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
715 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
716 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
717 { HCBT_ACTIVATE
, hook
},
718 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
719 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
720 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
721 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
722 { WM_ERASEBKGND
, sent
|optional
},
723 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_NOMOVE
|SWP_NOSIZE
},
724 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
725 { WM_NCACTIVATE
, sent
},
726 { WM_ACTIVATE
, sent
|wparam
, 1 },
727 { HCBT_SETFOCUS
, hook
},
728 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
729 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
730 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
731 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
732 { WM_GETTEXT
, sent
|optional
},
733 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
734 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
735 { WM_ERASEBKGND
, sent
|optional
},
736 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
737 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
738 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
741 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
742 static const struct message WmCreateInvisibleMaxPopupSeq
[] = {
743 { HCBT_CREATEWND
, hook
},
744 { WM_NCCREATE
, sent
},
745 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
747 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
748 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
750 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
751 { WM_GETMINMAXINFO
, sent
},
752 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
753 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
754 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
755 { WM_MOVE
, sent
|defwinproc
},
756 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
757 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
760 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
761 static const struct message WmShowMaxPopupResizedSeq_todo
[] = {
762 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
763 { WM_GETMINMAXINFO
, sent
},
764 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
765 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
766 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
767 { HCBT_ACTIVATE
, hook
},
768 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
769 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
770 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
771 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
772 { WM_ERASEBKGND
, sent
|optional
},
773 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
774 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
775 { WM_NCACTIVATE
, sent
},
776 { WM_ACTIVATE
, sent
|wparam
, 1 },
777 { HCBT_SETFOCUS
, hook
},
778 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
779 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
780 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
781 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
782 { WM_GETTEXT
, sent
|optional
},
783 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
784 { WM_ERASEBKGND
, sent
|optional
},
785 { WM_WINDOWPOSCHANGED
, sent
},
786 /* WinNT4.0 sends WM_MOVE */
787 { WM_MOVE
, sent
|defwinproc
|optional
},
788 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
789 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
792 static const struct message WmShowMaxPopupResizedSeq
[] = {
793 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
794 { WM_GETMINMAXINFO
, sent
},
795 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
796 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
797 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
798 { HCBT_ACTIVATE
, hook
},
799 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
800 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
801 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
802 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
803 { WM_ERASEBKGND
, sent
|optional
},
804 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
805 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
806 { WM_NCACTIVATE
, sent
},
807 { WM_ACTIVATE
, sent
|wparam
, 1 },
808 { HCBT_SETFOCUS
, hook
},
809 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
810 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
811 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
812 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
813 { WM_GETTEXT
, sent
|optional
},
814 { WM_NCPAINT
, sent
|optional
}, /* We'll check WM_NCPAINT behaviour in another test */
815 { WM_ERASEBKGND
, sent
|optional
},
816 { WM_WINDOWPOSCHANGED
, sent
},
817 /* WinNT4.0 sends WM_MOVE */
818 { WM_MOVE
, sent
|defwinproc
|optional
},
819 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
820 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
823 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
824 static const struct message WmShowMaxPopupSeq
[] = {
825 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
826 { WM_GETMINMAXINFO
, sent
},
827 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
828 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
829 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
830 { HCBT_ACTIVATE
, hook
},
831 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
832 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
833 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
834 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
835 { WM_ERASEBKGND
, sent
|optional
},
836 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOMOVE
|SWP_NOSIZE
},
837 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
838 { WM_NCACTIVATE
, sent
},
839 { WM_ACTIVATE
, sent
|wparam
, 1 },
840 { HCBT_SETFOCUS
, hook
},
841 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
842 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
843 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
844 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
845 { WM_GETTEXT
, sent
|optional
},
846 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
847 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
848 { WM_ERASEBKGND
, sent
|optional
},
849 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
850 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
851 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
},
852 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
855 /* CreateWindow(WS_VISIBLE) for popup window */
856 static const struct message WmCreatePopupSeq
[] = {
857 { HCBT_CREATEWND
, hook
},
858 { WM_NCCREATE
, sent
},
859 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
861 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
862 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
864 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
865 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
866 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
867 { HCBT_ACTIVATE
, hook
},
868 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
869 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
870 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
871 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
872 { WM_ERASEBKGND
, sent
|optional
},
873 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
874 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
875 { WM_NCACTIVATE
, sent
},
876 { WM_ACTIVATE
, sent
|wparam
, 1 },
877 { HCBT_SETFOCUS
, hook
},
878 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
879 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
880 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
881 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
882 { WM_GETTEXT
, sent
|optional
},
883 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
884 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
885 { WM_ERASEBKGND
, sent
|optional
},
886 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
889 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
890 static const struct message WmShowVisMaxPopupSeq
[] = {
891 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
892 { WM_GETMINMAXINFO
, sent
},
893 { WM_GETTEXT
, sent
|optional
},
894 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
895 { WM_GETTEXT
, sent
|optional
},
896 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
897 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
898 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
899 { WM_ERASEBKGND
, sent
|optional
},
900 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
901 { WM_MOVE
, sent
|defwinproc
},
902 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
903 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
906 /* CreateWindow (for a child popup window, not initially visible) */
907 static const struct message WmCreateChildPopupSeq
[] = {
908 { HCBT_CREATEWND
, hook
},
909 { WM_NCCREATE
, sent
},
910 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
912 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
913 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
917 /* CreateWindow (for a popup window, not initially visible,
918 * which sets WS_VISIBLE in WM_CREATE handler)
920 static const struct message WmCreateInvisiblePopupSeq
[] = {
921 { HCBT_CREATEWND
, hook
},
922 { WM_NCCREATE
, sent
},
923 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
925 { WM_STYLECHANGING
, sent
},
926 { WM_STYLECHANGED
, sent
},
927 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
928 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
932 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
933 * for a popup window with WS_VISIBLE style set
935 static const struct message WmShowVisiblePopupSeq_2
[] = {
936 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
939 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
940 * for a popup window with WS_VISIBLE style set
942 static const struct message WmShowVisiblePopupSeq_3
[] = {
943 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
944 { HCBT_ACTIVATE
, hook
},
945 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
946 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
947 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
948 { WM_NCACTIVATE
, sent
},
949 { WM_ACTIVATE
, sent
|wparam
, 1 },
950 { HCBT_SETFOCUS
, hook
},
951 { WM_KILLFOCUS
, sent
|parent
},
952 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
953 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
954 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
955 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
956 { WM_SETFOCUS
, sent
|defwinproc
},
957 { WM_GETTEXT
, sent
|optional
},
958 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_SHOWWINDOW
},
961 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
963 static const struct message WmShowPopupExtremeLocationSeq
[] = {
964 { HCBT_CREATEWND
, hook
},
965 { WM_NCCREATE
, sent
},
966 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
968 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
969 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
971 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
972 { WM_WINDOWPOSCHANGING
, sent
},
973 { HCBT_ACTIVATE
, hook
},
974 { WM_WINDOWPOSCHANGING
, sent
|optional
},
975 { WM_QUERYNEWPALETTE
, sent
|optional
},
976 { WM_ACTIVATEAPP
, sent
},
977 { WM_NCACTIVATE
, sent
},
978 { WM_ACTIVATE
, sent
},
979 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
980 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
981 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
982 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
983 { HCBT_SETFOCUS
, hook
},
984 { WM_SETFOCUS
, sent
|defwinproc
},
985 { WM_NCPAINT
, sent
|wparam
, 1 },
986 { WM_ERASEBKGND
, sent
},
987 { WM_WINDOWPOSCHANGED
, sent
},
988 /* occasionally received on test machines */
989 { WM_NCPAINT
, sent
|optional
},
990 { WM_ERASEBKGND
, sent
|optional
},
993 /* CreateWindow (for a popup window with WS_VISIBLE style set)
995 static const struct message WmShowPopupFirstDrawSeq_1
[] = {
996 { HCBT_CREATEWND
, hook
},
997 { WM_NCCREATE
, sent
},
998 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1000 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1001 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1003 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1004 { WM_WINDOWPOSCHANGING
, sent
},
1005 { HCBT_ACTIVATE
, hook
},
1006 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1007 { WM_QUERYNEWPALETTE
, sent
|optional
},
1008 { WM_ACTIVATEAPP
, sent
},
1009 { WM_NCACTIVATE
, sent
},
1010 { WM_ACTIVATE
, sent
},
1011 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1012 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1013 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1014 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1015 { HCBT_SETFOCUS
, hook
},
1016 { WM_SETFOCUS
, sent
|defwinproc
},
1017 { WM_NCPAINT
, sent
|wparam
, 1 },
1018 { WM_ERASEBKGND
, sent
},
1019 { WM_WINDOWPOSCHANGED
, sent
},
1021 /* occasionally received on test machines */
1022 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1023 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1026 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1028 static const struct message WmShowPopupFirstDrawSeq_2
[] = {
1029 { HCBT_CREATEWND
, hook
},
1030 { WM_NCCREATE
, sent
},
1031 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1032 { WM_CREATE
, sent
},
1033 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1034 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1036 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1037 { WM_GETMINMAXINFO
, sent
},
1038 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_STATECHANGED
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
1039 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
1040 { HCBT_ACTIVATE
, hook
},
1041 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1042 { WM_NCPAINT
, sent
|optional
|wparam
, 1 },
1043 { WM_ERASEBKGND
, sent
|optional
},
1044 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1045 { WM_QUERYNEWPALETTE
, sent
|optional
},
1046 { WM_ACTIVATEAPP
, sent
},
1047 { WM_NCACTIVATE
, sent
},
1048 { WM_ACTIVATE
, sent
},
1049 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1050 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1051 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1052 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1053 { HCBT_SETFOCUS
, hook
},
1054 { WM_SETFOCUS
, sent
|defwinproc
},
1055 { WM_NCPAINT
, sent
|wparam
, 1 },
1056 { WM_ERASEBKGND
, sent
},
1057 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1058 { WM_MOVE
, sent
|defwinproc
},
1059 { WM_SIZE
, sent
|defwinproc
, 0 },
1061 /* occasionally received on test machines */
1062 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1063 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1066 static const struct message WmFirstDrawSetWindowPosSeq1
[] = {
1067 { HCBT_CREATEWND
, hook
},
1068 { WM_NCCREATE
, sent
},
1069 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1070 { WM_CREATE
, sent
},
1071 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1072 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1074 { WM_WINDOWPOSCHANGING
, sent
},
1075 { HCBT_ACTIVATE
, hook
},
1076 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1077 { WM_QUERYNEWPALETTE
, sent
|optional
},
1078 { WM_ACTIVATEAPP
, sent
},
1079 { WM_NCACTIVATE
, sent
},
1080 { WM_ACTIVATE
, sent
},
1081 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1082 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1083 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1084 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1085 { HCBT_SETFOCUS
, hook
},
1086 { WM_SETFOCUS
, sent
|defwinproc
},
1087 { WM_NCPAINT
, sent
|wparam
, 1 },
1088 { WM_ERASEBKGND
, sent
},
1089 { WM_WINDOWPOSCHANGED
, sent
},
1090 { WM_MOVE
, sent
|defwinproc
},
1093 static const struct message WmFirstDrawSetWindowPosSeq2
[] = {
1094 { HCBT_CREATEWND
, hook
},
1095 { WM_NCCREATE
, sent
},
1096 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1097 { WM_CREATE
, sent
},
1098 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1099 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1101 { WM_WINDOWPOSCHANGING
, sent
},
1102 { HCBT_ACTIVATE
, hook
},
1103 { WM_QUERYNEWPALETTE
, sent
|optional
},
1104 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1105 { WM_ACTIVATEAPP
, sent
},
1106 { WM_NCACTIVATE
, sent
},
1107 { WM_ACTIVATE
, sent
},
1108 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1109 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1110 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1111 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1112 { HCBT_SETFOCUS
, hook
},
1113 { WM_SETFOCUS
, sent
|defwinproc
},
1114 { WM_WINDOWPOSCHANGED
, sent
},
1115 { WM_MOVE
, sent
|defwinproc
},
1118 static const struct message WmFirstDrawSetWindowPosSeq3
[] = {
1119 { HCBT_CREATEWND
, hook
},
1120 { WM_NCCREATE
, sent
},
1121 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1122 { WM_CREATE
, sent
},
1123 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1124 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1126 { HCBT_ACTIVATE
, hook
|optional
},
1127 /* Probably shouldn't happen, but not part of this test */
1128 { WM_QUERYNEWPALETTE
, sent
|optional
},
1129 { WM_ACTIVATEAPP
, sent
|optional
},
1130 { WM_NCACTIVATE
, sent
|optional
},
1131 { WM_ACTIVATE
, sent
|optional
},
1132 { HCBT_SETFOCUS
, hook
|optional
},
1133 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
1136 static const struct message WmFirstDrawSetWindowPosSeq4
[] = {
1137 { HCBT_CREATEWND
, hook
},
1138 { WM_NCCREATE
, sent
},
1139 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1140 { WM_CREATE
, sent
},
1141 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1142 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1144 { WM_WINDOWPOSCHANGING
, sent
},
1145 { HCBT_ACTIVATE
, hook
},
1146 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1147 { WM_QUERYNEWPALETTE
, sent
|optional
},
1148 { WM_ACTIVATEAPP
, sent
},
1149 { WM_NCACTIVATE
, sent
},
1150 { WM_ACTIVATE
, sent
},
1151 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1152 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1153 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1154 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1155 { HCBT_SETFOCUS
, hook
},
1156 { WM_SETFOCUS
, sent
|defwinproc
},
1157 { WM_NCPAINT
, sent
|wparam
, 1 },
1158 { WM_ERASEBKGND
, sent
},
1159 { WM_WINDOWPOSCHANGED
, sent
},
1162 static const struct message WmFirstDrawSetWindowPosSeq5
[] = {
1163 { HCBT_CREATEWND
, hook
},
1164 { WM_NCCREATE
, sent
},
1165 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1166 { WM_CREATE
, sent
},
1167 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1168 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1170 { WM_WINDOWPOSCHANGING
, sent
},
1171 { HCBT_ACTIVATE
, hook
},
1172 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1173 { WM_QUERYNEWPALETTE
, sent
|optional
},
1174 { WM_ACTIVATEAPP
, sent
},
1175 { WM_NCACTIVATE
, sent
},
1176 { WM_ACTIVATE
, sent
},
1177 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1178 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1179 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1180 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1181 { HCBT_SETFOCUS
, hook
},
1182 { WM_SETFOCUS
, sent
|defwinproc
},
1183 { WM_WINDOWPOSCHANGED
, sent
},
1186 static const struct message WmFirstDrawChildSeq1
[] = {
1189 static const struct message WmFirstDrawChildSeq2
[] = {
1190 { WM_NCPAINT
, sent
|wparam
, 1 },
1191 { WM_ERASEBKGND
, sent
},
1192 /* occasionally received on test machines */
1193 { WM_NCPAINT
, sent
|optional
},
1194 { WM_ERASEBKGND
, sent
|optional
},
1197 /* CreateWindow (for child window, not initially visible) */
1198 static const struct message WmCreateChildSeq
[] = {
1199 { HCBT_CREATEWND
, hook
},
1200 { WM_NCCREATE
, sent
},
1201 /* child is inserted into parent's child list after WM_NCCREATE returns */
1202 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1203 { WM_CREATE
, sent
},
1204 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1205 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1207 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1210 /* CreateWindow (for maximized child window, not initially visible) */
1211 static const struct message WmCreateMaximizedChildSeq
[] = {
1212 { HCBT_CREATEWND
, hook
},
1213 { WM_NCCREATE
, sent
},
1214 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1215 { WM_CREATE
, sent
},
1216 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1217 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1219 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1220 { WM_GETMINMAXINFO
, sent
},
1221 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
1222 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1223 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1224 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1225 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1226 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1229 /* CreateWindow (for a child window, initially visible) */
1230 static const struct message WmCreateVisibleChildSeq
[] = {
1231 { HCBT_CREATEWND
, hook
},
1232 { WM_NCCREATE
, sent
},
1233 /* child is inserted into parent's child list after WM_NCCREATE returns */
1234 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1235 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1236 { WM_CREATE
, sent
},
1237 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1238 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1240 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1241 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1242 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1243 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1244 { WM_ERASEBKGND
, sent
|parent
|optional
},
1245 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1246 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
1247 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1250 /* ShowWindow(SW_SHOW) for a not visible child window */
1251 static const struct message WmShowChildSeq
[] = {
1252 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1253 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1254 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1255 { WM_ERASEBKGND
, sent
|parent
|optional
},
1256 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1259 /* ShowWindow(SW_HIDE) for a visible child window */
1260 static const struct message WmHideChildSeq
[] = {
1261 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1262 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1263 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1264 { WM_ERASEBKGND
, sent
|parent
|optional
},
1265 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1268 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1269 static const struct message WmHideChildSeq2
[] = {
1270 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1271 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1272 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1273 { WM_ERASEBKGND
, sent
|parent
|optional
},
1274 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1277 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1278 * for a not visible child window
1280 static const struct message WmShowChildSeq_2
[] = {
1281 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1282 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1283 { WM_CHILDACTIVATE
, sent
},
1284 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1287 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1288 * for a not visible child window
1290 static const struct message WmShowChildSeq_3
[] = {
1291 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1292 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1293 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1296 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1297 * for a visible child window with a caption
1299 static const struct message WmShowChildSeq_4
[] = {
1300 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1301 { WM_CHILDACTIVATE
, sent
},
1304 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1305 static const struct message WmShowChildInvisibleParentSeq_1
[] = {
1306 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1307 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1308 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1309 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1310 { WM_CHILDACTIVATE
, sent
|optional
},
1311 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1312 { WM_MOVE
, sent
|defwinproc
},
1313 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1314 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1315 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1316 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1317 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1318 { WM_GETTEXT
, sent
|optional
},
1321 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1322 static const struct message WmShowChildInvisibleParentSeq_1r
[] = {
1323 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1326 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1327 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
1328 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1329 { WM_GETMINMAXINFO
, sent
},
1330 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
1331 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1332 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1333 { WM_CHILDACTIVATE
, sent
},
1334 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1335 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1336 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1339 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1340 static const struct message WmShowChildInvisibleParentSeq_2r
[] = {
1341 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1344 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1345 static const struct message WmShowChildInvisibleParentSeq_3
[] = {
1346 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1347 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1348 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1349 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1350 { WM_CHILDACTIVATE
, sent
},
1351 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1352 { WM_MOVE
, sent
|defwinproc
},
1353 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1354 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1355 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1356 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1357 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1358 { WM_GETTEXT
, sent
|optional
},
1361 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1362 static const struct message WmShowChildInvisibleParentSeq_3r
[] = {
1363 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1366 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1367 static const struct message WmShowChildInvisibleParentSeq_4
[] = {
1368 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1369 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1370 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1371 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1372 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1373 { WM_MOVE
, sent
|defwinproc
},
1374 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1375 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1376 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1377 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1378 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
},
1379 { WM_GETTEXT
, sent
|optional
},
1382 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1383 static const struct message WmShowChildInvisibleParentSeq_4r
[] = {
1384 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1387 /* ShowWindow(SW_SHOW) for child with invisible parent */
1388 static const struct message WmShowChildInvisibleParentSeq_5
[] = {
1389 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1392 /* ShowWindow(SW_HIDE) for child with invisible parent */
1393 static const struct message WmHideChildInvisibleParentSeq
[] = {
1394 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1397 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1398 static const struct message WmShowChildInvisibleParentSeq_6
[] = {
1399 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1400 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1401 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1404 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1405 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
1406 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1407 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1408 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1411 /* DestroyWindow for a visible child window */
1412 static const struct message WmDestroyChildSeq
[] = {
1413 { HCBT_DESTROYWND
, hook
},
1414 { 0x0090, sent
|optional
},
1415 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1416 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1417 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1418 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1419 { WM_ERASEBKGND
, sent
|parent
|optional
},
1420 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1421 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
1422 { WM_KILLFOCUS
, sent
},
1423 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1424 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
1425 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1426 { WM_SETFOCUS
, sent
|parent
},
1427 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1428 { WM_DESTROY
, sent
},
1429 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
1430 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
1431 { WM_NCDESTROY
, sent
},
1434 /* visible child window destroyed by thread exit */
1435 static const struct message WmExitThreadSeq
[] = {
1436 { WM_NCDESTROY
, sent
}, /* actually in grandchild */
1437 { WM_PAINT
, sent
|parent
},
1438 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
1441 /* DestroyWindow for a visible child window with invisible parent */
1442 static const struct message WmDestroyInvisibleChildSeq
[] = {
1443 { HCBT_DESTROYWND
, hook
},
1444 { 0x0090, sent
|optional
},
1445 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1446 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1447 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1448 { WM_DESTROY
, sent
},
1449 { WM_NCDESTROY
, sent
},
1452 /* Resizing child window with MoveWindow (32) */
1453 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1454 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1455 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1456 { WM_ERASEBKGND
, sent
|parent
|optional
},
1457 { WM_ERASEBKGND
, sent
|optional
},
1458 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1459 { WM_MOVE
, sent
|defwinproc
},
1460 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1461 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1464 /* Creation of a custom dialog (32) */
1465 static const struct message WmCreateCustomDialogSeq
[] = {
1466 { HCBT_CREATEWND
, hook
},
1467 { WM_GETMINMAXINFO
, sent
},
1468 { WM_NCCREATE
, sent
},
1469 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1470 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1471 { WM_CREATE
, sent
},
1472 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1473 { WM_NOTIFYFORMAT
, sent
|optional
},
1474 { WM_QUERYUISTATE
, sent
|optional
},
1475 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1476 { WM_GETMINMAXINFO
, sent
|optional
},
1477 { WM_NCCALCSIZE
, sent
|optional
},
1478 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1479 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1480 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1481 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1482 { HCBT_ACTIVATE
, hook
},
1483 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1486 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1488 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1490 { WM_NCACTIVATE
, sent
},
1491 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1492 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1493 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1494 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1495 { WM_ACTIVATE
, sent
|wparam
, 1 },
1496 { WM_GETTEXT
, sent
|optional
},
1497 { WM_KILLFOCUS
, sent
|parent
},
1498 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1499 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1500 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1501 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1502 { WM_SETFOCUS
, sent
},
1503 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1504 { WM_NCPAINT
, sent
|wparam
, 1 },
1505 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1506 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1507 { WM_ERASEBKGND
, sent
},
1508 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1509 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1510 { WM_GETTEXT
, sent
|optional
},
1511 { WM_GETTEXT
, sent
|optional
},
1512 { WM_NCCALCSIZE
, sent
|optional
},
1513 { WM_NCPAINT
, sent
|optional
},
1514 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1515 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1516 { WM_ERASEBKGND
, sent
|optional
},
1517 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1518 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1519 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1523 /* Calling EndDialog for a custom dialog (32) */
1524 static const struct message WmEndCustomDialogSeq
[] = {
1525 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1526 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1527 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1528 { WM_GETTEXT
, sent
|optional
},
1529 { HCBT_ACTIVATE
, hook
},
1530 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1531 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1532 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1533 { WM_ACTIVATE
, sent
|wparam
, 0 },
1534 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1535 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1536 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1537 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1538 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1539 { HCBT_SETFOCUS
, hook
},
1540 { WM_KILLFOCUS
, sent
},
1541 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1542 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1543 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1544 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1545 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1548 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1549 static const struct message WmShowCustomDialogSeq
[] = {
1550 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1551 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1552 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1553 { HCBT_ACTIVATE
, hook
},
1554 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1556 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1558 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1559 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1560 { WM_NCACTIVATE
, sent
},
1561 { WM_ACTIVATE
, sent
|wparam
, 1 },
1562 { WM_GETTEXT
, sent
|optional
},
1564 { WM_KILLFOCUS
, sent
|parent
},
1565 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1566 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1567 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1568 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1569 { WM_SETFOCUS
, sent
},
1570 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1571 { WM_NCPAINT
, sent
|wparam
, 1 },
1572 { WM_ERASEBKGND
, sent
},
1573 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1574 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1577 /* Creation and destruction of a modal dialog (32) */
1578 static const struct message WmModalDialogSeq
[] = {
1579 { WM_CANCELMODE
, sent
|parent
},
1580 { HCBT_SETFOCUS
, hook
},
1581 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1582 { WM_KILLFOCUS
, sent
|parent
},
1583 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1584 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1585 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1586 { HCBT_CREATEWND
, hook
},
1587 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1588 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1589 { WM_SETFONT
, sent
},
1590 { WM_INITDIALOG
, sent
},
1591 { WM_CHANGEUISTATE
, sent
|optional
},
1592 { WM_UPDATEUISTATE
, sent
|optional
},
1593 { WM_SHOWWINDOW
, sent
},
1594 { HCBT_ACTIVATE
, hook
},
1595 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1596 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1597 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1598 { WM_NCACTIVATE
, sent
},
1599 { WM_GETTEXT
, sent
|optional
},
1600 { WM_ACTIVATE
, sent
|wparam
, 1 },
1601 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1602 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1603 { WM_NCPAINT
, sent
|optional
},
1604 { WM_GETTEXT
, sent
|optional
},
1605 { WM_ERASEBKGND
, sent
|optional
},
1606 { WM_CTLCOLORDLG
, sent
|optional
},
1607 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1608 { WM_GETTEXT
, sent
|optional
},
1609 { WM_NCCALCSIZE
, sent
|optional
},
1610 { WM_NCPAINT
, sent
|optional
},
1611 { WM_GETTEXT
, sent
|optional
},
1612 { WM_ERASEBKGND
, sent
|optional
},
1613 { WM_CTLCOLORDLG
, sent
|optional
},
1614 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1615 { WM_PAINT
, sent
|optional
},
1616 { WM_CTLCOLORBTN
, sent
|optional
},
1617 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1618 { WM_ENTERIDLE
, sent
|parent
|optional
},
1619 { WM_ENTERIDLE
, sent
|parent
|optional
},
1620 { WM_ENTERIDLE
, sent
|parent
|optional
},
1621 { WM_ENTERIDLE
, sent
|parent
|optional
},
1622 { WM_ENTERIDLE
, sent
|parent
|optional
},
1623 { WM_ENTERIDLE
, sent
|parent
|optional
},
1624 { WM_ENTERIDLE
, sent
|parent
|optional
},
1625 { WM_ENTERIDLE
, sent
|parent
|optional
},
1626 { WM_ENTERIDLE
, sent
|parent
|optional
},
1627 { WM_ENTERIDLE
, sent
|parent
|optional
},
1628 { WM_ENTERIDLE
, sent
|parent
|optional
},
1629 { WM_ENTERIDLE
, sent
|parent
|optional
},
1630 { WM_ENTERIDLE
, sent
|parent
|optional
},
1631 { WM_ENTERIDLE
, sent
|parent
|optional
},
1632 { WM_ENTERIDLE
, sent
|parent
|optional
},
1633 { WM_ENTERIDLE
, sent
|parent
|optional
},
1634 { WM_ENTERIDLE
, sent
|parent
|optional
},
1635 { WM_ENTERIDLE
, sent
|parent
|optional
},
1636 { WM_ENTERIDLE
, sent
|parent
|optional
},
1637 { WM_ENTERIDLE
, sent
|parent
|optional
},
1639 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1640 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1641 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1642 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1643 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1644 { WM_GETTEXT
, sent
|optional
},
1645 { HCBT_ACTIVATE
, hook
},
1646 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1647 { WM_GETTEXT
, sent
|optional
},
1648 { WM_ACTIVATE
, sent
|wparam
, 0 },
1649 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1650 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1651 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1652 { HCBT_SETFOCUS
, hook
},
1653 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1654 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1655 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1656 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1657 { HCBT_DESTROYWND
, hook
},
1658 { 0x0090, sent
|optional
},
1659 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1660 { WM_DESTROY
, sent
},
1661 { WM_NCDESTROY
, sent
},
1664 static const struct message WmModalDialogSeq_2
[] = {
1665 { WM_CANCELMODE
, sent
},
1666 { HCBT_SETFOCUS
, hook
},
1667 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1668 { WM_KILLFOCUS
, sent
},
1669 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1670 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1671 { WM_ENABLE
, sent
|wparam
, 0 },
1672 { HCBT_CREATEWND
, hook
},
1673 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1674 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1675 { WM_SETFONT
, sent
},
1676 { WM_INITDIALOG
, sent
},
1677 { WM_CHANGEUISTATE
, sent
|optional
},
1678 { WM_UPDATEUISTATE
, sent
|optional
},
1679 { WM_ENABLE
, sent
|wparam
, 1 },
1680 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1681 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1682 { WM_CHANGEUISTATE
, sent
|optional
},
1683 { WM_UPDATEUISTATE
, sent
|optional
},
1684 { HCBT_DESTROYWND
, hook
},
1685 { 0x0090, sent
|optional
},
1686 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
1687 { WM_DESTROY
, sent
},
1688 { WM_NCDESTROY
, sent
},
1691 /* SetMenu for NonVisible windows with size change*/
1692 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1693 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1694 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1695 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1696 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1697 { WM_MOVE
, sent
|defwinproc
},
1698 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1699 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1700 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1701 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1702 { WM_GETTEXT
, sent
|optional
},
1703 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1706 /* SetMenu for NonVisible windows with no size change */
1707 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1708 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1709 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1710 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1711 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1714 /* SetMenu for Visible windows with size change */
1715 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1716 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1717 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1718 { 0x0093, sent
|defwinproc
|optional
},
1719 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1720 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1721 { 0x0093, sent
|defwinproc
|optional
},
1722 { 0x0093, sent
|defwinproc
|optional
},
1723 { 0x0091, sent
|defwinproc
|optional
},
1724 { 0x0092, sent
|defwinproc
|optional
},
1725 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1726 { WM_ERASEBKGND
, sent
|optional
},
1727 { WM_ACTIVATE
, sent
|optional
},
1728 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1729 { WM_MOVE
, sent
|defwinproc
},
1730 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1731 { 0x0093, sent
|optional
},
1732 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1733 { 0x0093, sent
|defwinproc
|optional
},
1734 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1735 { 0x0093, sent
|defwinproc
|optional
},
1736 { 0x0093, sent
|defwinproc
|optional
},
1737 { 0x0091, sent
|defwinproc
|optional
},
1738 { 0x0092, sent
|defwinproc
|optional
},
1739 { WM_ERASEBKGND
, sent
|optional
},
1740 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1741 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1744 /* SetMenu for Visible windows with no size change */
1745 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1746 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1747 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1748 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1749 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1750 { WM_ERASEBKGND
, sent
|optional
},
1751 { WM_ACTIVATE
, sent
|optional
},
1752 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1753 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1756 /* DrawMenuBar for a visible window */
1757 static const struct message WmDrawMenuBarSeq
[] =
1759 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1760 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1761 { 0x0093, sent
|defwinproc
|optional
},
1762 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1763 { 0x0093, sent
|defwinproc
|optional
},
1764 { 0x0093, sent
|defwinproc
|optional
},
1765 { 0x0091, sent
|defwinproc
|optional
},
1766 { 0x0092, sent
|defwinproc
|optional
},
1767 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1768 { WM_ERASEBKGND
, sent
|optional
},
1769 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1770 { 0x0093, sent
|optional
},
1771 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1775 static const struct message WmSetRedrawFalseSeq
[] =
1777 { WM_SETREDRAW
, sent
|wparam
, 0 },
1781 static const struct message WmSetRedrawTrueSeq
[] =
1783 { WM_SETREDRAW
, sent
|wparam
, 1 },
1787 static const struct message WmEnableWindowSeq_1
[] =
1789 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
1790 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1791 { HCBT_SETFOCUS
, hook
|optional
},
1792 { WM_KILLFOCUS
, sent
|optional
},
1793 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
1797 static const struct message WmEnableWindowSeq_2
[] =
1799 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1800 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
1804 static const struct message WmGetScrollRangeSeq
[] =
1806 { SBM_GETRANGE
, sent
},
1809 static const struct message WmGetScrollInfoSeq
[] =
1811 { SBM_GETSCROLLINFO
, sent
},
1814 static const struct message WmSetScrollRangeSeq
[] =
1816 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
1817 sends SBM_SETSCROLLINFO.
1819 { SBM_SETSCROLLINFO
, sent
},
1822 /* SetScrollRange for a window without a non-client area */
1823 static const struct message WmSetScrollRangeHSeq_empty
[] =
1825 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 0 },
1828 static const struct message WmSetScrollRangeVSeq_empty
[] =
1830 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 0 },
1833 static const struct message WmSetScrollRangeHVSeq
[] =
1835 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1836 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1837 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1838 { WM_ERASEBKGND
, sent
|optional
},
1839 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1840 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1841 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1844 /* SetScrollRange for a window with a non-client area */
1845 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
1847 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
1848 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1849 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
1850 { WM_NCPAINT
, sent
|optional
},
1851 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1852 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1853 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1854 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1855 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1856 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1857 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
1858 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
1859 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1860 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1861 { WM_ERASEBKGND
, sent
|optional
},
1862 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
1863 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
1864 { WM_SIZE
, sent
|defwinproc
|optional
},
1865 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1866 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
1867 { WM_GETTEXT
, sent
|optional
},
1868 { WM_GETTEXT
, sent
|optional
},
1869 { WM_GETTEXT
, sent
|optional
},
1870 { WM_GETTEXT
, sent
|optional
},
1873 /* test if we receive the right sequence of messages */
1874 /* after calling ShowWindow( SW_SHOWNA) */
1875 static const struct message WmSHOWNAChildInvisParInvis
[] = {
1876 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1879 static const struct message WmSHOWNAChildVisParInvis
[] = {
1880 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1883 static const struct message WmSHOWNAChildVisParVis
[] = {
1884 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1885 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1888 static const struct message WmSHOWNAChildInvisParVis
[] = {
1889 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1890 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1891 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1892 { WM_ERASEBKGND
, sent
|optional
},
1893 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
1896 static const struct message WmSHOWNATopVisible
[] = {
1897 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1898 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1899 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1900 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1901 { WM_ERASEBKGND
, sent
|optional
},
1902 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1905 static const struct message WmSHOWNATopInvisible
[] = {
1906 { WM_NOTIFYFORMAT
, sent
|optional
},
1907 { WM_QUERYUISTATE
, sent
|optional
},
1908 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1909 { WM_GETMINMAXINFO
, sent
|optional
},
1910 { WM_NCCALCSIZE
, sent
|optional
},
1911 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1912 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1913 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1914 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1915 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1916 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1917 { WM_ERASEBKGND
, sent
|optional
},
1918 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1919 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1920 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
1921 { WM_ERASEBKGND
, sent
|optional
},
1922 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1923 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1928 static const struct message WmTrackPopupMenu
[] = {
1929 { HCBT_CREATEWND
, hook
},
1930 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1931 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1932 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1933 { 0x0093, sent
|optional
},
1934 { 0x0094, sent
|optional
},
1935 { 0x0094, sent
|optional
},
1936 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1937 { WM_CAPTURECHANGED
, sent
},
1938 { HCBT_DESTROYWND
, hook
},
1939 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1940 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1941 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1945 static const struct message WmTrackPopupMenuEsc
[] = {
1949 static const struct message WmTrackPopupMenuCapture
[] = {
1950 { HCBT_CREATEWND
, hook
},
1951 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1952 { WM_CAPTURECHANGED
, sent
},
1953 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1954 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1955 { 0x0093, sent
|optional
},
1956 { 0x0094, sent
|optional
},
1957 { 0x0094, sent
|optional
},
1958 { WM_ENTERIDLE
, sent
|wparam
, 2 },
1959 { WM_CAPTURECHANGED
, sent
},
1960 { HCBT_DESTROYWND
, hook
},
1961 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1962 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1963 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1967 static const struct message WmTrackPopupMenuEmpty
[] = {
1968 { HCBT_CREATEWND
, hook
},
1969 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1970 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1971 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1972 { 0x0093, sent
|optional
},
1973 { 0x0094, sent
|optional
},
1974 { 0x0094, sent
|optional
},
1975 { WM_CAPTURECHANGED
, sent
},
1976 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1977 { HCBT_DESTROYWND
, hook
},
1978 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1982 static const struct message WmTrackPopupMenuAbort
[] = {
1983 { HCBT_CREATEWND
, hook
},
1984 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
1985 { WM_INITMENU
, sent
|lparam
, 0, 0 },
1986 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
1987 { 0x0093, sent
|optional
},
1988 { 0x0094, sent
|optional
},
1989 { 0x0094, sent
|optional
},
1990 { WM_CAPTURECHANGED
, sent
},
1991 { HCBT_DESTROYWND
, hook
},
1992 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
1993 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
1994 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
1998 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
1999 static int sequence_cnt
, sequence_size
;
2000 static struct recvd_message
* sequence
;
2001 static int log_all_parent_messages
;
2002 static CRITICAL_SECTION sequence_cs
;
2004 /* user32 functions */
2005 static HWND (WINAPI
*pGetAncestor
)(HWND
,UINT
);
2006 static BOOL (WINAPI
*pGetMenuInfo
)(HMENU
,LPCMENUINFO
);
2007 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
2008 static BOOL (WINAPI
*pSetMenuInfo
)(HMENU
,LPCMENUINFO
);
2009 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
2010 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
2011 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
2012 static BOOL (WINAPI
*pGetMonitorInfoA
)(HMONITOR
,LPMONITORINFO
);
2013 static HMONITOR (WINAPI
*pMonitorFromPoint
)(POINT
,DWORD
);
2014 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
2015 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
2016 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
2017 static UINT_PTR (WINAPI
*pSetCoalescableTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
, ULONG
);
2018 /* kernel32 functions */
2019 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
2021 static void init_procs(void)
2023 HMODULE user32
= GetModuleHandleA("user32.dll");
2024 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
2026 #define GET_PROC(dll, func) \
2027 p ## func = (void*)GetProcAddress(dll, #func); \
2029 trace("GetProcAddress(%s) failed\n", #func); \
2032 GET_PROC(user32
, GetAncestor
)
2033 GET_PROC(user32
, GetMenuInfo
)
2034 GET_PROC(user32
, NotifyWinEvent
)
2035 GET_PROC(user32
, SetMenuInfo
)
2036 GET_PROC(user32
, SetWinEventHook
)
2037 GET_PROC(user32
, TrackMouseEvent
)
2038 GET_PROC(user32
, UnhookWinEvent
)
2039 GET_PROC(user32
, GetMonitorInfoA
)
2040 GET_PROC(user32
, MonitorFromPoint
)
2041 GET_PROC(user32
, UpdateLayeredWindow
)
2042 GET_PROC(user32
, SetSystemTimer
)
2043 GET_PROC(user32
, KillSystemTimer
)
2044 GET_PROC(user32
, SetCoalescableTimer
)
2046 GET_PROC(kernel32
, GetCPInfoExA
)
2051 static const char *get_winpos_flags(UINT flags
)
2053 static char buffer
[300];
2056 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2057 DUMP( SWP_SHOWWINDOW
);
2058 DUMP( SWP_HIDEWINDOW
);
2059 DUMP( SWP_NOACTIVATE
);
2060 DUMP( SWP_FRAMECHANGED
);
2061 DUMP( SWP_NOCOPYBITS
);
2062 DUMP( SWP_NOOWNERZORDER
);
2063 DUMP( SWP_NOSENDCHANGING
);
2064 DUMP( SWP_DEFERERASE
);
2065 DUMP( SWP_ASYNCWINDOWPOS
);
2066 DUMP( SWP_NOZORDER
);
2067 DUMP( SWP_NOREDRAW
);
2070 DUMP( SWP_NOCLIENTSIZE
);
2071 DUMP( SWP_NOCLIENTMOVE
);
2072 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
2077 static BOOL
ignore_message( UINT message
)
2079 /* these are always ignored */
2080 return (message
>= 0xc000 ||
2081 message
== WM_GETICON
||
2082 message
== WM_GETOBJECT
||
2083 message
== WM_TIMECHANGE
||
2084 message
== WM_DISPLAYCHANGE
||
2085 message
== WM_DEVICECHANGE
||
2086 message
== WM_DWMNCRENDERINGCHANGED
);
2090 #define add_message(msg) add_message_(__LINE__,msg);
2091 static void add_message_(int line
, const struct recvd_message
*msg
)
2093 struct recvd_message
*seq
;
2095 EnterCriticalSection( &sequence_cs
);
2099 sequence
= HeapAlloc( GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
) );
2101 if (sequence_cnt
== sequence_size
)
2104 sequence
= HeapReAlloc( GetProcessHeap(), 0, sequence
, sequence_size
* sizeof(*sequence
) );
2108 seq
= &sequence
[sequence_cnt
++];
2109 seq
->hwnd
= msg
->hwnd
;
2110 seq
->message
= msg
->message
;
2111 seq
->flags
= msg
->flags
;
2112 seq
->wParam
= msg
->wParam
;
2113 seq
->lParam
= msg
->lParam
;
2115 seq
->descr
= msg
->descr
;
2117 LeaveCriticalSection( &sequence_cs
);
2121 if (msg
->flags
& hook
)
2123 static const char * const CBT_code_name
[10] =
2131 "HCBT_CLICKSKIPPED",
2136 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
2138 sprintf( seq
->output
, "%s: hook %d (%s) wp %08lx lp %08lx",
2139 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
2141 else if (msg
->flags
& winevent_hook
)
2143 sprintf( seq
->output
, "%s: winevent %p %08x %08lx %08lx",
2144 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2148 switch (msg
->message
)
2150 case WM_WINDOWPOSCHANGING
:
2151 case WM_WINDOWPOSCHANGED
:
2153 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
2155 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s",
2156 msg
->descr
, msg
->hwnd
,
2157 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
2158 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
2159 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
2160 get_winpos_flags(winpos
->flags
) );
2162 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2163 * in the high word for internal purposes
2165 seq
->wParam
= winpos
->flags
& 0xffff;
2166 /* We are not interested in the flags that don't match under XP and Win9x */
2167 seq
->wParam
&= ~SWP_NOZORDER
;
2173 DRAW_ITEM_STRUCT di
;
2174 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
2176 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2177 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
2178 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
2181 di
.u
.item
.type
= dis
->CtlType
;
2182 di
.u
.item
.ctl_id
= dis
->CtlID
;
2183 if (dis
->CtlType
== ODT_LISTBOX
||
2184 dis
->CtlType
== ODT_COMBOBOX
||
2185 dis
->CtlType
== ODT_MENU
)
2186 di
.u
.item
.item_id
= dis
->itemID
;
2187 di
.u
.item
.action
= dis
->itemAction
;
2188 di
.u
.item
.state
= dis
->itemState
;
2190 seq
->lParam
= di
.u
.lp
;
2194 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
2195 sprintf( seq
->output
, "%s: %p %04x wp %08lx lp %08lx",
2196 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2198 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
2199 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
2204 /* try to make sure pending X events have been processed before continuing */
2205 static void flush_events(void)
2209 int min_timeout
= 100;
2210 DWORD time
= GetTickCount() + diff
;
2214 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
2215 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2216 diff
= time
- GetTickCount();
2220 static void flush_sequence(void)
2222 EnterCriticalSection( &sequence_cs
);
2223 HeapFree(GetProcessHeap(), 0, sequence
);
2225 sequence_cnt
= sequence_size
= 0;
2226 LeaveCriticalSection( &sequence_cs
);
2229 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
2231 const struct recvd_message
*actual
= sequence
;
2232 unsigned int count
= 0;
2234 trace_(file
, line
)("Failed sequence %s:\n", context
);
2235 while (expected
->message
&& actual
->message
)
2237 if (actual
->output
[0])
2239 if (expected
->flags
& hook
)
2241 trace_(file
, line
)( " %u: expected: hook %04x - actual: %s\n",
2242 count
, expected
->message
, actual
->output
);
2244 else if (expected
->flags
& winevent_hook
)
2246 trace_(file
, line
)( " %u: expected: winevent %04x - actual: %s\n",
2247 count
, expected
->message
, actual
->output
);
2249 else if (expected
->flags
& kbd_hook
)
2251 trace_(file
, line
)( " %u: expected: kbd %04x - actual: %s\n",
2252 count
, expected
->message
, actual
->output
);
2256 trace_(file
, line
)( " %u: expected: msg %04x - actual: %s\n",
2257 count
, expected
->message
, actual
->output
);
2261 if (expected
->message
== actual
->message
)
2263 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) &&
2264 (expected
->flags
& optional
))
2266 /* don't match messages if their defwinproc status differs */
2275 /* silently drop winevent messages if there is no support for them */
2276 else if ((expected
->flags
& optional
) || ((expected
->flags
& winevent_hook
) && !hEvent_hook
))
2286 /* optional trailing messages */
2287 while (expected
->message
&& ((expected
->flags
& optional
) ||
2288 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2290 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2295 if (expected
->message
)
2297 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2301 while (actual
->message
&& actual
->output
[0])
2303 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
2309 #define ok_sequence( exp, contx, todo) \
2310 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2313 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2314 const char *file
, int line
)
2316 static const struct recvd_message end_of_sequence
;
2317 const struct message
*expected
= expected_list
;
2318 const struct recvd_message
*actual
;
2319 int failcount
= 0, dump
= 0;
2320 unsigned int count
= 0;
2322 add_message(&end_of_sequence
);
2326 while (expected
->message
&& actual
->message
)
2328 if (expected
->message
== actual
->message
&&
2329 !((expected
->flags
^ actual
->flags
) & (hook
|winevent_hook
|kbd_hook
)))
2331 if (expected
->flags
& wparam
)
2333 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2337 if (strcmp(winetest_platform
, "wine")) dump
++;
2338 ok_( file
, line
) (FALSE
,
2339 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2340 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2345 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2346 "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
2347 context
, count
, expected
->message
, expected
->wParam
, actual
->wParam
);
2348 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2352 if (expected
->flags
& lparam
)
2354 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2358 if (strcmp(winetest_platform
, "wine")) dump
++;
2359 ok_( file
, line
) (FALSE
,
2360 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2361 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2366 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2367 "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
2368 context
, count
, expected
->message
, expected
->lParam
, actual
->lParam
);
2369 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2372 if ((expected
->flags
& optional
) &&
2373 ((expected
->flags
^ actual
->flags
) & (defwinproc
|parent
)))
2375 /* don't match optional messages if their defwinproc or parent status differs */
2380 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2384 if (strcmp(winetest_platform
, "wine")) dump
++;
2385 ok_( file
, line
) (FALSE
,
2386 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2387 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2392 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2393 "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n",
2394 context
, count
, expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2395 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2398 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2399 "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n",
2400 context
, count
, expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2401 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2403 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2404 "%s: %u: the msg 0x%04x should have been %s\n",
2405 context
, count
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2406 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2408 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2409 "%s: %u: the msg 0x%04x was expected in %s\n",
2410 context
, count
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2411 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2413 ok_( file
, line
) ((expected
->flags
& hook
) == (actual
->flags
& hook
),
2414 "%s: %u: the msg 0x%04x should have been sent by a hook\n",
2415 context
, count
, expected
->message
);
2416 if ((expected
->flags
& hook
) != (actual
->flags
& hook
)) dump
++;
2418 ok_( file
, line
) ((expected
->flags
& winevent_hook
) == (actual
->flags
& winevent_hook
),
2419 "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n",
2420 context
, count
, expected
->message
);
2421 if ((expected
->flags
& winevent_hook
) != (actual
->flags
& winevent_hook
)) dump
++;
2423 ok_( file
, line
) ((expected
->flags
& kbd_hook
) == (actual
->flags
& kbd_hook
),
2424 "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n",
2425 context
, count
, expected
->message
);
2426 if ((expected
->flags
& kbd_hook
) != (actual
->flags
& kbd_hook
)) dump
++;
2431 /* silently drop hook messages if there is no support for them */
2432 else if ((expected
->flags
& optional
) ||
2433 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2434 ((expected
->flags
& winevent_hook
) && !hEvent_hook
) ||
2435 ((expected
->flags
& kbd_hook
) && !hKBD_hook
))
2441 if (strcmp(winetest_platform
, "wine")) dump
++;
2442 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2443 context
, count
, expected
->message
, actual
->message
);
2449 ok_( file
, line
) (FALSE
, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
2450 context
, count
, expected
->message
, actual
->message
);
2458 /* skip all optional trailing messages */
2459 while (expected
->message
&& ((expected
->flags
& optional
) ||
2460 ((expected
->flags
& hook
) && !hCBT_hook
) ||
2461 ((expected
->flags
& winevent_hook
) && !hEvent_hook
)))
2467 if (expected
->message
|| actual
->message
) {
2469 if (strcmp(winetest_platform
, "wine")) dump
++;
2470 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2471 context
, count
, expected
->message
, actual
->message
);
2477 if (expected
->message
|| actual
->message
)
2480 ok_( file
, line
) (FALSE
, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n",
2481 context
, count
, expected
->message
, actual
->message
);
2484 if( todo
&& !failcount
) /* succeeded yet marked todo */
2486 if (!strcmp(winetest_platform
, "wine")) dump
++;
2487 ok_( file
, line
)( TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
2491 if (dump
) dump_sequence(expected_list
, context
, file
, line
);
2495 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
2497 /******************************** MDI test **********************************/
2499 /* CreateWindow for MDI frame window, initially visible */
2500 static const struct message WmCreateMDIframeSeq
[] = {
2501 { HCBT_CREATEWND
, hook
},
2502 { WM_GETMINMAXINFO
, sent
},
2503 { WM_NCCREATE
, sent
},
2504 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2505 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
2506 { WM_CREATE
, sent
},
2507 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2508 { WM_NOTIFYFORMAT
, sent
|optional
},
2509 { WM_QUERYUISTATE
, sent
|optional
},
2510 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2511 { WM_GETMINMAXINFO
, sent
|optional
},
2512 { WM_NCCALCSIZE
, sent
|optional
},
2513 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2514 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2515 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2516 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2517 { HCBT_ACTIVATE
, hook
},
2518 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
2519 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2520 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2521 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2522 { WM_NCACTIVATE
, sent
},
2523 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2524 { WM_ACTIVATE
, sent
|wparam
, 1 },
2525 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2526 { HCBT_SETFOCUS
, hook
},
2527 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2528 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2529 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2530 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
2531 /* Win9x adds SWP_NOZORDER below */
2532 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2533 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
2534 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2535 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2539 /* DestroyWindow for MDI frame window, initially visible */
2540 static const struct message WmDestroyMDIframeSeq
[] = {
2541 { HCBT_DESTROYWND
, hook
},
2542 { 0x0090, sent
|optional
},
2543 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2544 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2545 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2546 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2547 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
2548 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
2549 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
2550 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
2551 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2552 { WM_DESTROY
, sent
},
2553 { WM_NCDESTROY
, sent
},
2556 /* CreateWindow for MDI client window, initially visible */
2557 static const struct message WmCreateMDIclientSeq
[] = {
2558 { HCBT_CREATEWND
, hook
},
2559 { WM_NCCREATE
, sent
},
2560 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2561 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2562 { WM_CREATE
, sent
},
2563 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2564 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2565 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2567 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
2568 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2569 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2570 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2571 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2574 /* ShowWindow(SW_SHOW) for MDI client window */
2575 static const struct message WmShowMDIclientSeq
[] = {
2576 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2577 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2578 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2579 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2582 /* ShowWindow(SW_HIDE) for MDI client window */
2583 static const struct message WmHideMDIclientSeq
[] = {
2584 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2585 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2586 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
2587 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
2588 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2591 /* DestroyWindow for MDI client window, initially visible */
2592 static const struct message WmDestroyMDIclientSeq
[] = {
2593 { HCBT_DESTROYWND
, hook
},
2594 { 0x0090, sent
|optional
},
2595 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
2596 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2597 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2598 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2599 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2600 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2601 { WM_DESTROY
, sent
},
2602 { WM_NCDESTROY
, sent
},
2605 /* CreateWindow for MDI child window, initially visible */
2606 static const struct message WmCreateMDIchildVisibleSeq
[] = {
2607 { HCBT_CREATEWND
, hook
},
2608 { WM_NCCREATE
, sent
},
2609 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2610 { WM_CREATE
, sent
},
2611 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2612 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2614 /* Win2k sends wparam set to
2615 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2616 * while Win9x doesn't bother to set child window id according to
2617 * CLIENTCREATESTRUCT.idFirstChild
2619 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2620 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2621 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2622 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2623 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2624 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2625 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2626 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2627 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2629 /* Win9x: message sequence terminates here. */
2631 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2632 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2633 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2634 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2635 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2636 { WM_SETFOCUS
, sent
}, /* in MDI client */
2637 { HCBT_SETFOCUS
, hook
},
2638 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2639 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2640 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2641 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2642 { WM_SETFOCUS
, sent
|defwinproc
},
2643 { WM_MDIACTIVATE
, sent
|defwinproc
},
2646 /* WM_CHILDACTIVATE sent to disabled window */
2647 static const struct message WmChildActivateDisabledWindowSeq
[] = {
2648 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2651 /* WM_CHILDACTIVATE sent to enabled window */
2652 static const struct message WmChildActivateWindowSeq
[] = {
2653 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2654 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 },
2655 { WM_MDIACTIVATE
, sent
|defwinproc
},
2656 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2657 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2658 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2659 { HCBT_SETFOCUS
, hook
},
2660 { WM_KILLFOCUS
, sent
|defwinproc
},
2661 { WM_SETFOCUS
, sent
},
2662 { HCBT_SETFOCUS
, hook
},
2663 { WM_KILLFOCUS
, sent
},
2664 { WM_SETFOCUS
, sent
|defwinproc
},
2665 { WM_MDIACTIVATE
, sent
|defwinproc
},
2668 /* CreateWindow for MDI child window with invisible parent */
2669 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
2670 { HCBT_CREATEWND
, hook
},
2671 { WM_GETMINMAXINFO
, sent
},
2672 { WM_NCCREATE
, sent
},
2673 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2674 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2675 { WM_CREATE
, sent
},
2676 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2677 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2679 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2680 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2681 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
2682 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2683 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2684 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2686 /* Win9x: message sequence terminates here. */
2688 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2689 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2690 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2691 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2692 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2693 { WM_SETFOCUS
, sent
}, /* in MDI client */
2694 { HCBT_SETFOCUS
, hook
},
2695 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2696 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2697 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2698 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2699 { WM_SETFOCUS
, sent
|defwinproc
},
2700 { WM_MDIACTIVATE
, sent
|defwinproc
},
2703 /* DestroyWindow for MDI child window, initially visible */
2704 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
2705 { HCBT_DESTROYWND
, hook
},
2706 /* Win2k sends wparam set to
2707 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2708 * while Win9x doesn't bother to set child window id according to
2709 * CLIENTCREATESTRUCT.idFirstChild
2711 { 0x0090, sent
|optional
},
2712 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2713 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
2714 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2715 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2716 { WM_ERASEBKGND
, sent
|parent
|optional
},
2717 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2719 /* { WM_DESTROY, sent }
2720 * Win9x: message sequence terminates here.
2723 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2724 { WM_KILLFOCUS
, sent
},
2725 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2726 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2727 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2728 { WM_SETFOCUS
, sent
}, /* in MDI client */
2730 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2731 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2732 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2733 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2734 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2735 { WM_SETFOCUS
, sent
}, /* in MDI client */
2737 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2739 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2740 { WM_KILLFOCUS
, sent
},
2741 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2742 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2743 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2744 { WM_SETFOCUS
, sent
}, /* in MDI client */
2746 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2747 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2748 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2749 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2750 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2751 { WM_SETFOCUS
, sent
}, /* in MDI client */
2753 { WM_DESTROY
, sent
},
2755 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
2756 { WM_KILLFOCUS
, sent
},
2757 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
2758 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2759 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2760 { WM_SETFOCUS
, sent
}, /* in MDI client */
2762 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
2763 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2764 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2765 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
2766 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2767 { WM_SETFOCUS
, sent
}, /* in MDI client */
2769 { WM_NCDESTROY
, sent
},
2772 /* CreateWindow for MDI child window, initially invisible */
2773 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
2774 { HCBT_CREATEWND
, hook
},
2775 { WM_NCCREATE
, sent
},
2776 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2777 { WM_CREATE
, sent
},
2778 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2779 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2781 /* Win2k sends wparam set to
2782 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2783 * while Win9x doesn't bother to set child window id according to
2784 * CLIENTCREATESTRUCT.idFirstChild
2786 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2789 /* DestroyWindow for MDI child window, initially invisible */
2790 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
2791 { HCBT_DESTROYWND
, hook
},
2792 /* Win2k sends wparam set to
2793 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
2794 * while Win9x doesn't bother to set child window id according to
2795 * CLIENTCREATESTRUCT.idFirstChild
2797 { 0x0090, sent
|optional
},
2798 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
2799 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
2800 { WM_DESTROY
, sent
},
2801 { WM_NCDESTROY
, sent
},
2802 /* FIXME: Wine destroys an icon/title window while Windows doesn't */
2803 { WM_PARENTNOTIFY
, sent
|wparam
|optional
, WM_DESTROY
}, /* MDI client */
2806 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
2807 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
2808 { HCBT_CREATEWND
, hook
},
2809 { WM_NCCREATE
, sent
},
2810 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2811 { WM_CREATE
, sent
},
2812 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2813 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2815 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2816 { WM_GETMINMAXINFO
, sent
},
2817 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2818 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2819 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2820 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2822 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2823 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2824 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2825 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2826 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2827 /* Win2k sends wparam set to
2828 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2829 * while Win9x doesn't bother to set child window id according to
2830 * CLIENTCREATESTRUCT.idFirstChild
2832 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2833 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2834 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2835 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2836 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2837 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2838 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2839 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2840 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
2842 /* Win9x: message sequence terminates here. */
2844 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
2845 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
2846 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2847 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
2848 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2849 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2850 { HCBT_SETFOCUS
, hook
|optional
},
2851 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
2852 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2853 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2854 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2855 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
2856 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
2858 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2859 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2860 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2861 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2864 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
2865 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
2866 /* restore the 1st MDI child */
2867 { WM_SETREDRAW
, sent
|wparam
, 0 },
2868 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
2869 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
2870 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2871 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2872 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2873 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
2875 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2876 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2877 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2878 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2879 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2880 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
2881 /* create the 2nd MDI child */
2882 { HCBT_CREATEWND
, hook
},
2883 { WM_NCCREATE
, sent
},
2884 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2885 { WM_CREATE
, sent
},
2886 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2887 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2889 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2890 { WM_GETMINMAXINFO
, sent
},
2891 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2892 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2893 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2894 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2895 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2897 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2898 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2899 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2900 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2901 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2902 /* Win2k sends wparam set to
2903 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2904 * while Win9x doesn't bother to set child window id according to
2905 * CLIENTCREATESTRUCT.idFirstChild
2907 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2908 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2909 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2910 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2911 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2912 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2913 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2914 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2916 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
2917 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
2919 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2921 /* Win9x: message sequence terminates here. */
2923 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2924 { HCBT_SETFOCUS
, hook
},
2925 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
2926 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
2927 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2928 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2929 { WM_SETFOCUS
, sent
}, /* in MDI client */
2930 { HCBT_SETFOCUS
, hook
},
2931 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2932 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2933 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2934 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2935 { WM_SETFOCUS
, sent
|defwinproc
},
2937 { WM_MDIACTIVATE
, sent
|defwinproc
},
2939 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2940 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2941 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2942 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2945 /* WM_MDICREATE MDI child window, initially visible and maximized */
2946 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
2947 { WM_MDICREATE
, sent
},
2948 { HCBT_CREATEWND
, hook
},
2949 { WM_NCCREATE
, sent
},
2950 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2951 { WM_CREATE
, sent
},
2952 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2953 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2955 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
2956 { WM_GETMINMAXINFO
, sent
},
2957 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
2958 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2959 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
2960 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
2963 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2964 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2965 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2966 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
2967 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
2969 /* Win2k sends wparam set to
2970 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
2971 * while Win9x doesn't bother to set child window id according to
2972 * CLIENTCREATESTRUCT.idFirstChild
2974 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
2975 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2976 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2978 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2980 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2981 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
2982 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2984 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
2985 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2987 /* Win9x: message sequence terminates here. */
2989 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
2990 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2991 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
2992 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
2993 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
2994 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
2995 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
2996 { HCBT_SETFOCUS
, hook
|optional
},
2997 { WM_KILLFOCUS
, sent
}, /* in MDI client */
2998 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
2999 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3000 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3001 { WM_SETFOCUS
, sent
|defwinproc
},
3003 { WM_MDIACTIVATE
, sent
|defwinproc
},
3006 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3007 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3008 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3009 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3012 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3013 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3014 { 0x0093, sent
|defwinproc
|optional
},
3015 { 0x0093, sent
|defwinproc
|optional
},
3016 { 0x0093, sent
|defwinproc
|optional
},
3017 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3018 { WM_MOVE
, sent
|defwinproc
},
3019 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3022 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3023 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3024 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3025 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3028 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3029 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3030 { 0x0093, sent
|optional
},
3031 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3032 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3034 { 0x0093, sent
|optional
},
3035 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3036 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3037 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
3038 { 0x0093, sent
|defwinproc
|optional
},
3039 { 0x0093, sent
|defwinproc
|optional
},
3040 { 0x0093, sent
|defwinproc
|optional
},
3041 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3042 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3046 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3047 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
3048 { HCBT_CREATEWND
, hook
},
3049 { WM_GETMINMAXINFO
, sent
},
3050 { WM_NCCREATE
, sent
},
3051 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3052 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, 0, 0 },
3053 { WM_CREATE
, sent
},
3054 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3055 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3056 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3057 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
3058 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3060 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3061 { WM_GETMINMAXINFO
, sent
},
3062 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3063 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3064 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3065 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3066 { WM_MOVE
, sent
|defwinproc
},
3067 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3069 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3070 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3071 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3072 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3073 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
3074 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3075 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3076 /* Win2k sends wparam set to
3077 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3078 * while Win9x doesn't bother to set child window id according to
3079 * CLIENTCREATESTRUCT.idFirstChild
3081 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3084 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3085 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
3086 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
3087 { HCBT_SYSCOMMAND
, hook
},
3088 { WM_CLOSE
, sent
|defwinproc
},
3089 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3091 /* bring the 1st MDI child to top */
3092 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
3093 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
3095 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3097 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
3098 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3099 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3101 /* maximize the 1st MDI child */
3102 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3103 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3104 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3105 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3106 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3107 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3108 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3110 /* restore the 2nd MDI child */
3111 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
3112 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
3113 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3114 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3116 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3118 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3119 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3121 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3123 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
3125 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3126 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3127 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3128 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3129 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3131 /* bring the 1st MDI child to top */
3132 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3133 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3134 { HCBT_SETFOCUS
, hook
},
3135 { WM_KILLFOCUS
, sent
|defwinproc
},
3136 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
3137 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3138 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3139 { WM_SETFOCUS
, sent
}, /* in MDI client */
3140 { HCBT_SETFOCUS
, hook
},
3141 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3142 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3143 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3144 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3145 { WM_SETFOCUS
, sent
|defwinproc
},
3146 { WM_MDIACTIVATE
, sent
|defwinproc
},
3147 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3149 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3150 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3151 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3152 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3153 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3154 { WM_MDIREFRESHMENU
, sent
},
3156 { HCBT_DESTROYWND
, hook
},
3157 /* Win2k sends wparam set to
3158 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3159 * while Win9x doesn't bother to set child window id according to
3160 * CLIENTCREATESTRUCT.idFirstChild
3162 { 0x0090, sent
|defwinproc
|optional
},
3163 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3164 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
3165 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3166 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3167 { WM_ERASEBKGND
, sent
|parent
|optional
},
3168 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3170 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3171 { WM_DESTROY
, sent
|defwinproc
},
3172 { WM_NCDESTROY
, sent
|defwinproc
},
3175 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3176 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
3177 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3178 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3179 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3180 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3181 { WM_ERASEBKGND
, sent
|parent
|optional
},
3182 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3184 { HCBT_SETFOCUS
, hook
},
3185 { WM_KILLFOCUS
, sent
},
3186 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3187 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3188 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3189 { WM_SETFOCUS
, sent
}, /* in MDI client */
3190 { HCBT_SETFOCUS
, hook
},
3191 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3192 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3193 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3194 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3195 { WM_SETFOCUS
, sent
},
3198 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3199 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3200 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3201 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3204 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3205 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3206 { 0x0093, sent
|defwinproc
|optional
},
3207 { 0x0093, sent
|defwinproc
|optional
},
3208 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3209 { WM_MOVE
, sent
|defwinproc
},
3210 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3213 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3214 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3215 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3216 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3219 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3220 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3221 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3222 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3225 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3226 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3227 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3228 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3231 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3232 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3233 { 0x0093, sent
|defwinproc
|optional
},
3234 { 0x0093, sent
|defwinproc
|optional
},
3235 { 0x0093, sent
|defwinproc
|optional
},
3236 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3237 { WM_MOVE
, sent
|defwinproc
},
3238 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3241 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3242 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3243 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3244 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3247 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3248 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3249 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3250 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3251 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3252 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3254 { 0x0093, sent
|defwinproc
|optional
},
3255 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
3256 { 0x0093, sent
|defwinproc
|optional
},
3257 { 0x0093, sent
|defwinproc
|optional
},
3258 { 0x0093, sent
|defwinproc
|optional
},
3259 { 0x0093, sent
|optional
},
3261 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3262 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3263 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3264 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3265 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3268 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3269 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3270 { 0x0093, sent
|defwinproc
|optional
},
3271 { 0x0093, sent
|defwinproc
|optional
},
3272 { 0x0093, sent
|defwinproc
|optional
},
3273 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3274 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3275 { 0x0093, sent
|optional
},
3277 { WM_NCACTIVATE
, sent
|wparam
, 0 },
3278 { WM_MDIACTIVATE
, sent
},
3280 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3281 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3282 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3284 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3286 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3287 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3288 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3291 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3292 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3293 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3294 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3297 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3298 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3299 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3300 { WM_MOVE
, sent
|defwinproc
},
3301 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3304 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3305 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3306 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3307 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3308 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3309 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3310 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI client */
3311 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3312 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* XP sends a duplicate */
3314 { HCBT_SETFOCUS
, hook
},
3315 { WM_KILLFOCUS
, sent
},
3316 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3317 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3318 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3319 { WM_SETFOCUS
, sent
}, /* in MDI client */
3321 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3323 { HCBT_DESTROYWND
, hook
},
3324 /* Win2k sends wparam set to
3325 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3326 * while Win9x doesn't bother to set child window id according to
3327 * CLIENTCREATESTRUCT.idFirstChild
3329 { 0x0090, sent
|optional
},
3330 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3332 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3333 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3334 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3335 { WM_ERASEBKGND
, sent
|parent
|optional
},
3336 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3338 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 },
3339 { WM_DESTROY
, sent
},
3340 { WM_NCDESTROY
, sent
},
3343 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3344 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3345 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3346 { WM_GETMINMAXINFO
, sent
},
3347 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3348 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3349 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3350 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3352 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3353 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3354 { HCBT_SETFOCUS
, hook
|optional
},
3355 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3356 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3357 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3358 { HCBT_SETFOCUS
, hook
|optional
},
3359 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3360 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3361 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3362 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3363 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3364 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3365 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3366 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3368 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3369 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3370 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3371 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3372 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3375 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3376 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3377 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3378 { WM_GETMINMAXINFO
, sent
},
3379 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
3380 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3381 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3382 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3383 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3385 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3386 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3387 { HCBT_SETFOCUS
, hook
|optional
},
3388 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3389 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3390 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3391 { HCBT_SETFOCUS
, hook
|optional
},
3392 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3393 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3394 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3395 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3396 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3397 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3398 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3399 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3402 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3403 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3404 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3405 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3406 { WM_GETMINMAXINFO
, sent
},
3407 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3408 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3409 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3410 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3411 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3412 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3413 { WM_MOVE
, sent
|defwinproc
},
3414 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3416 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3417 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3418 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3419 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3420 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3421 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3423 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3424 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3425 { 0x0093, sent
|defwinproc
|optional
},
3426 { 0x0094, sent
|defwinproc
|optional
},
3427 { 0x0094, sent
|defwinproc
|optional
},
3428 { 0x0094, sent
|defwinproc
|optional
},
3429 { 0x0094, sent
|defwinproc
|optional
},
3430 { 0x0093, sent
|defwinproc
|optional
},
3431 { 0x0093, sent
|defwinproc
|optional
},
3432 { 0x0091, sent
|defwinproc
|optional
},
3433 { 0x0092, sent
|defwinproc
|optional
},
3434 { 0x0092, sent
|defwinproc
|optional
},
3435 { 0x0092, sent
|defwinproc
|optional
},
3436 { 0x0092, sent
|defwinproc
|optional
},
3437 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3438 { WM_MOVE
, sent
|defwinproc
},
3439 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3440 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3442 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3443 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3444 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3445 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3447 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3448 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3449 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3450 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3451 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3452 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3453 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3454 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3455 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3456 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3458 { 0x0093, sent
|optional
},
3459 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3460 { 0x0093, sent
|defwinproc
|optional
},
3461 { 0x0093, sent
|defwinproc
|optional
},
3462 { 0x0093, sent
|defwinproc
|optional
},
3463 { 0x0091, sent
|defwinproc
|optional
},
3464 { 0x0092, sent
|defwinproc
|optional
},
3465 { 0x0092, sent
|defwinproc
|optional
},
3466 { 0x0092, sent
|defwinproc
|optional
},
3467 { 0x0092, sent
|defwinproc
|optional
},
3468 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3469 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3470 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3473 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3474 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3475 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3476 { WM_GETMINMAXINFO
, sent
},
3477 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3478 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3479 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3480 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3481 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3483 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3484 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3485 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3486 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3487 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3490 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3491 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3492 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3493 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3494 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3495 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3496 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3497 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3499 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3500 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3501 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3502 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3503 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3506 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3507 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3508 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3509 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3510 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3511 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3512 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3513 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3514 { WM_MOVE
, sent
|defwinproc
},
3515 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3516 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3517 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3518 { HCBT_SETFOCUS
, hook
},
3519 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3520 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3521 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3522 { WM_SETFOCUS
, sent
},
3525 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
3526 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
3527 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
3528 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3529 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3530 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3531 { WM_MOVE
, sent
|defwinproc
},
3532 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
3533 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
3534 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3535 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3536 /* FIXME: Wine creates an icon/title window while Windows doesn't */
3537 { WM_PARENTNOTIFY
, sent
|parent
|wparam
|optional
, WM_CREATE
}, /* MDI client */
3540 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
3541 static const struct message WmRestoreMDIchildInvisibleSeq
[] = {
3542 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3543 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3544 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3545 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3546 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3547 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3548 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3550 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3551 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3552 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3553 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3554 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3558 static HWND mdi_client
;
3559 static WNDPROC old_mdi_client_proc
;
3561 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3563 struct recvd_message msg
;
3565 /* do not log painting messages */
3566 if (message
!= WM_PAINT
&&
3567 message
!= WM_NCPAINT
&&
3568 message
!= WM_SYNCPAINT
&&
3569 message
!= WM_ERASEBKGND
&&
3570 message
!= WM_NCHITTEST
&&
3571 message
!= WM_GETTEXT
&&
3572 message
!= WM_MDIGETACTIVE
&&
3573 !ignore_message( message
))
3576 msg
.message
= message
;
3577 msg
.flags
= sent
|wparam
|lparam
;
3578 msg
.wParam
= wParam
;
3579 msg
.lParam
= lParam
;
3580 msg
.descr
= "mdi client";
3584 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
3587 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3589 static LONG defwndproc_counter
= 0;
3591 struct recvd_message msg
;
3593 /* do not log painting messages */
3594 if (message
!= WM_PAINT
&&
3595 message
!= WM_NCPAINT
&&
3596 message
!= WM_SYNCPAINT
&&
3597 message
!= WM_ERASEBKGND
&&
3598 message
!= WM_NCHITTEST
&&
3599 message
!= WM_GETTEXT
&&
3600 !ignore_message( message
))
3604 case WM_MDIACTIVATE
:
3606 HWND active
, client
= GetParent(hwnd
);
3608 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
3610 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
3611 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
3613 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
3619 msg
.message
= message
;
3620 msg
.flags
= sent
|wparam
|lparam
;
3621 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3622 msg
.wParam
= wParam
;
3623 msg
.lParam
= lParam
;
3624 msg
.descr
= "mdi child";
3628 defwndproc_counter
++;
3629 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
3630 defwndproc_counter
--;
3635 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3637 static LONG defwndproc_counter
= 0;
3639 struct recvd_message msg
;
3641 /* do not log painting messages */
3642 if (message
!= WM_PAINT
&&
3643 message
!= WM_NCPAINT
&&
3644 message
!= WM_SYNCPAINT
&&
3645 message
!= WM_ERASEBKGND
&&
3646 message
!= WM_NCHITTEST
&&
3647 message
!= WM_GETTEXT
&&
3648 !ignore_message( message
))
3651 msg
.message
= message
;
3652 msg
.flags
= sent
|wparam
|lparam
;
3653 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
3654 msg
.wParam
= wParam
;
3655 msg
.lParam
= lParam
;
3656 msg
.descr
= "mdi frame";
3660 defwndproc_counter
++;
3661 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
3662 defwndproc_counter
--;
3667 static BOOL
mdi_RegisterWindowClasses(void)
3672 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
3675 cls
.hInstance
= GetModuleHandleA(0);
3677 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
3678 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
3679 cls
.lpszMenuName
= NULL
;
3680 cls
.lpszClassName
= "MDI_frame_class";
3681 if (!RegisterClassA(&cls
)) return FALSE
;
3683 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
3684 cls
.lpszClassName
= "MDI_child_class";
3685 if (!RegisterClassA(&cls
)) return FALSE
;
3687 if (!GetClassInfoA(0, "MDIClient", &cls
)) assert(0);
3688 old_mdi_client_proc
= cls
.lpfnWndProc
;
3689 cls
.hInstance
= GetModuleHandleA(0);
3690 cls
.lpfnWndProc
= mdi_client_hook_proc
;
3691 cls
.lpszClassName
= "MDI_client_class";
3692 if (!RegisterClassA(&cls
)) assert(0);
3697 static void test_mdi_messages(void)
3699 MDICREATESTRUCTA mdi_cs
;
3700 CLIENTCREATESTRUCT client_cs
;
3701 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
3704 HMENU hMenu
= CreateMenu();
3707 if (!mdi_RegisterWindowClasses()) assert(0);
3711 trace("creating MDI frame window\n");
3712 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
3713 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
3714 WS_MAXIMIZEBOX
| WS_VISIBLE
,
3715 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
3716 GetDesktopWindow(), hMenu
,
3717 GetModuleHandleA(0), NULL
);
3719 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
3721 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3722 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
3724 trace("creating MDI client window\n");
3725 GetClientRect(mdi_frame
, &rc
);
3726 client_cs
.hWindowMenu
= 0;
3727 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
3728 mdi_client
= CreateWindowExA(0, "MDI_client_class",
3730 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
3731 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
3732 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
3734 SetWindowLongA(mdi_client
, 0, 0xdeadbeef);
3736 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
3737 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3738 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
3740 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3741 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3742 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3747 trace("creating invisible MDI child window\n");
3748 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3750 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3751 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3755 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
3756 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
3758 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3759 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3761 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3762 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3764 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3765 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3766 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3768 ShowWindow(mdi_child
, SW_HIDE
);
3769 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
3772 ShowWindow(mdi_child
, SW_SHOW
);
3773 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
3775 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3776 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3778 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3779 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3781 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3782 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
3783 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3785 DestroyWindow(mdi_child
);
3788 trace("creating visible MDI child window\n");
3789 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3790 WS_CHILD
| WS_VISIBLE
,
3791 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3792 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3794 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
3796 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3797 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
3799 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3800 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
3802 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3803 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3804 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3807 DestroyWindow(mdi_child
);
3808 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
3810 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3811 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3813 /* Win2k: MDI client still returns a just destroyed child as active
3814 * Win9x: MDI client returns 0
3816 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3817 ok(active_child
== mdi_child
|| /* win2k */
3818 !active_child
, /* win9x */
3819 "wrong active MDI child %p\n", active_child
);
3820 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3824 trace("creating invisible MDI child window\n");
3825 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3827 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3828 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3830 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
3832 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
3833 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
3835 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3836 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3838 /* Win2k: MDI client still returns a just destroyed child as active
3839 * Win9x: MDI client returns mdi_child2
3841 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3842 ok(active_child
== mdi_child
|| /* win2k */
3843 active_child
== mdi_child2
, /* win9x */
3844 "wrong active MDI child %p\n", active_child
);
3845 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3848 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3849 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
3851 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3852 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3854 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3855 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3856 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
3859 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3860 ok(GetFocus() == mdi_child2
|| /* win2k */
3861 GetFocus() == 0, /* win9x */
3862 "wrong focus window %p\n", GetFocus());
3867 ShowWindow(mdi_child2
, SW_HIDE
);
3868 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3870 ShowWindow(mdi_child2
, SW_RESTORE
);
3871 ok_sequence(WmRestoreMDIchildInvisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
3874 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
3875 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
3877 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3878 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3879 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3885 ShowWindow(mdi_child2
, SW_HIDE
);
3886 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3888 ShowWindow(mdi_child2
, SW_SHOW
);
3889 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
3891 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3892 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3894 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
3895 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
3897 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3898 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3900 ShowWindow(mdi_child2
, SW_RESTORE
);
3901 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
3903 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3904 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3906 ShowWindow(mdi_child2
, SW_MINIMIZE
);
3907 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", TRUE
);
3909 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3910 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3912 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3913 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3914 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3917 ShowWindow(mdi_child2
, SW_RESTORE
);
3918 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
3920 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3921 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
3923 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3924 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3925 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3931 ShowWindow(mdi_child2
, SW_HIDE
);
3932 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
3934 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3935 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3937 DestroyWindow(mdi_child2
);
3938 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
3940 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3941 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3943 trace("Testing WM_CHILDACTIVATE\n");
3945 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3946 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_DISABLED
,
3947 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3948 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3950 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3951 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
,
3952 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3953 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3955 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3956 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3957 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3960 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
3961 ok_sequence(WmChildActivateDisabledWindowSeq
, "WM_CHILDACTIVATE sent to disabled window", FALSE
);
3963 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3964 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3965 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3968 EnableWindow(mdi_child
, TRUE
);
3970 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3971 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
3972 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3975 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
3976 ok_sequence(WmChildActivateWindowSeq
, "WM_CHILDACTIVATE sent to enabled window", FALSE
);
3978 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
3979 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
3980 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
3983 DestroyWindow(mdi_child
);
3984 DestroyWindow(mdi_child2
);
3987 /* test for maximized MDI children */
3988 trace("creating maximized visible MDI child window 1\n");
3989 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
3990 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
3991 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
3992 mdi_client
, 0, GetModuleHandleA(0), NULL
);
3994 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
3995 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
3997 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
3998 ok(GetFocus() == mdi_child
|| /* win2k */
3999 GetFocus() == 0, /* win9x */
4000 "wrong focus window %p\n", GetFocus());
4002 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4003 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4004 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4007 trace("creating maximized visible MDI child window 2\n");
4008 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4009 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4010 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4011 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4013 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4014 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4015 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4017 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4018 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4020 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4021 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4022 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4025 trace("destroying maximized visible MDI child window 2\n");
4026 DestroyWindow(mdi_child2
);
4027 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4029 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4031 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4032 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4034 /* Win2k: MDI client still returns a just destroyed child as active
4035 * Win9x: MDI client returns 0
4037 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4038 ok(active_child
== mdi_child2
|| /* win2k */
4039 !active_child
, /* win9x */
4040 "wrong active MDI child %p\n", active_child
);
4043 ShowWindow(mdi_child
, SW_MAXIMIZE
);
4044 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4047 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4048 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4050 trace("re-creating maximized visible MDI child window 2\n");
4051 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4052 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4053 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4054 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4056 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4057 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4058 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4060 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4061 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4063 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4064 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4065 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4068 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
4069 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
4070 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
4072 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4073 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4074 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4076 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4077 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4078 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4081 DestroyWindow(mdi_child
);
4082 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4084 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4085 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4087 /* Win2k: MDI client still returns a just destroyed child as active
4088 * Win9x: MDI client returns 0
4090 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4091 ok(active_child
== mdi_child
|| /* win2k */
4092 !active_child
, /* win9x */
4093 "wrong active MDI child %p\n", active_child
);
4096 trace("creating maximized invisible MDI child window\n");
4097 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4098 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
4099 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4100 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4102 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
4103 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4104 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
4105 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
4107 /* Win2k: MDI client still returns a just destroyed child as active
4108 * Win9x: MDI client returns 0
4110 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4111 ok(active_child
== mdi_child
|| /* win2k */
4112 !active_child
|| active_child
== mdi_child2
, /* win9x */
4113 "wrong active MDI child %p\n", active_child
);
4116 trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4117 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4118 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
4119 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4120 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4121 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4123 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4124 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4125 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4128 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4131 /* end of test for maximized MDI children */
4134 trace("creating maximized visible MDI child window 1(Switch test)\n");
4135 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4136 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4137 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4138 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4140 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
4141 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
4143 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4144 ok(GetFocus() == mdi_child
|| /* win2k */
4145 GetFocus() == 0, /* win9x */
4146 "wrong focus window %p(Switch test)\n", GetFocus());
4148 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4149 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4150 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4153 trace("creating maximized visible MDI child window 2(Switch test)\n");
4154 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4155 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4156 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4157 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4159 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
4161 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
4162 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
4164 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4165 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
4167 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4168 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
4169 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4172 trace("Switch child window.\n");
4173 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
4174 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
4175 trace("end of test for switch maximized MDI children\n");
4178 /* Prepare for switching test of not maximized MDI children */
4179 ShowWindow( mdi_child
, SW_NORMAL
);
4180 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
4181 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
4182 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
4183 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4186 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
4187 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
4188 trace("end of test for switch not maximized MDI children\n");
4191 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4194 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4199 /* end of tests for switch maximized/not maximized MDI children */
4201 mdi_cs
.szClass
= "MDI_child_Class";
4202 mdi_cs
.szTitle
= "MDI child";
4203 mdi_cs
.hOwner
= GetModuleHandleA(0);
4206 mdi_cs
.cx
= CW_USEDEFAULT
;
4207 mdi_cs
.cy
= CW_USEDEFAULT
;
4208 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
4210 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
4211 ok(mdi_child
!= 0, "MDI child creation failed\n");
4212 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
4214 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
4216 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4217 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4219 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
4220 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4221 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4223 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4224 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4225 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4228 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4229 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
4231 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
4232 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4233 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4238 val
= GetWindowLongA(mdi_client
, 0);
4239 ok(val
== 0xdeadbeef || broken(val
== 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val
);
4240 DestroyWindow(mdi_client
);
4241 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4243 /* test maximization of MDI child with invisible parent */
4244 client_cs
.hWindowMenu
= 0;
4245 mdi_client
= CreateWindowA("MDI_client_class",
4247 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
4249 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4250 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
4252 ShowWindow(mdi_client
, SW_HIDE
);
4253 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
4255 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4256 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
4258 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4259 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
4261 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
4262 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
4263 zoomed
= IsZoomed(mdi_child
);
4264 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4266 ShowWindow(mdi_client
, SW_SHOW
);
4267 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
4269 DestroyWindow(mdi_child
);
4270 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
4272 /* end of test for maximization of MDI child with invisible parent */
4274 DestroyWindow(mdi_client
);
4275 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4277 DestroyWindow(mdi_frame
);
4278 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
4280 /************************* End of MDI test **********************************/
4282 static void test_WM_SETREDRAW(HWND hwnd
)
4284 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4289 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
4290 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
4292 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
4293 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
4296 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
4297 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
4299 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4300 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
4302 /* restore original WS_VISIBLE state */
4303 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4309 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4311 struct recvd_message msg
;
4313 if (ignore_message( message
)) return 0;
4319 case WM_NCMOUSEMOVE
:
4320 case WM_NCMOUSELEAVE
:
4328 msg
.message
= message
;
4329 msg
.flags
= sent
|wparam
|lparam
;
4330 msg
.wParam
= wParam
;
4331 msg
.lParam
= lParam
;
4332 msg
.descr
= "dialog";
4335 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
4336 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
4340 static INT_PTR CALLBACK
TestModalDlgProc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4342 struct recvd_message msg
;
4344 if (ignore_message( message
)) return 0;
4350 case WM_NCMOUSEMOVE
:
4351 case WM_NCMOUSELEAVE
:
4359 msg
.message
= message
;
4360 msg
.flags
= sent
|wparam
|lparam
;
4361 msg
.wParam
= wParam
;
4362 msg
.lParam
= lParam
;
4363 msg
.descr
= "dialog";
4366 if (message
== WM_INITDIALOG
) EndDialog( hwnd
, 0 );
4370 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4372 DWORD style
, exstyle
;
4376 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4377 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4378 /* do not be confused by WS_DLGFRAME set */
4379 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4381 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4382 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4384 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4385 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4386 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4387 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
4389 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
4391 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4392 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4393 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4395 /* a subsequent call should do nothing */
4396 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4397 ok( ret
, "SetScrollRange(%d) error %d\n", ctl
, GetLastError());
4398 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4402 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
4403 ok( ret
, "GetScrollRange(%d) error %d\n", ctl
, GetLastError());
4404 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4405 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
4406 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
4409 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4411 DWORD style
, exstyle
;
4415 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4416 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4417 /* do not be confused by WS_DLGFRAME set */
4418 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4420 if (clear
) ok(style
& clear
, "style %08x should be set\n", clear
);
4421 if (set
) ok(!(style
& set
), "style %08x should not be set\n", set
);
4423 si
.cbSize
= sizeof(si
);
4424 si
.fMask
= SIF_RANGE
;
4427 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4428 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4429 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4431 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4433 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4434 if (set
) ok(style
& set
, "style %08x should be set\n", set
);
4435 if (clear
) ok(!(style
& clear
), "style %08x should not be set\n", clear
);
4437 /* a subsequent call should do nothing */
4438 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4439 if (style
& WS_HSCROLL
)
4440 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4441 else if (style
& WS_VSCROLL
)
4442 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4444 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4446 si
.fMask
= SIF_PAGE
;
4448 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4449 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4453 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4454 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4456 si
.fMask
= SIF_RANGE
;
4457 si
.nMin
= 0xdeadbeef;
4458 si
.nMax
= 0xdeadbeef;
4459 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4460 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4461 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4462 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4463 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4466 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4467 static void test_scroll_messages(HWND hwnd
)
4478 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4479 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4480 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4481 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4482 /* values of min and max are undefined */
4485 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4486 ok( ret
, "SetScrollRange error %d\n", GetLastError());
4487 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4488 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4493 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4494 ok( ret
, "GetScrollRange error %d\n", GetLastError());
4495 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4496 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4497 /* values of min and max are undefined */
4500 si
.cbSize
= sizeof(si
);
4501 si
.fMask
= SIF_RANGE
;
4504 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4505 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4506 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4509 si
.fMask
= SIF_PAGE
;
4511 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4512 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4513 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4518 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4519 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4520 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4523 si
.fMask
= SIF_RANGE
;
4524 si
.nMin
= 0xdeadbeef;
4525 si
.nMax
= 0xdeadbeef;
4526 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
4527 ok( ret
, "GetScrollInfo error %d\n", GetLastError());
4528 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
4529 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4530 /* values of min and max are undefined */
4533 /* set WS_HSCROLL */
4534 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4535 /* clear WS_HSCROLL */
4536 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4538 /* set WS_HSCROLL */
4539 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
4540 /* clear WS_HSCROLL */
4541 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
4543 /* set WS_VSCROLL */
4544 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4545 /* clear WS_VSCROLL */
4546 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4548 /* set WS_VSCROLL */
4549 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
4550 /* clear WS_VSCROLL */
4551 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
4554 static void test_showwindow(void)
4559 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
4560 100, 100, 200, 200, 0, 0, 0, NULL
);
4561 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4562 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
4563 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
4564 ok (hchild
!= 0, "Failed to create child\n");
4567 /* ShowWindow( SW_SHOWNA) for invisible top level window */
4568 trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
4569 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4570 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
4572 /* ShowWindow( SW_SHOWNA) for now visible top level window */
4573 trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
4574 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4575 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
4576 /* back to invisible */
4577 ShowWindow(hchild
, SW_HIDE
);
4578 ShowWindow(hwnd
, SW_HIDE
);
4580 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
4581 trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
4582 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4583 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
4584 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
4585 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
4587 trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
4588 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4589 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
4590 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
4591 ShowWindow( hwnd
, SW_SHOW
);
4593 trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
4594 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
4595 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
4597 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
4598 ShowWindow( hchild
, SW_HIDE
);
4600 trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
4601 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
4602 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
4605 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
4606 DestroyWindow(hchild
);
4607 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
4609 DestroyWindow(hwnd
);
4614 * 1. Create invisible maximized popup window.
4615 * 2. Move and resize it.
4616 * 3. Show it maximized.
4618 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4619 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4620 100, 100, 200, 200, 0, 0, 0, NULL
);
4621 ok (hwnd
!= 0, "Failed to create popup window\n");
4622 ok(IsZoomed(hwnd
), "window should be maximized\n");
4623 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4625 GetWindowRect(hwnd
, &rc
);
4626 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4627 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4628 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc
));
4629 /* Reset window's size & position */
4630 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4631 ok(IsZoomed(hwnd
), "window should be maximized\n");
4634 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4635 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4636 ok(IsZoomed(hwnd
), "window should be maximized\n");
4637 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
4639 GetWindowRect(hwnd
, &rc
);
4640 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
4641 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
4642 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc
));
4643 DestroyWindow(hwnd
);
4646 /* Test again, this time the NC_PAINT message */
4647 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4648 100, 100, 200, 200, 0, 0, 0, NULL
);
4649 ok (hwnd
!= 0, "Failed to create popup window\n");
4650 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
4652 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4653 ok_sequence(WmShowMaxPopupResizedSeq_todo
,
4654 "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup TODO", FALSE
);
4655 DestroyWindow(hwnd
);
4659 * 1. Create invisible maximized popup window.
4660 * 2. Show it maximized.
4662 trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
4663 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
4664 100, 100, 200, 200, 0, 0, 0, NULL
);
4665 ok (hwnd
!= 0, "Failed to create popup window\n");
4666 ok(IsZoomed(hwnd
), "window should be maximized\n");
4667 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4669 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
4670 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4671 ok(IsZoomed(hwnd
), "window should be maximized\n");
4672 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
4673 DestroyWindow(hwnd
);
4677 * 1. Create visible maximized popup window.
4679 trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
4680 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
4681 100, 100, 200, 200, 0, 0, 0, NULL
);
4682 ok (hwnd
!= 0, "Failed to create popup window\n");
4683 ok(IsZoomed(hwnd
), "window should be maximized\n");
4684 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
4685 DestroyWindow(hwnd
);
4689 * 1. Create visible popup window.
4692 trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
4693 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
4694 100, 100, 200, 200, 0, 0, 0, NULL
);
4695 ok (hwnd
!= 0, "Failed to create popup window\n");
4696 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
4697 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
4699 trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
4700 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
4701 ok(IsZoomed(hwnd
), "window should be maximized\n");
4702 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
4703 DestroyWindow(hwnd
);
4707 static void test_sys_menu(void)
4713 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4714 100, 100, 200, 200, 0, 0, 0, NULL
);
4715 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4719 /* test existing window without CS_NOCLOSE style */
4720 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4721 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4723 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4724 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4725 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4727 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
4728 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4730 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4731 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4732 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
4734 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
4735 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
4737 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4738 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4739 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
4741 /* test whether removing WS_SYSMENU destroys a system menu */
4742 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
4743 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
4745 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4746 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4748 DestroyWindow(hwnd
);
4750 /* test new window with CS_NOCLOSE style */
4751 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
4752 100, 100, 200, 200, 0, 0, 0, NULL
);
4753 ok (hwnd
!= 0, "Failed to create overlapped window\n");
4755 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4756 ok(hmenu
!= 0, "GetSystemMenu error %d\n", GetLastError());
4758 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
4759 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
4761 DestroyWindow(hwnd
);
4763 /* test new window without WS_SYSMENU style */
4764 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
4765 100, 100, 200, 200, 0, 0, 0, NULL
);
4766 ok(hwnd
!= 0, "Failed to create overlapped window\n");
4768 hmenu
= GetSystemMenu(hwnd
, FALSE
);
4769 ok(!hmenu
, "GetSystemMenu error %d\n", GetLastError());
4771 DestroyWindow(hwnd
);
4774 /* For shown WS_OVERLAPPEDWINDOW */
4775 static const struct message WmSetIcon_1
[] = {
4776 { WM_SETICON
, sent
},
4777 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
4778 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4779 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
4783 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
4784 static const struct message WmSetIcon_2
[] = {
4785 { WM_SETICON
, sent
},
4789 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
4790 static const struct message WmInitEndSession
[] = {
4792 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4796 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
4797 static const struct message WmInitEndSession_2
[] = {
4799 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4803 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
4804 static const struct message WmInitEndSession_3
[] = {
4806 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
4810 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
4811 static const struct message WmInitEndSession_4
[] = {
4813 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
4817 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
4818 static const struct message WmInitEndSession_5
[] = {
4820 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
4824 static const struct message WmOptionalPaint
[] = {
4825 { WM_PAINT
, sent
|optional
},
4826 { WM_NCPAINT
, sent
|beginpaint
|optional
},
4827 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
4828 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
4832 static const struct message WmZOrder
[] = {
4833 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
4834 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
4835 { HCBT_ACTIVATE
, hook
},
4836 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
4837 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
4838 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
4839 { WM_GETTEXT
, sent
|optional
},
4840 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
4841 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
4842 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
4843 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4844 { WM_GETTEXT
, sent
|defwinproc
|optional
},
4845 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
4846 { HCBT_SETFOCUS
, hook
},
4847 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
4848 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
4849 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
4850 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
4851 { WM_GETTEXT
, sent
|optional
},
4852 { WM_NCCALCSIZE
, sent
|optional
},
4856 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
4861 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
4866 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4867 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4869 PostMessageA(hwnd
, WM_USER
, 0, 0);
4871 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4872 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4874 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4875 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4877 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4878 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4880 PostMessageA(hwnd
, WM_USER
, 0, 0);
4882 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4883 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4885 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
4886 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4888 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
4889 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4890 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4892 PostMessageA(hwnd
, WM_USER
, 0, 0);
4894 /* new incoming message causes it to become signaled again */
4895 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4896 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4898 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4899 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4900 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4901 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4903 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
4904 PostMessageA( hwnd
, WM_USER
, 0, 0 );
4905 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
4906 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4908 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_INPUTAVAILABLE
);
4909 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4911 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4912 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4914 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
4915 ret
= QueueUserAPC( apc_test_proc
, GetCurrentThread(), 0 );
4916 ok(ret
, "QueueUserAPC failed %u\n", GetLastError());
4918 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, 0 );
4919 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4921 /* but even with MWMO_ALERTABLE window events are preferred */
4922 PostMessageA( hwnd
, WM_USER
, 0, 0 );
4924 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
4925 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4927 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4928 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
4930 /* the APC call is still queued */
4931 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
4932 ok(ret
== WAIT_IO_COMPLETION
, "MsgWaitForMultipleObjectsEx returned %x\n", ret
);
4935 static void test_WM_DEVICECHANGE(HWND hwnd
)
4940 static const WPARAM wparams
[] = {0,
4941 DBT_DEVNODES_CHANGED
,
4942 DBT_QUERYCHANGECONFIG
,
4944 DBT_CONFIGCHANGECANCELED
,
4947 DBT_CONFIGMGPRIVATE
, /* 0x7fff */
4948 DBT_DEVICEARRIVAL
, /* 0x8000 */
4949 DBT_DEVICEQUERYREMOVE
,
4950 DBT_DEVICEQUERYREMOVEFAILED
,
4951 DBT_DEVICEREMOVEPENDING
,
4952 DBT_DEVICEREMOVECOMPLETE
,
4953 DBT_DEVICETYPESPECIFIC
,
4956 for (i
= 0; i
< sizeof(wparams
)/sizeof(wparams
[0]); i
++)
4958 SetLastError(0xdeadbeef);
4959 ret
= PostMessageA(hwnd
, WM_DEVICECHANGE
, wparams
[i
], 0);
4960 if (wparams
[i
] & 0x8000)
4962 ok(ret
== FALSE
, "PostMessage should returned %d\n", ret
);
4963 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY
, "PostMessage error %08x\n", GetLastError());
4967 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
4968 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %x\n", ret
);
4969 memset(&msg
, 0, sizeof(msg
));
4970 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
4971 ok(msg
.message
== WM_DEVICECHANGE
, "got %04x instead of WM_DEVICECHANGE\n", msg
.message
);
4976 static DWORD CALLBACK
show_window_thread(LPVOID arg
)
4980 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
4981 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
4986 /* Helper function to easier test SetWindowPos messages */
4987 #define test_msg_setpos( expected_list, flags, todo ) \
4988 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
4989 static void test_msg_setpos_(const struct message
*expected_list
, UINT flags
, BOOL todo
, const char *file
, int line
)
4995 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
4996 10, 10, 100, 100, NULL
, 0, 0, NULL
);
4997 ok (hwnd
!= 0, "Failed to create popup window\n");
4998 SetWindowPos(hwnd
, NULL
, 0, 0, 100, 100, flags
);
4999 ok_sequence_(expected_list
, "SetWindowPos:show_popup_first_show_window", todo
, file
, line
);
5000 DestroyWindow(hwnd
);
5003 /* test if we receive the right sequence of messages */
5004 static void test_messages(void)
5008 HWND hwnd
, hparent
, hchild
;
5009 HWND hchild2
, hbutton
;
5018 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5019 100, 100, 200, 200, 0, 0, 0, NULL
);
5020 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5021 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5023 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5024 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
5025 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
5027 /* test WM_SETREDRAW on a not visible top level window */
5028 test_WM_SETREDRAW(hwnd
);
5030 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5032 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
5033 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
5035 ok(GetActiveWindow() == hwnd
, "window should be active\n");
5036 ok(GetFocus() == hwnd
, "window should have input focus\n");
5037 ShowWindow(hwnd
, SW_HIDE
);
5039 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5041 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5042 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5044 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5046 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5047 hthread
= CreateThread(NULL
, 0, show_window_thread
, hwnd
, 0, &tid
);
5048 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
5049 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5050 CloseHandle(hthread
);
5052 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5054 ShowWindow(hwnd
, SW_SHOW
);
5056 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
5058 ShowWindow(hwnd
, SW_HIDE
);
5060 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5062 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5064 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
5067 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
5069 ShowWindow(hwnd
, SW_RESTORE
);
5071 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5075 ShowWindow(hwnd
, SW_MINIMIZE
);
5077 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE
);
5080 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
5082 ShowWindow(hwnd
, SW_RESTORE
);
5084 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5088 ShowWindow(hwnd
, SW_SHOW
);
5090 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
5092 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5093 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
5094 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
5095 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
5097 /* test WM_SETREDRAW on a visible top level window */
5098 ShowWindow(hwnd
, SW_SHOW
);
5100 test_WM_SETREDRAW(hwnd
);
5102 trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
5103 test_scroll_messages(hwnd
);
5105 /* test resizing and moving */
5106 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
5107 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
5110 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
5111 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
5114 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
5115 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
5119 /* popups don't get WM_GETMINMAXINFO */
5120 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
5121 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5123 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
5124 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
5126 DestroyWindow(hwnd
);
5127 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
5129 /* Test if windows are correctly drawn when first shown */
5131 /* Visible, redraw */
5134 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5135 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5136 ok (hwnd
!= 0, "Failed to create popup window\n");
5137 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5138 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_visible", TRUE
);
5139 DestroyWindow(hwnd
);
5141 /* Invisible, show, message */
5144 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5145 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5146 ok (hwnd
!= 0, "Failed to create popup window\n");
5147 ShowWindow(hwnd
, SW_SHOW
);
5148 SendMessageW(hwnd
, WM_PAINT
, 0, 0);
5149 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_show", TRUE
);
5150 DestroyWindow(hwnd
);
5152 /* Invisible, show maximized, redraw */
5155 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5156 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5157 ok (hwnd
!= 0, "Failed to create popup window\n");
5158 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5159 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5160 ok_sequence(WmShowPopupFirstDrawSeq_2
, "RedrawWindow:show_popup_first_draw_show_maximized", TRUE
);
5161 DestroyWindow(hwnd
);
5163 /* Test SetWindowPos */
5164 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
, TRUE
);
5165 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, 0, FALSE
);
5166 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
,
5167 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_NOZORDER
, TRUE
);
5169 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOSIZE
, TRUE
);
5170 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOMOVE
, TRUE
);
5171 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTSIZE
, TRUE
);
5172 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTMOVE
, TRUE
);
5173 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOZORDER
, TRUE
);
5175 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
, FALSE
);
5176 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTMOVE
, TRUE
);
5177 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTSIZE
, TRUE
);
5178 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOMOVE
, FALSE
);
5179 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOSIZE
, FALSE
);
5180 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOZORDER
, FALSE
);
5182 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
, TRUE
);
5183 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTMOVE
, TRUE
);
5184 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTSIZE
, TRUE
);
5185 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOMOVE
, TRUE
);
5186 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOSIZE
, TRUE
);
5187 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOZORDER
, TRUE
);
5189 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
, FALSE
);
5190 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTMOVE
, TRUE
);
5191 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTSIZE
, TRUE
);
5192 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOMOVE
, FALSE
);
5193 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOSIZE
, FALSE
);
5194 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOZORDER
, FALSE
);
5196 /* Test SetWindowPos with child windows */
5198 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5199 100, 100, 200, 200, 0, 0, 0, NULL
);
5200 ok (hparent
!= 0, "Failed to create parent window\n");
5202 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5203 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5204 ok (hchild
!= 0, "Failed to create child window\n");
5206 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5207 ok_sequence(WmFirstDrawChildSeq1
, /* Expect no messages for the child */
5208 "SetWindowPos:show_popup_first_show_window_child1", FALSE
);
5209 DestroyWindow(hchild
);
5210 DestroyWindow(hparent
);
5213 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
,
5214 100, 100, 200, 200, 0, 0, 0, NULL
);
5215 ok (hparent
!= 0, "Failed to create parent window\n");
5217 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5218 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5219 ok (hchild
!= 0, "Failed to create child window\n");
5221 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5222 ok_sequence(WmFirstDrawChildSeq2
, /* Expect child to be redrawn */
5223 "SetWindowPos:show_popup_first_show_window_child2", TRUE
);
5224 DestroyWindow(hchild
);
5225 DestroyWindow(hparent
);
5227 /* Test message sequence for extreme position and size */
5230 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5231 -10, -10, 10000, 10000, NULL
, 0, 0, NULL
);
5232 ok (hwnd
!= 0, "Failed to create popup window\n");
5233 ok_sequence(WmShowPopupExtremeLocationSeq
, "RedrawWindow:show_popup_extreme_location", TRUE
);
5234 DestroyWindow(hwnd
);
5237 /* Test child windows */
5239 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5240 100, 100, 200, 200, 0, 0, 0, NULL
);
5241 ok (hparent
!= 0, "Failed to create parent window\n");
5244 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
5245 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5246 ok (hchild
!= 0, "Failed to create child window\n");
5247 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
5248 DestroyWindow(hchild
);
5251 /* visible child window with a caption */
5252 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
5253 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
5254 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5255 ok (hchild
!= 0, "Failed to create child window\n");
5256 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
5258 trace("testing scroll APIs on a visible child window %p\n", hchild
);
5259 test_scroll_messages(hchild
);
5261 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5262 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
5264 DestroyWindow(hchild
);
5267 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5268 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5269 ok (hchild
!= 0, "Failed to create child window\n");
5270 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5272 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
5273 100, 100, 50, 50, hparent
, 0, 0, NULL
);
5274 ok (hchild2
!= 0, "Failed to create child2 window\n");
5277 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
5278 0, 100, 50, 50, hchild
, 0, 0, NULL
);
5279 ok (hbutton
!= 0, "Failed to create button window\n");
5281 /* test WM_SETREDRAW on a not visible child window */
5282 test_WM_SETREDRAW(hchild
);
5284 ShowWindow(hchild
, SW_SHOW
);
5285 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5287 /* check parent messages too */
5288 log_all_parent_messages
++;
5289 ShowWindow(hchild
, SW_HIDE
);
5290 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
5291 log_all_parent_messages
--;
5293 ShowWindow(hchild
, SW_SHOW
);
5294 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5296 ShowWindow(hchild
, SW_HIDE
);
5297 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
5299 ShowWindow(hchild
, SW_SHOW
);
5300 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5302 /* test WM_SETREDRAW on a visible child window */
5303 test_WM_SETREDRAW(hchild
);
5305 log_all_parent_messages
++;
5306 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
5307 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
5308 log_all_parent_messages
--;
5310 ShowWindow(hchild
, SW_HIDE
);
5312 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5313 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
5315 ShowWindow(hchild
, SW_HIDE
);
5317 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
5318 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
5320 /* DestroyWindow sequence below expects that a child has focus */
5324 DestroyWindow(hchild
);
5325 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
5326 DestroyWindow(hchild2
);
5327 DestroyWindow(hbutton
);
5330 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
5331 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5332 ok (hchild
!= 0, "Failed to create child popup window\n");
5333 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
5334 DestroyWindow(hchild
);
5336 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5338 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
5339 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5340 ok (hchild
!= 0, "Failed to create popup window\n");
5341 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5342 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5343 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5345 ShowWindow(hchild
, SW_SHOW
);
5346 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5348 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5349 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5351 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5352 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
5353 DestroyWindow(hchild
);
5355 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5356 * changes nothing in message sequences.
5359 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5360 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5361 ok (hchild
!= 0, "Failed to create popup window\n");
5362 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5363 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5364 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5366 ShowWindow(hchild
, SW_SHOW
);
5367 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5369 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5370 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5371 DestroyWindow(hchild
);
5374 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
5375 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5376 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5377 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
5380 trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
5381 test_scroll_messages(hwnd
);
5387 SendMessageA(hwnd
, WM_NULL
, 0, 0);
5390 after_end_dialog
= TRUE
;
5391 EndDialog( hwnd
, 0 );
5392 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
5394 DestroyWindow(hwnd
);
5395 after_end_dialog
= FALSE
;
5396 test_def_id
= FALSE
;
5398 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
5399 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5401 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
5402 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
5403 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5405 trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
5406 ShowWindow(hwnd
, SW_SHOW
);
5407 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
5411 ret
= DrawMenuBar(hwnd
);
5412 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
5414 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5415 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
5417 DestroyWindow(hwnd
);
5419 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_CHILD
|WS_VISIBLE
,
5420 0, 0, 100, 100, hparent
, 0, GetModuleHandleA(0), NULL
);
5421 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5424 ret
= DrawMenuBar(hwnd
);
5425 ok(ret
, "DrawMenuBar failed: %d\n", GetLastError());
5427 ok_sequence(WmEmptySeq
, "DrawMenuBar for a child window", FALSE
);
5429 DestroyWindow(hwnd
);
5432 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
5433 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
5435 DestroyWindow(hparent
);
5438 /* Message sequence for SetMenu */
5439 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
5440 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %d\n", GetLastError());
5441 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
5443 hmenu
= CreateMenu();
5444 ok (hmenu
!= 0, "Failed to create menu\n");
5445 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
5446 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5447 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
5448 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5449 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5450 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
5451 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5452 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
5453 ShowWindow(hwnd
, SW_SHOW
);
5454 UpdateWindow( hwnd
);
5457 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5458 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
5459 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
5460 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
5462 UpdateWindow( hwnd
);
5465 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
5467 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5469 DestroyWindow(hwnd
);
5472 /* Message sequence for EnableWindow */
5473 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5474 100, 100, 200, 200, 0, 0, 0, NULL
);
5475 ok (hparent
!= 0, "Failed to create parent window\n");
5476 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5477 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5478 ok (hchild
!= 0, "Failed to create child window\n");
5484 EnableWindow(hparent
, FALSE
);
5485 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
5487 EnableWindow(hparent
, TRUE
);
5488 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(TRUE)", FALSE
);
5493 test_MsgWaitForMultipleObjects(hparent
);
5494 test_WM_DEVICECHANGE(hparent
);
5496 /* the following test causes an exception in user.exe under win9x */
5497 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
5499 DestroyWindow(hparent
);
5503 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
5504 /* PeekMessage(NULL) fails, but still removes the message */
5505 SetLastError(0xdeadbeef);
5506 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
5507 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
5508 GetLastError() == 0xdeadbeef, /* NT4 */
5509 "last error is %d\n", GetLastError() );
5510 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
5511 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
5513 DestroyWindow(hchild
);
5514 DestroyWindow(hparent
);
5517 /* Message sequences for WM_SETICON */
5518 trace("testing WM_SETICON\n");
5519 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5520 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5522 ShowWindow(hwnd
, SW_SHOW
);
5526 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5527 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
5529 ShowWindow(hwnd
, SW_HIDE
);
5532 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5533 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
5534 DestroyWindow(hwnd
);
5537 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
5538 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
5540 ShowWindow(hwnd
, SW_SHOW
);
5544 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5545 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
5547 ShowWindow(hwnd
, SW_HIDE
);
5550 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
5551 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
5554 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
5557 todo_wine
win_skip( "Message 0x3b not supported\n" );
5560 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
5561 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res
);
5562 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
5563 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
5564 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res
);
5565 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
5566 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
5567 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res
);
5570 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
5571 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
5572 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res
);
5573 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
5574 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
5575 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res
);
5577 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
5578 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
5579 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res
);
5581 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
5582 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
5583 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res
);
5586 DestroyWindow(hwnd
);
5590 static void test_setwindowpos(void)
5595 const INT winX
= 100;
5596 const INT winY
= 100;
5597 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
5599 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
5600 0, 0, winX
, winY
, 0,
5603 GetWindowRect(hwnd
, &rc
);
5604 expect(sysX
, rc
.right
);
5605 expect(winY
, rc
.bottom
);
5609 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, winX
, winY
, 0);
5610 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
5611 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %ld\n", res
);
5613 GetWindowRect(hwnd
, &rc
);
5614 expect(sysX
, rc
.right
);
5615 expect(winY
, rc
.bottom
);
5616 DestroyWindow(hwnd
);
5619 static void invisible_parent_tests(void)
5621 HWND hparent
, hchild
;
5623 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
5624 100, 100, 200, 200, 0, 0, 0, NULL
);
5625 ok (hparent
!= 0, "Failed to create parent window\n");
5628 /* test showing child with hidden parent */
5630 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5631 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5632 ok (hchild
!= 0, "Failed to create child window\n");
5633 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5635 ShowWindow( hchild
, SW_MINIMIZE
);
5636 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5637 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5638 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5643 ShowWindow( hchild
, SW_MINIMIZE
);
5644 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
5646 DestroyWindow(hchild
);
5647 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5648 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5651 ShowWindow( hchild
, SW_MAXIMIZE
);
5652 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5653 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5654 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5659 ShowWindow( hchild
, SW_MAXIMIZE
);
5660 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
5662 DestroyWindow(hchild
);
5663 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5664 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5667 ShowWindow( hchild
, SW_RESTORE
);
5668 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
5669 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5670 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5672 DestroyWindow(hchild
);
5673 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5674 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5677 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5678 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5679 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5680 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5685 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
5686 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
5688 DestroyWindow(hchild
);
5689 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5690 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5693 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
5694 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
5695 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
5696 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5697 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5699 DestroyWindow(hchild
);
5700 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5701 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5704 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5705 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5706 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5707 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5712 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
5713 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
5715 DestroyWindow(hchild
);
5716 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5717 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5720 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
5721 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
5722 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
5724 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5726 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5728 DestroyWindow(hchild
);
5729 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5730 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5733 ShowWindow( hchild
, SW_SHOWNA
);
5734 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5735 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5736 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5741 ShowWindow( hchild
, SW_SHOWNA
);
5742 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
5744 DestroyWindow(hchild
);
5745 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5746 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5749 ShowWindow( hchild
, SW_SHOW
);
5750 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5751 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5752 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5757 ShowWindow( hchild
, SW_SHOW
);
5758 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
5760 ShowWindow( hchild
, SW_HIDE
);
5761 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
5762 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
5763 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5765 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5766 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
5767 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5768 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5770 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5771 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
5772 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
5773 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
5775 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5777 DestroyWindow(hchild
);
5778 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
5780 DestroyWindow(hparent
);
5784 /****************** button message test *************************/
5785 #define ID_BUTTON 0x000e
5787 static const struct message WmSetFocusButtonSeq
[] =
5789 { HCBT_SETFOCUS
, hook
},
5790 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5791 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5792 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5793 { WM_SETFOCUS
, sent
|wparam
, 0 },
5794 { WM_CTLCOLORBTN
, sent
|parent
},
5795 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5796 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5799 static const struct message WmKillFocusButtonSeq
[] =
5801 { HCBT_SETFOCUS
, hook
},
5802 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5803 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5804 { WM_CTLCOLORBTN
, sent
|parent
},
5805 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5806 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5807 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5808 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5810 { WM_CTLCOLORBTN
, sent
|parent
},
5813 static const struct message WmSetFocusStaticSeq
[] =
5815 { HCBT_SETFOCUS
, hook
},
5816 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5817 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5818 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5819 { WM_SETFOCUS
, sent
|wparam
, 0 },
5820 { WM_CTLCOLORSTATIC
, sent
|parent
},
5821 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5822 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
5823 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5826 static const struct message WmKillFocusStaticSeq
[] =
5828 { HCBT_SETFOCUS
, hook
},
5829 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5830 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5831 { WM_CTLCOLORSTATIC
, sent
|parent
},
5832 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5833 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5834 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5835 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5837 { WM_CTLCOLORSTATIC
, sent
|parent
},
5840 static const struct message WmSetFocusOwnerdrawSeq
[] =
5842 { HCBT_SETFOCUS
, hook
},
5843 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
5844 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5845 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5846 { WM_SETFOCUS
, sent
|wparam
, 0 },
5847 { WM_CTLCOLORBTN
, sent
|parent
},
5848 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
5849 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
5850 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5853 static const struct message WmKillFocusOwnerdrawSeq
[] =
5855 { HCBT_SETFOCUS
, hook
},
5856 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5857 { WM_KILLFOCUS
, sent
|wparam
, 0 },
5858 { WM_CTLCOLORBTN
, sent
|parent
},
5859 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
5860 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
5861 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
5862 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
5863 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5865 { WM_CTLCOLORBTN
, sent
|parent
},
5866 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
5869 static const struct message WmLButtonDownSeq
[] =
5871 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
5872 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
5873 { HCBT_SETFOCUS
, hook
},
5874 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5875 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5876 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5877 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5878 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5879 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
5880 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5881 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5884 static const struct message WmLButtonDownStaticSeq
[] =
5886 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
5887 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
5888 { HCBT_SETFOCUS
, hook
},
5889 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5890 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5891 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5892 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5893 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
5894 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
5895 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
5896 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5899 static const struct message WmLButtonUpSeq
[] =
5901 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
5902 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
5903 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5904 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5905 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
5906 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
5909 static const struct message WmLButtonUpStaticSeq
[] =
5911 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
5912 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
5913 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
5914 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5915 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
5916 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
5919 static const struct message WmLButtonUpAutoSeq
[] =
5921 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
5922 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
5923 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
5924 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5925 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
5926 { BM_SETCHECK
, sent
|defwinproc
},
5927 { WM_CTLCOLORSTATIC
, sent
|defwinproc
, 0, 0 },
5928 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
5931 static const struct message WmLButtonUpBrokenSeq
[] =
5933 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
5936 static const struct message WmSetFontButtonSeq
[] =
5938 { WM_SETFONT
, sent
},
5940 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
5941 { WM_CTLCOLORBTN
, sent
|defwinproc
},
5942 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
5945 static const struct message WmSetFontStaticSeq
[] =
5947 { WM_SETFONT
, sent
},
5949 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
5950 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
5953 static const struct message WmSetTextButtonSeq
[] =
5955 { WM_SETTEXT
, sent
},
5956 { WM_CTLCOLORBTN
, sent
|parent
},
5957 { WM_CTLCOLORBTN
, sent
|parent
},
5958 { WM_COMMAND
, sent
|parent
|optional
},
5959 { WM_DRAWITEM
, sent
|parent
|optional
},
5962 static const struct message WmSetTextStaticSeq
[] =
5964 { WM_SETTEXT
, sent
},
5965 { WM_CTLCOLORSTATIC
, sent
|parent
},
5966 { WM_CTLCOLORSTATIC
, sent
|parent
},
5969 static const struct message WmSetTextGroupSeq
[] =
5971 { WM_SETTEXT
, sent
},
5972 { WM_CTLCOLORSTATIC
, sent
|parent
},
5973 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
5974 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
}, /* FIXME: Missing in Wine */
5977 static const struct message WmSetTextInvisibleSeq
[] =
5979 { WM_SETTEXT
, sent
},
5982 static const struct message WmSetStyleButtonSeq
[] =
5984 { BM_SETSTYLE
, sent
},
5985 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5987 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5988 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5989 { WM_CTLCOLORBTN
, sent
|parent
},
5992 static const struct message WmSetStyleStaticSeq
[] =
5994 { BM_SETSTYLE
, sent
},
5995 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
5997 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
5998 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
5999 { WM_CTLCOLORSTATIC
, sent
|parent
},
6002 static const struct message WmSetStyleUserSeq
[] =
6004 { BM_SETSTYLE
, sent
},
6005 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6007 { WM_NCPAINT
, sent
|defwinproc
|optional
}, /* FIXME: Wine sends it */
6008 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6009 { WM_CTLCOLORBTN
, sent
|parent
},
6010 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
6013 static const struct message WmSetStyleOwnerdrawSeq
[] =
6015 { BM_SETSTYLE
, sent
},
6016 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6018 { WM_NCPAINT
, sent
|optional
}, /* FIXME: Wine sends it */
6019 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6020 { WM_CTLCOLORBTN
, sent
|parent
},
6021 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
6022 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6025 static const struct message WmSetStateButtonSeq
[] =
6027 { BM_SETSTATE
, sent
},
6028 { WM_CTLCOLORBTN
, sent
|parent
},
6029 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6032 static const struct message WmSetStateStaticSeq
[] =
6034 { BM_SETSTATE
, sent
},
6035 { WM_CTLCOLORSTATIC
, sent
|parent
},
6036 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6039 static const struct message WmSetStateUserSeq
[] =
6041 { BM_SETSTATE
, sent
},
6042 { WM_CTLCOLORBTN
, sent
|parent
},
6043 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
6044 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6047 static const struct message WmSetStateOwnerdrawSeq
[] =
6049 { BM_SETSTATE
, sent
},
6050 { WM_CTLCOLORBTN
, sent
|parent
},
6051 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
6052 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6055 static const struct message WmClearStateButtonSeq
[] =
6057 { BM_SETSTATE
, sent
},
6058 { WM_CTLCOLORBTN
, sent
|parent
},
6059 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
6060 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6063 static const struct message WmDisableButtonSeq
[] =
6065 { WM_LBUTTONDOWN
, sent
},
6066 { BM_SETSTATE
, sent
|defwinproc
},
6067 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6068 { WM_CTLCOLORBTN
, sent
|optional
},
6069 { WM_LBUTTONUP
, sent
},
6070 { BM_SETSTATE
, sent
|defwinproc
},
6071 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
},
6072 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6073 { BM_SETCHECK
, sent
|defwinproc
|optional
},
6074 { WM_CTLCOLORBTN
, sent
|optional
},
6075 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6076 { WM_CAPTURECHANGED
, sent
|defwinproc
},
6077 { WM_COMMAND
, sent
},
6080 static const struct message WmClearStateOwnerdrawSeq
[] =
6082 { BM_SETSTATE
, sent
},
6083 { WM_CTLCOLORBTN
, sent
|parent
},
6084 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
6085 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6088 static const struct message WmSetCheckIgnoredSeq
[] =
6090 { BM_SETCHECK
, sent
},
6091 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6094 static const struct message WmSetCheckStaticSeq
[] =
6096 { BM_SETCHECK
, sent
},
6097 { WM_CTLCOLORSTATIC
, sent
|parent
},
6098 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6102 static WNDPROC old_button_proc
;
6104 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6106 static LONG defwndproc_counter
= 0;
6108 struct recvd_message msg
;
6110 if (ignore_message( message
)) return 0;
6118 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
6122 msg
.message
= message
;
6123 msg
.flags
= sent
|wparam
|lparam
;
6124 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6125 msg
.wParam
= wParam
;
6126 msg
.lParam
= lParam
;
6127 msg
.descr
= "button";
6131 defwndproc_counter
++;
6132 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
6133 defwndproc_counter
--;
6138 static void subclass_button(void)
6142 if (!GetClassInfoA(0, "button", &cls
)) assert(0);
6144 old_button_proc
= cls
.lpfnWndProc
;
6146 cls
.hInstance
= GetModuleHandleA(NULL
);
6147 cls
.lpfnWndProc
= button_hook_proc
;
6148 cls
.lpszClassName
= "my_button_class";
6149 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6150 if (!RegisterClassA(&cls
)) assert(0);
6153 static void test_button_messages(void)
6159 const struct message
*setfocus
;
6160 const struct message
*killfocus
;
6161 const struct message
*setstyle
;
6162 const struct message
*setstate
;
6163 const struct message
*clearstate
;
6164 const struct message
*setcheck
;
6165 const struct message
*lbuttondown
;
6166 const struct message
*lbuttonup
;
6167 const struct message
*setfont
;
6168 const struct message
*settext
;
6170 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6171 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6172 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6173 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6174 WmSetTextButtonSeq
},
6175 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
6176 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6177 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6178 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6179 WmSetTextButtonSeq
},
6180 { BS_CHECKBOX
, DLGC_BUTTON
,
6181 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6182 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6183 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6184 WmSetTextStaticSeq
},
6185 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
6186 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6187 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6188 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6189 WmSetTextStaticSeq
},
6190 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6191 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6192 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6193 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6194 WmSetTextStaticSeq
},
6195 { BS_3STATE
, DLGC_BUTTON
,
6196 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6197 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6198 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6199 WmSetTextStaticSeq
},
6200 { BS_AUTO3STATE
, DLGC_BUTTON
,
6201 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6202 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6203 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6204 WmSetTextStaticSeq
},
6205 { BS_GROUPBOX
, DLGC_STATIC
,
6206 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6207 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
,
6208 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6209 WmSetTextGroupSeq
},
6210 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6211 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
6212 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
,
6213 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6214 WmSetTextButtonSeq
},
6215 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6216 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6217 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6218 NULL
/* avoid infinite loop */, WmLButtonUpBrokenSeq
, WmSetFontStaticSeq
,
6219 WmSetTextStaticSeq
},
6220 { BS_OWNERDRAW
, DLGC_BUTTON
,
6221 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
6222 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
,
6223 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6224 WmSetTextButtonSeq
},
6226 LOGFONTA logfont
= { 0 };
6227 HFONT zfont
, hfont2
;
6232 /* selection with VK_SPACE should capture button window */
6233 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
6234 0, 0, 50, 14, 0, 0, 0, NULL
);
6235 ok(hwnd
!= 0, "Failed to create button window\n");
6238 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
6239 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6240 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
6241 DestroyWindow(hwnd
);
6245 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6246 100, 100, 200, 200, 0, 0, 0, NULL
);
6247 ok(parent
!= 0, "Failed to create parent window\n");
6249 memset(&logfont
, 0, sizeof(logfont
));
6250 logfont
.lfHeight
= -12;
6251 logfont
.lfWeight
= FW_NORMAL
;
6252 strcpy(logfont
.lfFaceName
, "Tahoma");
6254 hfont2
= CreateFontIndirectA(&logfont
);
6255 ok(hfont2
!= NULL
, "Failed to create Tahoma font\n");
6257 for (i
= 0; i
< sizeof(button
)/sizeof(button
[0]); i
++)
6265 trace("button style %08x\n", button
[i
].style
);
6267 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
6268 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
6269 ok(hwnd
!= 0, "Failed to create button window\n");
6271 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6272 style
&= ~(WS_CHILD
| BS_NOTIFY
);
6273 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6274 if (button
[i
].style
== BS_USERBUTTON
)
6275 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %x\n", style
);
6277 ok(style
== button
[i
].style
, "expected style %x got %x\n", button
[i
].style
, style
);
6279 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
6280 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
6282 ShowWindow(hwnd
, SW_SHOW
);
6289 log_all_parent_messages
++;
6291 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6293 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6294 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6295 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
6298 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6299 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6300 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
6302 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6304 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
6305 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6306 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6307 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
6309 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6310 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
6311 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
6312 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6314 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6315 ok(state
== 0, "expected state 0, got %04x\n", state
);
6319 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
6320 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6321 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6322 ok_sequence(button
[i
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
6324 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6325 ok(state
== 0x0004, "expected state 0x0004, got %04x\n", state
);
6327 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6328 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6329 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6333 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
6334 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6335 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6336 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
6338 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6339 ok(state
== 0, "expected state 0, got %04x\n", state
);
6341 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6342 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6343 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6345 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6346 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
6350 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
6351 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6352 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6353 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
6355 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6356 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04x\n", state
);
6358 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6359 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6360 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6364 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
6365 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6366 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6367 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
6369 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 1");
6370 sprintf(desc
, "button[%i]: WM_SETTEXT on a visible button", i
);
6371 ok_sequence(button
[i
].settext
, desc
, FALSE
);
6373 ShowWindow(hwnd
, SW_HIDE
);
6377 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 2");
6378 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6379 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6381 ShowWindow(hwnd
, SW_SHOW
);
6382 ShowWindow(parent
, SW_HIDE
);
6386 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 3");
6387 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
6388 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
6390 ShowWindow(parent
, SW_SHOW
);
6393 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6394 if (button
[i
].style
== BS_PUSHBUTTON
||
6395 button
[i
].style
== BS_DEFPUSHBUTTON
||
6396 button
[i
].style
== BS_GROUPBOX
||
6397 button
[i
].style
== BS_USERBUTTON
||
6398 button
[i
].style
== BS_OWNERDRAW
)
6399 ok(state
== BST_UNCHECKED
, "expected check 0, got %04x\n", state
);
6401 ok(state
== BST_CHECKED
, "expected check 1, got %04x\n", state
);
6403 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6404 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6405 if (button
[i
].style
== BS_RADIOBUTTON
||
6406 button
[i
].style
== BS_AUTORADIOBUTTON
)
6407 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04x | WS_TABSTOP got %04x\n", button
[i
].style
, style
);
6409 ok(style
== button
[i
].style
, "expected style %04x got %04x\n", button
[i
].style
, style
);
6411 log_all_parent_messages
--;
6413 DestroyWindow(hwnd
);
6415 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
6416 0, 0, 50, 14, 0, 0, 0, NULL
);
6417 ok(hwnd
!= 0, "Failed to create button window\n");
6419 SetForegroundWindow(hwnd
);
6422 SetActiveWindow(hwnd
);
6426 if (button
[i
].lbuttondown
)
6428 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
6429 sprintf(desc
, "button[%i]: WM_LBUTTONDOWN on a button", i
);
6430 ok_sequence(button
[i
].lbuttondown
, desc
, FALSE
);
6433 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
6434 sprintf(desc
, "button[%i]: WM_LBUTTONUP on a button", i
);
6435 ok_sequence(button
[i
].lbuttonup
, desc
, FALSE
);
6438 zfont
= GetStockObject(DEFAULT_GUI_FONT
);
6439 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
6441 sprintf(desc
, "button[%i]: WM_SETFONT on a button", i
);
6442 ok_sequence(button
[i
].setfont
, desc
, FALSE
);
6444 /* Test that original font is not selected back after painting */
6445 hdc
= CreateCompatibleDC(0);
6447 prevfont
= SelectObject(hdc
, hfont2
);
6448 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
6449 SendMessageA(hwnd
, WM_PRINTCLIENT
, (WPARAM
)hdc
, 0);
6451 ok(GetStockObject(SYSTEM_FONT
) == GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i
);
6452 SelectObject(hdc
, prevfont
);
6454 prevfont
= SelectObject(hdc
, hfont2
);
6455 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
6456 SendMessageA(hwnd
, WM_PAINT
, (WPARAM
)hdc
, 0);
6458 ok(GetStockObject(SYSTEM_FONT
) == GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PAINT\n", i
);
6459 SelectObject(hdc
, prevfont
);
6463 DestroyWindow(hwnd
);
6466 DeleteObject(hfont2
);
6467 DestroyWindow(parent
);
6469 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
6471 parent
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6472 100, 100, 200, 200, 0, 0, 0, NULL
);
6473 ok (hwnd
!= 0, "Failed to create overlapped window\n");
6475 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON
| WS_VISIBLE
| WS_CHILD
,
6476 0, 0, 50, 14, parent
, 0, 0, NULL
);
6478 EnableWindow(hwnd
, FALSE
);
6480 SendMessageA(hwnd
, WM_LBUTTONDOWN
, MK_LBUTTON
, 0);
6481 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
6482 ok_sequence(WmDisableButtonSeq
, "Mouseclick on a disabled button", FALSE
);
6484 DestroyWindow(hwnd
);
6485 DestroyWindow(parent
);
6488 /****************** static message test *************************/
6489 static const struct message WmSetFontStaticSeq2
[] =
6491 { WM_SETFONT
, sent
},
6492 { WM_PAINT
, sent
|defwinproc
|optional
},
6493 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6494 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6498 static WNDPROC old_static_proc
;
6500 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6502 static LONG defwndproc_counter
= 0;
6504 struct recvd_message msg
;
6506 if (ignore_message( message
)) return 0;
6509 msg
.message
= message
;
6510 msg
.flags
= sent
|wparam
|lparam
;
6511 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6512 msg
.wParam
= wParam
;
6513 msg
.lParam
= lParam
;
6514 msg
.descr
= "static";
6517 defwndproc_counter
++;
6518 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
6519 defwndproc_counter
--;
6524 static void subclass_static(void)
6528 if (!GetClassInfoA(0, "static", &cls
)) assert(0);
6530 old_static_proc
= cls
.lpfnWndProc
;
6532 cls
.hInstance
= GetModuleHandleA(NULL
);
6533 cls
.lpfnWndProc
= static_hook_proc
;
6534 cls
.lpszClassName
= "my_static_class";
6535 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6536 if (!RegisterClassA(&cls
)) assert(0);
6539 static void test_static_messages(void)
6541 /* FIXME: make as comprehensive as the button message test */
6546 const struct message
*setfont
;
6548 { SS_LEFT
, DLGC_STATIC
,
6549 WmSetFontStaticSeq2
}
6557 for (i
= 0; i
< sizeof(static_ctrl
)/sizeof(static_ctrl
[0]); i
++)
6559 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
6560 0, 0, 50, 14, 0, 0, 0, NULL
);
6561 ok(hwnd
!= 0, "Failed to create static window\n");
6563 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
6564 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08x\n", i
, dlg_code
);
6566 ShowWindow(hwnd
, SW_SHOW
);
6571 trace("static style %08x\n", static_ctrl
[i
].style
);
6572 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
6573 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
6575 DestroyWindow(hwnd
);
6579 /****************** ComboBox message test *************************/
6580 #define ID_COMBOBOX 0x000f
6582 static const struct message WmKeyDownComboSeq
[] =
6584 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
6585 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
6586 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
6587 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
6588 { WM_CTLCOLOREDIT
, sent
|parent
},
6589 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
6593 static const struct message WmSetPosComboSeq
[] =
6595 { WM_WINDOWPOSCHANGING
, sent
},
6596 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
6597 { WM_CHILDACTIVATE
, sent
},
6598 { WM_WINDOWPOSCHANGED
, sent
},
6599 { WM_MOVE
, sent
|defwinproc
},
6600 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
6601 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
6602 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
6603 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
6604 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
6608 static const struct message WMSetFocusComboBoxSeq
[] =
6610 { WM_SETFOCUS
, sent
},
6611 { WM_KILLFOCUS
, sent
|parent
},
6612 { WM_SETFOCUS
, sent
},
6613 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
6614 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
6615 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
6616 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
6617 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
6621 static const struct message SetFocusButtonSeq
[] =
6623 { WM_KILLFOCUS
, sent
},
6624 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
6625 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
6626 { WM_LBUTTONUP
, sent
|defwinproc
},
6627 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
6628 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
6629 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
6630 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
6631 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
6632 { WM_CTLCOLORBTN
, sent
|parent
},
6636 static const struct message SetFocusComboBoxSeq
[] =
6638 { WM_CTLCOLORBTN
, sent
|parent
},
6639 { WM_SETFOCUS
, sent
},
6640 { WM_KILLFOCUS
, sent
|defwinproc
},
6641 { WM_SETFOCUS
, sent
},
6642 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
6643 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
6644 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
6645 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
6646 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
6650 static const struct message SetFocusButtonSeq2
[] =
6652 { WM_KILLFOCUS
, sent
},
6653 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
6654 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
6655 { WM_LBUTTONUP
, sent
|defwinproc
},
6656 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
6657 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
6658 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
6659 { WM_CTLCOLOREDIT
, sent
|parent
},
6660 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
6661 { WM_CTLCOLORBTN
, sent
|parent
},
6665 static WNDPROC old_combobox_proc
, edit_window_proc
;
6667 static LRESULT CALLBACK
combobox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6669 static LONG defwndproc_counter
= 0;
6671 struct recvd_message msg
;
6673 /* do not log painting messages */
6674 if (message
!= WM_PAINT
&&
6675 message
!= WM_NCPAINT
&&
6676 message
!= WM_SYNCPAINT
&&
6677 message
!= WM_ERASEBKGND
&&
6678 message
!= WM_NCHITTEST
&&
6679 message
!= WM_GETTEXT
&&
6680 !ignore_message( message
))
6683 msg
.message
= message
;
6684 msg
.flags
= sent
|wparam
|lparam
;
6685 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6686 msg
.wParam
= wParam
;
6687 msg
.lParam
= lParam
;
6688 msg
.descr
= "combo";
6692 defwndproc_counter
++;
6693 ret
= CallWindowProcA(edit_window_proc
, hwnd
, message
, wParam
, lParam
);
6694 defwndproc_counter
--;
6699 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6701 static LONG defwndproc_counter
= 0;
6703 struct recvd_message msg
;
6705 /* do not log painting messages */
6706 if (message
!= WM_PAINT
&&
6707 message
!= WM_NCPAINT
&&
6708 message
!= WM_SYNCPAINT
&&
6709 message
!= WM_ERASEBKGND
&&
6710 message
!= WM_NCHITTEST
&&
6711 message
!= WM_GETTEXT
&&
6712 !ignore_message( message
))
6715 msg
.message
= message
;
6716 msg
.flags
= sent
|wparam
|lparam
;
6717 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6718 msg
.wParam
= wParam
;
6719 msg
.lParam
= lParam
;
6720 msg
.descr
= "combo";
6724 defwndproc_counter
++;
6725 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
6726 defwndproc_counter
--;
6731 static void subclass_combobox(void)
6735 if (!GetClassInfoA(0, "ComboBox", &cls
)) assert(0);
6737 old_combobox_proc
= cls
.lpfnWndProc
;
6739 cls
.hInstance
= GetModuleHandleA(NULL
);
6740 cls
.lpfnWndProc
= combobox_hook_proc
;
6741 cls
.lpszClassName
= "my_combobox_class";
6742 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6743 if (!RegisterClassA(&cls
)) assert(0);
6746 static void test_combobox_messages(void)
6748 HWND parent
, combo
, button
, edit
;
6750 BOOL (WINAPI
*pGetComboBoxInfo
)(HWND
, PCOMBOBOXINFO
);
6751 COMBOBOXINFO cbInfo
;
6754 subclass_combobox();
6756 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6757 100, 100, 200, 200, 0, 0, 0, NULL
);
6758 ok(parent
!= 0, "Failed to create parent window\n");
6761 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
6762 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
6763 ok(combo
!= 0, "Failed to create combobox window\n");
6765 UpdateWindow(combo
);
6767 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
6768 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", ret
);
6770 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
6771 ok(ret
== 0, "expected 0, got %ld\n", ret
);
6772 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
6773 ok(ret
== 1, "expected 1, got %ld\n", ret
);
6774 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
6775 ok(ret
== 2, "expected 2, got %ld\n", ret
);
6777 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
6781 log_all_parent_messages
++;
6782 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
6783 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
6784 log_all_parent_messages
--;
6785 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
6788 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
6789 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
6791 DestroyWindow(combo
);
6792 DestroyWindow(parent
);
6794 /* Start again. Test combobox text selection when getting and losing focus */
6795 pGetComboBoxInfo
= (void *)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
6796 if (!pGetComboBoxInfo
)
6798 win_skip("GetComboBoxInfo is not available\n");
6802 parent
= CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6803 10, 10, 300, 300, NULL
, NULL
, NULL
, NULL
);
6804 ok(parent
!= 0, "Failed to create parent window\n");
6806 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWN
,
6807 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
6808 ok(combo
!= 0, "Failed to create combobox window\n");
6810 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
6811 SetLastError(0xdeadbeef);
6812 res
= pGetComboBoxInfo(combo
, &cbInfo
);
6813 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError());
6814 edit
= cbInfo
.hwndItem
;
6816 edit_window_proc
= (WNDPROC
)SetWindowLongPtrA(edit
, GWLP_WNDPROC
, (ULONG_PTR
)combobox_subclass_proc
);
6818 button
= CreateWindowExA(0, "Button", "OK", WS_CHILD
| WS_VISIBLE
| BS_DEFPUSHBUTTON
,
6819 5, 50, 100, 20, parent
, NULL
,
6820 (HINSTANCE
)GetWindowLongPtrA(parent
, GWLP_HINSTANCE
), NULL
);
6821 ok(button
!= 0, "Failed to create button window\n");
6824 log_all_parent_messages
++;
6825 SendMessageA(combo
, WM_SETFOCUS
, 0, (LPARAM
)edit
);
6826 log_all_parent_messages
--;
6827 ok_sequence(WMSetFocusComboBoxSeq
, "WM_SETFOCUS on a ComboBox", TRUE
);
6830 log_all_parent_messages
++;
6832 log_all_parent_messages
--;
6833 ok_sequence(SetFocusButtonSeq
, "SetFocus on a Button", TRUE
);
6835 SendMessageA(combo
, WM_SETTEXT
, 0, (LPARAM
)"Wine Test");
6838 log_all_parent_messages
++;
6840 log_all_parent_messages
--;
6841 ok_sequence(SetFocusComboBoxSeq
, "SetFocus on a ComboBox", TRUE
);
6844 log_all_parent_messages
++;
6846 log_all_parent_messages
--;
6847 ok_sequence(SetFocusButtonSeq2
, "SetFocus on a Button (2)", TRUE
);
6849 DestroyWindow(button
);
6850 DestroyWindow(combo
);
6851 DestroyWindow(parent
);
6854 /****************** WM_IME_KEYDOWN message test *******************/
6856 static const struct message WmImeKeydownMsgSeq_0
[] =
6858 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
6859 { WM_CHAR
, wparam
, 'A' },
6863 static const struct message WmImeKeydownMsgSeq_1
[] =
6865 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
6866 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
6870 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6872 struct recvd_message msg
;
6875 msg
.message
= message
;
6876 msg
.flags
= wparam
|lparam
;
6877 msg
.wParam
= wParam
;
6878 msg
.lParam
= lParam
;
6879 msg
.descr
= "wmime_keydown";
6882 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
6885 static void register_wmime_keydown_class(void)
6889 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
6890 cls
.lpfnWndProc
= wmime_keydown_procA
;
6891 cls
.hInstance
= GetModuleHandleA(0);
6892 cls
.lpszClassName
= "wmime_keydown_class";
6893 if (!RegisterClassA(&cls
)) assert(0);
6896 static void test_wmime_keydown_message(void)
6901 trace("Message sequences by WM_IME_KEYDOWN\n");
6903 register_wmime_keydown_class();
6904 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
6905 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6910 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
6911 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
6912 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
6914 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
6916 TranslateMessage(&msg
);
6917 DispatchMessageA(&msg
);
6919 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
6921 DestroyWindow(hwnd
);
6924 /************* painting message test ********************/
6926 void dump_region(HRGN hrgn
)
6929 RGNDATA
*data
= NULL
;
6934 printf( "null region\n" );
6937 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
6938 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
6939 GetRegionData( hrgn
, size
, data
);
6940 printf("%d rects:", data
->rdh
.nCount
);
6941 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
6942 printf( " %s", wine_dbgstr_rect( rect
));
6944 HeapFree( GetProcessHeap(), 0, data
);
6947 static void check_update_rgn( HWND hwnd
, HRGN hrgn
)
6951 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
6952 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
6954 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
6955 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
6956 if (ret
== NULLREGION
)
6958 ok( !hrgn
, "Update region shouldn't be empty\n" );
6962 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
6964 ok( 0, "Regions are different\n" );
6965 if (winetest_debug
> 0)
6967 printf( "Update region: " );
6968 dump_region( update
);
6969 printf( "Wanted region: " );
6970 dump_region( hrgn
);
6974 GetRgnBox( update
, &r1
);
6975 GetUpdateRect( hwnd
, &r2
, FALSE
);
6976 ok( EqualRect( &r1
, &r2
), "Rectangles are different: %s / %s\n", wine_dbgstr_rect( &r1
),
6977 wine_dbgstr_rect( &r2
));
6979 DeleteObject( tmp
);
6980 DeleteObject( update
);
6983 static const struct message WmInvalidateRgn
[] = {
6984 { WM_NCPAINT
, sent
},
6985 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6989 static const struct message WmGetUpdateRect
[] = {
6990 { WM_NCPAINT
, sent
},
6991 { WM_GETTEXT
, sent
|defwinproc
|optional
},
6996 static const struct message WmInvalidateFull
[] = {
6997 { WM_NCPAINT
, sent
|wparam
, 1 },
6998 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7002 static const struct message WmInvalidateErase
[] = {
7003 { WM_NCPAINT
, sent
|wparam
, 1 },
7004 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7005 { WM_ERASEBKGND
, sent
},
7009 static const struct message WmInvalidatePaint
[] = {
7011 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
7012 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7016 static const struct message WmInvalidateErasePaint
[] = {
7018 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
7019 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7020 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7024 static const struct message WmInvalidateErasePaint2
[] = {
7026 { WM_NCPAINT
, sent
|beginpaint
},
7027 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7028 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7032 static const struct message WmErase
[] = {
7033 { WM_ERASEBKGND
, sent
},
7037 static const struct message WmPaint
[] = {
7042 static const struct message WmParentOnlyPaint
[] = {
7043 { WM_PAINT
, sent
|parent
},
7047 static const struct message WmInvalidateParent
[] = {
7048 { WM_NCPAINT
, sent
|parent
},
7049 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
7050 { WM_ERASEBKGND
, sent
|parent
},
7054 static const struct message WmInvalidateParentChild
[] = {
7055 { WM_NCPAINT
, sent
|parent
},
7056 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
7057 { WM_ERASEBKGND
, sent
|parent
},
7058 { WM_NCPAINT
, sent
},
7059 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7060 { WM_ERASEBKGND
, sent
},
7064 static const struct message WmInvalidateParentChild2
[] = {
7065 { WM_ERASEBKGND
, sent
|parent
},
7066 { WM_NCPAINT
, sent
},
7067 { WM_GETTEXT
, sent
|defwinproc
|optional
},
7068 { WM_ERASEBKGND
, sent
},
7072 static const struct message WmParentPaint
[] = {
7073 { WM_PAINT
, sent
|parent
},
7078 static const struct message WmParentPaintNc
[] = {
7079 { WM_PAINT
, sent
|parent
},
7081 { WM_NCPAINT
, sent
|beginpaint
},
7082 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7083 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7087 static const struct message WmChildPaintNc
[] = {
7089 { WM_NCPAINT
, sent
|beginpaint
},
7090 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7091 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7095 static const struct message WmParentErasePaint
[] = {
7096 { WM_PAINT
, sent
|parent
},
7097 { WM_NCPAINT
, sent
|parent
|beginpaint
},
7098 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
7099 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
7101 { WM_NCPAINT
, sent
|beginpaint
},
7102 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
7103 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
7107 static const struct message WmParentOnlyNcPaint
[] = {
7108 { WM_PAINT
, sent
|parent
},
7109 { WM_NCPAINT
, sent
|parent
|beginpaint
},
7110 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
7114 static const struct message WmSetParentStyle
[] = {
7115 { WM_STYLECHANGING
, sent
|parent
},
7116 { WM_STYLECHANGED
, sent
|parent
},
7120 static void test_paint_messages(void)
7126 HWND hparent
, hchild
;
7127 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
7128 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
7129 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
7130 100, 100, 200, 200, 0, 0, 0, NULL
);
7131 ok (hwnd
!= 0, "Failed to create overlapped window\n");
7133 ShowWindow( hwnd
, SW_SHOW
);
7134 UpdateWindow( hwnd
);
7138 check_update_rgn( hwnd
, 0 );
7139 SetRectRgn( hrgn
, 10, 10, 20, 20 );
7140 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7141 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7142 check_update_rgn( hwnd
, hrgn
);
7143 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
7144 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
7145 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7146 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
7147 check_update_rgn( hwnd
, hrgn
);
7148 /* validate everything */
7149 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7150 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7151 check_update_rgn( hwnd
, 0 );
7153 /* test empty region */
7154 SetRectRgn( hrgn
, 10, 10, 10, 15 );
7155 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7156 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7157 check_update_rgn( hwnd
, 0 );
7158 /* test empty rect */
7159 SetRect( &rect
, 10, 10, 10, 15 );
7160 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
7161 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
7162 check_update_rgn( hwnd
, 0 );
7164 /* flush pending messages */
7168 GetClientRect( hwnd
, &rect
);
7169 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
7170 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
7171 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
7173 trace("testing InvalidateRect(0, NULL, FALSE)\n");
7174 SetRectEmpty( &rect
);
7175 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) should fail\n");
7176 check_update_rgn( hwnd
, hrgn
);
7177 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7179 ok_sequence( WmPaint
, "Paint", FALSE
);
7180 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7181 check_update_rgn( hwnd
, 0 );
7183 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
7184 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
7186 trace("testing ValidateRect(0, NULL)\n");
7187 SetRectEmpty( &rect
);
7188 if (ValidateRect(0, &rect
) && /* not supported on Win9x */
7189 GetUpdateRect(hwnd
, NULL
, FALSE
)) /* or >= Win 8 */
7191 check_update_rgn( hwnd
, hrgn
);
7192 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7194 ok_sequence( WmPaint
, "Paint", FALSE
);
7195 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
7196 check_update_rgn( hwnd
, 0 );
7199 trace("testing InvalidateRgn(0, NULL, FALSE)\n");
7200 SetLastError(0xdeadbeef);
7201 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
7202 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
7203 "wrong error code %d\n", GetLastError());
7204 check_update_rgn( hwnd
, 0 );
7206 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7208 trace("testing ValidateRgn(0, NULL)\n");
7209 SetLastError(0xdeadbeef);
7210 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
7211 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
7212 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
7213 "wrong error code %d\n", GetLastError());
7214 check_update_rgn( hwnd
, 0 );
7216 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7218 trace("testing UpdateWindow(NULL)\n");
7219 SetLastError(0xdeadbeef);
7220 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
7221 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
7222 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
7223 "wrong error code %d\n", GetLastError());
7224 check_update_rgn( hwnd
, 0 );
7226 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
7228 /* now with frame */
7229 SetRectRgn( hrgn
, -5, -5, 20, 20 );
7231 /* flush pending messages */
7234 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7235 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
7237 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
7238 check_update_rgn( hwnd
, hrgn
);
7241 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
7242 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
7245 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
7246 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
7248 GetClientRect( hwnd
, &rect
);
7249 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
7250 check_update_rgn( hwnd
, hrgn
);
7253 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
7254 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
7257 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
7258 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
7259 check_update_rgn( hwnd
, 0 );
7262 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
7263 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
7264 check_update_rgn( hwnd
, 0 );
7267 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7268 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
7269 SetRectRgn( hrgn
, 0, 0, 50, 100 );
7270 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
7271 SetRectRgn( hrgn
, 50, 0, 100, 100 );
7272 check_update_rgn( hwnd
, hrgn
);
7273 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
7274 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
7275 check_update_rgn( hwnd
, 0 );
7278 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7279 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
7280 SetRectRgn( hrgn
, 0, 0, 100, 50 );
7281 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
7282 ok_sequence( WmErase
, "Erase", FALSE
);
7283 SetRectRgn( hrgn
, 0, 50, 100, 100 );
7284 check_update_rgn( hwnd
, hrgn
);
7287 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7288 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
7289 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7290 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
7291 ok_sequence( WmPaint
, "Paint", FALSE
);
7294 SetRectRgn( hrgn
, -4, -4, -2, -2 );
7295 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7296 SetRectRgn( hrgn
, -200, -200, -198, -198 );
7297 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
7298 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
7301 SetRectRgn( hrgn
, -4, -4, -2, -2 );
7302 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7303 SetRectRgn( hrgn
, -4, -4, -3, -3 );
7304 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
7305 SetRectRgn( hrgn
, 0, 0, 1, 1 );
7306 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
7307 ok_sequence( WmPaint
, "Paint", FALSE
);
7310 SetRectRgn( hrgn
, -4, -4, -1, -1 );
7311 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7312 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
7313 /* make sure no WM_PAINT was generated */
7315 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
7318 SetRectRgn( hrgn
, -4, -4, -1, -1 );
7319 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
7320 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
7322 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
7324 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
7325 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
7326 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
7327 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
7328 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
7329 /* this will send WM_NCPAINT and validate the non client area */
7330 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
7331 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
7333 DispatchMessageA( &msg
);
7335 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
7337 DestroyWindow( hwnd
);
7339 /* now test with a child window */
7341 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
7342 100, 100, 200, 200, 0, 0, 0, NULL
);
7343 ok (hparent
!= 0, "Failed to create parent window\n");
7345 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
7346 10, 10, 100, 100, hparent
, 0, 0, NULL
);
7347 ok (hchild
!= 0, "Failed to create child window\n");
7349 ShowWindow( hparent
, SW_SHOW
);
7350 UpdateWindow( hparent
);
7351 UpdateWindow( hchild
);
7354 log_all_parent_messages
++;
7356 SetRect( &rect
, 0, 0, 50, 50 );
7357 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7358 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
7359 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
7361 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7363 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
7364 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
7365 check_update_rgn( hchild
, hrgn
);
7366 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7367 check_update_rgn( hparent
, hrgn
);
7368 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
7369 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
7370 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
7371 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
7374 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
7376 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
7377 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
7378 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
7379 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
7380 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
7382 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
7383 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
7384 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
7386 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
7388 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
7389 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
7390 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
7392 /* flush all paint messages */
7396 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
7397 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
7398 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7399 check_update_rgn( hparent
, hrgn
);
7400 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
7401 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
7402 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7403 check_update_rgn( hparent
, hrgn
);
7405 /* flush all paint messages */
7407 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
7410 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
7411 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7412 SetRectRgn( hrgn
, 0, 0, 50, 50 );
7413 check_update_rgn( hparent
, hrgn
);
7414 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
7415 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
7416 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
7417 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
7418 check_update_rgn( hparent
, hrgn
);
7419 /* flush all paint messages */
7423 /* same as above but parent gets completely validated */
7424 SetRect( &rect
, 20, 20, 30, 30 );
7425 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7426 SetRectRgn( hrgn
, 20, 20, 30, 30 );
7427 check_update_rgn( hparent
, hrgn
);
7428 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
7429 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
7430 check_update_rgn( hparent
, 0 ); /* no update region */
7432 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
7434 /* make sure RDW_VALIDATE on child doesn't have the same effect */
7436 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7437 SetRectRgn( hrgn
, 20, 20, 30, 30 );
7438 check_update_rgn( hparent
, hrgn
);
7439 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
7440 SetRectRgn( hrgn
, 20, 20, 30, 30 );
7441 check_update_rgn( hparent
, hrgn
);
7443 /* same as above but normal WM_PAINT doesn't validate parent */
7445 SetRect( &rect
, 20, 20, 30, 30 );
7446 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7447 SetRectRgn( hrgn
, 20, 20, 30, 30 );
7448 check_update_rgn( hparent
, hrgn
);
7449 /* no WM_PAINT in child while parent still pending */
7450 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
7451 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
7452 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
7453 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
7456 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7457 /* no WM_PAINT in child while parent still pending */
7458 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
7459 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
7460 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
7461 /* now that parent is valid child should get WM_PAINT */
7462 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
7463 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
7464 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
7465 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
7467 /* same thing with WS_CLIPCHILDREN in parent */
7469 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
7470 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
7471 /* changing style invalidates non client area, but we need to invalidate something else to see it */
7472 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
7473 ok_sequence( WmEmptySeq
, "No message", FALSE
);
7474 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
7475 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
7478 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
7479 SetRectRgn( hrgn
, 20, 20, 30, 30 );
7480 check_update_rgn( hparent
, hrgn
);
7481 /* no WM_PAINT in child while parent still pending */
7482 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
7483 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
7484 /* WM_PAINT in parent first */
7485 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
7486 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
7488 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
7490 SetRect( &rect
, 0, 0, 30, 30 );
7491 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
7492 SetRectRgn( hrgn
, 0, 0, 30, 30 );
7493 check_update_rgn( hparent
, hrgn
);
7495 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
7497 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
7499 SetRect( &rect
, -10, 0, 30, 30 );
7500 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
7501 SetRect( &rect
, 0, 0, 20, 20 );
7502 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
7503 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
7504 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
7506 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
7508 SetRect( &rect
, -10, 0, 30, 30 );
7509 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
7510 SetRect( &rect
, 0, 0, 100, 100 );
7511 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
7512 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
7513 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
7514 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
7515 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
7517 /* WS_CLIPCHILDREN doesn't exclude children from update region */
7519 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
7520 GetClientRect( hparent
, &rect
);
7521 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
7522 check_update_rgn( hparent
, hrgn
);
7525 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
7526 GetClientRect( hparent
, &rect
);
7527 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
7528 check_update_rgn( hparent
, hrgn
);
7531 /* test RDW_INTERNALPAINT behavior */
7534 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
7536 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
7538 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
7540 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
7542 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
7544 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
7546 assert( GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
);
7547 UpdateWindow( hparent
);
7550 trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
7551 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7552 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
7553 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
7555 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
7557 UpdateWindow( hparent
);
7560 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
7561 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7562 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
7563 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
7565 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
7567 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
7568 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
7569 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
7571 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
7573 assert( !(GetWindowLongA(hparent
, GWL_STYLE
) & WS_CLIPCHILDREN
) );
7574 UpdateWindow( hparent
);
7577 trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
7578 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7579 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
7580 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
7582 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
7584 UpdateWindow( hparent
);
7587 trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
7588 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
7589 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
7590 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
7592 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
7594 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
7595 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
7597 UpdateWindow( hparent
);
7600 trace("testing SetWindowPos(-10000, -10000) on child\n");
7601 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
7602 check_update_rgn( hchild
, 0 );
7605 #if 0 /* this one doesn't pass under Wine yet */
7606 UpdateWindow( hparent
);
7609 trace("testing ShowWindow(SW_MINIMIZE) on child\n");
7610 ShowWindow( hchild
, SW_MINIMIZE
);
7611 check_update_rgn( hchild
, 0 );
7615 UpdateWindow( hparent
);
7618 trace("testing SetWindowPos(-10000, -10000) on parent\n");
7619 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
7620 check_update_rgn( hparent
, 0 );
7623 log_all_parent_messages
--;
7624 DestroyWindow( hparent
);
7625 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
7627 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
7629 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
7630 100, 100, 200, 200, 0, 0, 0, NULL
);
7631 ok (hparent
!= 0, "Failed to create parent window\n");
7633 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
7634 10, 10, 100, 100, hparent
, 0, 0, NULL
);
7635 ok (hchild
!= 0, "Failed to create child window\n");
7637 ShowWindow( hparent
, SW_SHOW
);
7638 UpdateWindow( hparent
);
7639 UpdateWindow( hchild
);
7643 /* moving child outside of parent boundaries changes update region */
7644 SetRect( &rect
, 0, 0, 40, 40 );
7645 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
7646 SetRectRgn( hrgn
, 0, 0, 40, 40 );
7647 check_update_rgn( hchild
, hrgn
);
7648 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
7649 SetRectRgn( hrgn
, 10, 0, 40, 40 );
7650 check_update_rgn( hchild
, hrgn
);
7651 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
7652 SetRectRgn( hrgn
, 10, 10, 40, 40 );
7653 check_update_rgn( hchild
, hrgn
);
7655 /* moving parent off-screen does too */
7656 SetRect( &rect
, 0, 0, 100, 100 );
7657 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
7658 SetRectRgn( hrgn
, 0, 0, 100, 100 );
7659 check_update_rgn( hparent
, hrgn
);
7660 SetRectRgn( hrgn
, 10, 10, 40, 40 );
7661 check_update_rgn( hchild
, hrgn
);
7662 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
7663 GetUpdateRect( hparent
, &rect2
, FALSE
);
7664 if (!EqualRect( &rect2
, &rect
)) /* Win 8 and later don't crop update to screen */
7669 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
7670 check_update_rgn( hparent
, hrgn
);
7671 SetRectRgn( hrgn
, rect
.left
+ 10, rect
.top
+ 10, 40, 40 );
7672 check_update_rgn( hchild
, hrgn
);
7674 /* invalidated region is cropped by the parent rects */
7675 SetRect( &rect
, 0, 0, 50, 50 );
7676 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
7677 SetRectRgn( hrgn
, rect2
.left
+ 10, rect2
.top
+ 10, 50, 50 );
7678 check_update_rgn( hchild
, hrgn
);
7680 DestroyWindow( hparent
);
7681 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
7684 DeleteObject( hrgn
);
7685 DeleteObject( hrgn2
);
7696 static DWORD WINAPI
thread_proc(void *param
)
7699 struct wnd_event
*wnd_event
= param
;
7701 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
7702 100, 100, 200, 200, 0, 0, 0, NULL
);
7703 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
7705 SetEvent(wnd_event
->start_event
);
7707 while (GetMessageA(&msg
, 0, 0, 0))
7709 TranslateMessage(&msg
);
7710 DispatchMessageA(&msg
);
7713 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
7718 static DWORD CALLBACK
create_grand_child_thread( void *param
)
7720 struct wnd_event
*wnd_event
= param
;
7724 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
7725 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
7726 ok (hchild
!= 0, "Failed to create child window\n");
7729 SetEvent( wnd_event
->start_event
);
7733 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
7734 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
7735 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7740 static DWORD CALLBACK
create_child_thread( void *param
)
7742 struct wnd_event
*wnd_event
= param
;
7743 struct wnd_event child_event
;
7747 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
7748 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
7749 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
7750 SetFocus( child_event
.hwnd
);
7753 child_event
.start_event
= wnd_event
->start_event
;
7754 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
7757 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
7758 if (ret
!= 1) break;
7759 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7761 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
7762 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
7766 static const char manifest_dep
[] =
7767 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
7768 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
7769 " <file name=\"testdep.dll\" />"
7772 static const char manifest_main
[] =
7773 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
7774 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
7776 " <dependentAssembly>"
7777 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
7778 " </dependentAssembly>"
7782 static void create_manifest_file(const char *filename
, const char *manifest
)
7784 WCHAR path
[MAX_PATH
];
7788 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
7789 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
7790 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
7791 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
7795 static HANDLE
test_create(const char *file
)
7797 WCHAR path
[MAX_PATH
];
7801 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
7802 memset(&actctx
, 0, sizeof(ACTCTXW
));
7803 actctx
.cbSize
= sizeof(ACTCTXW
);
7804 actctx
.lpSource
= path
;
7806 handle
= pCreateActCtxW(&actctx
);
7807 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %u\n", GetLastError());
7809 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%d\n", actctx
.cbSize
);
7810 ok(actctx
.dwFlags
== 0, "dwFlags=%d\n", actctx
.dwFlags
);
7811 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
7812 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
7813 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
7814 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
7815 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
7816 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
7817 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
7822 static void test_interthread_messages(void)
7824 HANDLE hThread
, context
, handle
, event
;
7830 int len
, expected_len
;
7831 struct wnd_event wnd_event
;
7834 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
7835 if (!wnd_event
.start_event
)
7837 win_skip("skipping interthread message test under win9x\n");
7841 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
7842 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
7844 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7846 CloseHandle(wnd_event
.start_event
);
7848 SetLastError(0xdeadbeef);
7849 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
7850 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
7851 "wrong error code %d\n", GetLastError());
7853 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
7854 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
7856 expected_len
= lstrlenA("window caption text");
7857 memset(buf
, 0, sizeof(buf
));
7858 SetLastError(0xdeadbeef);
7859 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
7860 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
7861 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
7863 msg
.hwnd
= wnd_event
.hwnd
;
7864 msg
.message
= WM_GETTEXT
;
7865 msg
.wParam
= sizeof(buf
);
7866 msg
.lParam
= (LPARAM
)buf
;
7867 memset(buf
, 0, sizeof(buf
));
7868 SetLastError(0xdeadbeef);
7869 len
= DispatchMessageA(&msg
);
7870 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
7871 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len
, GetLastError());
7873 /* the following test causes an exception in user.exe under win9x */
7874 msg
.hwnd
= wnd_event
.hwnd
;
7875 msg
.message
= WM_TIMER
;
7877 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
7878 SetLastError(0xdeadbeef);
7879 len
= DispatchMessageA(&msg
);
7880 ok(!len
&& GetLastError() == 0xdeadbeef,
7881 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len
, GetLastError());
7883 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
7884 ok( ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
7886 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7887 CloseHandle(hThread
);
7889 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
7891 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7892 100, 100, 200, 200, 0, 0, 0, NULL
);
7893 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
7896 log_all_parent_messages
++;
7897 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
7898 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
7899 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
7902 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
7903 if (ret
!= 1) break;
7904 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7906 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
7907 /* now wait for the thread without processing messages; this shouldn't deadlock */
7908 SetEvent( wnd_event
.stop_event
);
7909 ret
= WaitForSingleObject( hThread
, 5000 );
7910 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
7911 CloseHandle( hThread
);
7913 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
7914 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
7915 CloseHandle( wnd_event
.grand_child
);
7917 CloseHandle( wnd_event
.start_event
);
7918 CloseHandle( wnd_event
.stop_event
);
7920 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
7921 log_all_parent_messages
--;
7922 DestroyWindow( wnd_event
.hwnd
);
7924 /* activation context tests */
7925 if (!pActivateActCtx
)
7927 win_skip("Activation contexts are not supported, skipping\n");
7931 create_manifest_file("testdep1.manifest", manifest_dep
);
7932 create_manifest_file("main.manifest", manifest_main
);
7934 context
= test_create("main.manifest");
7935 DeleteFileA("testdep1.manifest");
7936 DeleteFileA("main.manifest");
7938 handle
= (void*)0xdeadbeef;
7939 ret
= pGetCurrentActCtx(&handle
);
7940 ok(ret
, "GetCurrentActCtx failed: %u\n", GetLastError());
7941 ok(handle
== 0, "active context %p\n", handle
);
7943 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
7944 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
7945 ok(hThread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
7946 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7947 CloseHandle(wnd_event
.start_event
);
7949 /* context is activated after thread creation, so it doesn't inherit it by default */
7950 ret
= pActivateActCtx(context
, &cookie
);
7951 ok(ret
, "activation failed: %u\n", GetLastError());
7954 ret
= pGetCurrentActCtx(&handle
);
7955 ok(ret
, "GetCurrentActCtx failed: %u\n", GetLastError());
7956 ok(handle
!= 0, "active context %p\n", handle
);
7957 pReleaseActCtx(handle
);
7959 /* destination window will test for active context */
7960 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
7961 ok(ret
, "thread window returned %d\n", ret
);
7963 event
= CreateEventW(NULL
, 0, 0, NULL
);
7964 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
7965 ok(ret
, "thread window returned %d\n", ret
);
7966 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7969 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
7970 ok(ret
, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
7972 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
7973 CloseHandle(hThread
);
7975 ret
= pDeactivateActCtx(0, cookie
);
7976 ok(ret
, "DeactivateActCtx failed: %u\n", GetLastError());
7977 pReleaseActCtx(context
);
7981 static const struct message WmVkN
[] = {
7982 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7983 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7984 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7985 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
7986 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
7987 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
7988 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
7989 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
7992 static const struct message WmShiftVkN
[] = {
7993 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
7994 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
7995 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
7996 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
7997 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
7998 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
7999 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
8000 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
8001 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8002 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8003 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8004 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8005 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8006 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8009 static const struct message WmCtrlVkN
[] = {
8010 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8011 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8012 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8013 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8014 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8015 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
8016 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
8017 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
8018 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8019 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8020 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8021 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8022 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8023 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8026 static const struct message WmCtrlVkN_2
[] = {
8027 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8028 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8029 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8030 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8031 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8032 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
8033 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8034 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8035 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8036 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8037 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8038 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8041 static const struct message WmAltVkN
[] = {
8042 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8043 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8044 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8045 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8046 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8047 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
8048 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
8049 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
8050 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
8051 { HCBT_SYSCOMMAND
, hook
},
8052 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8053 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8054 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
8055 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
8056 { WM_INITMENU
, sent
|defwinproc
},
8057 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8058 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
8059 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
8060 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8061 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
8062 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8063 { WM_EXITMENULOOP
, sent
|defwinproc
},
8064 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
8065 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
8066 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8067 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8068 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8069 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8070 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8071 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8074 static const struct message WmAltVkN_2
[] = {
8075 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8076 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8077 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8078 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8079 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8080 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
8081 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8082 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8083 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8084 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8085 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8086 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8089 static const struct message WmCtrlAltVkN
[] = {
8090 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8091 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8092 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8093 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8094 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8095 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8096 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8097 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8098 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
8099 { WM_CHAR
, optional
},
8100 { WM_CHAR
, sent
|optional
},
8101 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8102 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8103 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8104 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8105 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8106 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8107 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8108 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8109 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8112 static const struct message WmCtrlShiftVkN
[] = {
8113 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8114 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8115 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8116 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8117 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8118 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8119 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
8120 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
8121 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
8122 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
8123 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
8124 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
8125 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8126 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8127 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8128 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8129 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8130 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8133 static const struct message WmCtrlAltShiftVkN
[] = {
8134 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
8135 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
8136 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
8137 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8138 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8139 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8140 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
8141 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
8142 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
8143 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
8144 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
8145 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
8146 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
8147 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
8148 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
8149 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
8150 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
8151 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
8152 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8153 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8154 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8155 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
8156 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8157 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
8160 static const struct message WmAltPressRelease
[] = {
8161 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
8162 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
8163 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
8164 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8165 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8166 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8167 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
8168 { HCBT_SYSCOMMAND
, hook
},
8169 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8170 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8171 { WM_INITMENU
, sent
|defwinproc
},
8172 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8173 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8174 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8176 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
8178 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8179 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
8180 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8181 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
8182 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8183 { WM_EXITMENULOOP
, sent
|defwinproc
},
8184 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
8185 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
8186 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
8189 static const struct message WmShiftMouseButton
[] = {
8190 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8191 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8192 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
8193 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
8194 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
8195 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
8196 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
8197 { WM_LBUTTONUP
, wparam
, MK_SHIFT
, 0 },
8198 { WM_LBUTTONUP
, sent
|wparam
, MK_SHIFT
, 0 },
8199 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
8200 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8201 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
8204 static const struct message WmF1Seq
[] = {
8205 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
8206 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
8207 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
8208 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
8209 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
8210 { WM_HELP
, sent
|defwinproc
},
8211 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
8212 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
8213 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
8216 static const struct message WmVkAppsSeq
[] = {
8217 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
8218 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
8219 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
8220 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
8221 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
8222 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
8223 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
8224 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
8227 static const struct message WmVkF10Seq
[] = {
8228 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8229 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
8230 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
8231 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8232 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8233 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8234 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
8235 { HCBT_SYSCOMMAND
, hook
},
8236 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8237 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
8238 { WM_INITMENU
, sent
|defwinproc
},
8239 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8240 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8241 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
8243 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
8245 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8246 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8247 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0, },
8248 { WM_CAPTURECHANGED
, sent
|defwinproc
},
8249 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
8250 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 0 },
8251 { WM_EXITMENULOOP
, sent
|defwinproc
},
8252 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8253 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8254 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8257 static const struct message WmShiftF10Seq
[] = {
8258 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
8259 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
8260 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
8261 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
8262 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
8263 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
8264 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
8265 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
8266 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
8267 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
8268 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
8269 { HCBT_SYSCOMMAND
, hook
},
8270 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8271 { WM_INITMENU
, sent
|defwinproc
},
8272 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
8273 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
8274 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
8275 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8276 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
8277 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
8278 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
8279 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
8280 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
8284 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
8288 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
8290 struct recvd_message log_msg
;
8292 /* ignore some unwanted messages */
8293 if (msg
.message
== WM_MOUSEMOVE
||
8294 msg
.message
== WM_TIMER
||
8295 ignore_message( msg
.message
))
8298 log_msg
.hwnd
= msg
.hwnd
;
8299 log_msg
.message
= msg
.message
;
8300 log_msg
.flags
= wparam
|lparam
;
8301 log_msg
.wParam
= msg
.wParam
;
8302 log_msg
.lParam
= msg
.lParam
;
8303 log_msg
.descr
= "accel";
8304 add_message(&log_msg
);
8306 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
8308 TranslateMessage(&msg
);
8309 DispatchMessageA(&msg
);
8314 static void test_accelerators(void)
8320 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8321 100, 100, 200, 200, 0, 0, 0, NULL
);
8330 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
8332 state
= GetKeyState(VK_SHIFT
);
8333 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
8334 state
= GetKeyState(VK_CAPITAL
);
8335 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
8337 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
8338 assert(hAccel
!= 0);
8341 pump_msg_loop(hwnd
, 0);
8344 trace("testing VK_N press/release\n");
8346 keybd_event('N', 0, 0, 0);
8347 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8348 pump_msg_loop(hwnd
, hAccel
);
8349 if (!sequence_cnt
) /* we didn't get any message */
8351 skip( "queuing key events not supported\n" );
8354 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
8356 trace("testing Shift+VK_N press/release\n");
8358 keybd_event(VK_SHIFT
, 0, 0, 0);
8359 keybd_event('N', 0, 0, 0);
8360 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8361 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8362 pump_msg_loop(hwnd
, hAccel
);
8363 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
8365 trace("testing Ctrl+VK_N press/release\n");
8367 keybd_event(VK_CONTROL
, 0, 0, 0);
8368 keybd_event('N', 0, 0, 0);
8369 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8370 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8371 pump_msg_loop(hwnd
, hAccel
);
8372 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
8374 trace("testing Alt+VK_N press/release\n");
8376 keybd_event(VK_MENU
, 0, 0, 0);
8377 keybd_event('N', 0, 0, 0);
8378 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8379 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8380 pump_msg_loop(hwnd
, hAccel
);
8381 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
8383 trace("testing Ctrl+Alt+VK_N press/release 1\n");
8385 keybd_event(VK_CONTROL
, 0, 0, 0);
8386 keybd_event(VK_MENU
, 0, 0, 0);
8387 keybd_event('N', 0, 0, 0);
8388 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8389 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8390 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8391 pump_msg_loop(hwnd
, hAccel
);
8392 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
8394 ret
= DestroyAcceleratorTable(hAccel
);
8395 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
8397 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
8398 assert(hAccel
!= 0);
8400 trace("testing VK_N press/release\n");
8402 keybd_event('N', 0, 0, 0);
8403 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8404 pump_msg_loop(hwnd
, hAccel
);
8405 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
8407 trace("testing Shift+VK_N press/release\n");
8409 keybd_event(VK_SHIFT
, 0, 0, 0);
8410 keybd_event('N', 0, 0, 0);
8411 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8412 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8413 pump_msg_loop(hwnd
, hAccel
);
8414 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
8416 trace("testing Ctrl+VK_N press/release 2\n");
8418 keybd_event(VK_CONTROL
, 0, 0, 0);
8419 keybd_event('N', 0, 0, 0);
8420 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8421 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8422 pump_msg_loop(hwnd
, hAccel
);
8423 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
8425 trace("testing Alt+VK_N press/release 2\n");
8427 keybd_event(VK_MENU
, 0, 0, 0);
8428 keybd_event('N', 0, 0, 0);
8429 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8430 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8431 pump_msg_loop(hwnd
, hAccel
);
8432 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
8434 trace("testing Ctrl+Alt+VK_N press/release 2\n");
8436 keybd_event(VK_CONTROL
, 0, 0, 0);
8437 keybd_event(VK_MENU
, 0, 0, 0);
8438 keybd_event('N', 0, 0, 0);
8439 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8440 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8441 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8442 pump_msg_loop(hwnd
, hAccel
);
8443 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
8445 trace("testing Ctrl+Shift+VK_N press/release\n");
8447 keybd_event(VK_CONTROL
, 0, 0, 0);
8448 keybd_event(VK_SHIFT
, 0, 0, 0);
8449 keybd_event('N', 0, 0, 0);
8450 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8451 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8452 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8453 pump_msg_loop(hwnd
, hAccel
);
8454 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
8456 trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
8458 keybd_event(VK_CONTROL
, 0, 0, 0);
8459 keybd_event(VK_MENU
, 0, 0, 0);
8460 keybd_event(VK_SHIFT
, 0, 0, 0);
8461 keybd_event('N', 0, 0, 0);
8462 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
8463 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8464 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8465 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
8466 pump_msg_loop(hwnd
, hAccel
);
8467 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
8469 ret
= DestroyAcceleratorTable(hAccel
);
8470 ok( ret
, "DestroyAcceleratorTable error %d\n", GetLastError());
8473 trace("testing Alt press/release\n");
8475 keybd_event(VK_MENU
, 0, 0, 0);
8476 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8477 keybd_event(VK_MENU
, 0, 0, 0);
8478 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
8479 pump_msg_loop(hwnd
, 0);
8480 /* this test doesn't pass in Wine for managed windows */
8481 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
8483 trace("testing VK_F1 press/release\n");
8484 keybd_event(VK_F1
, 0, 0, 0);
8485 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
8486 pump_msg_loop(hwnd
, 0);
8487 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
8489 trace("testing VK_APPS press/release\n");
8490 keybd_event(VK_APPS
, 0, 0, 0);
8491 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
8492 pump_msg_loop(hwnd
, 0);
8493 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
8495 trace("testing VK_F10 press/release\n");
8496 keybd_event(VK_F10
, 0, 0, 0);
8497 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
8498 keybd_event(VK_F10
, 0, 0, 0);
8499 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
8500 pump_msg_loop(hwnd
, 0);
8501 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", TRUE
);
8503 trace("testing SHIFT+F10 press/release\n");
8504 keybd_event(VK_SHIFT
, 0, 0, 0);
8505 keybd_event(VK_F10
, 0, 0, 0);
8506 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
8507 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8508 keybd_event(VK_ESCAPE
, 0, 0, 0);
8509 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
8510 pump_msg_loop(hwnd
, 0);
8511 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
8513 trace("testing Shift+MouseButton press/release\n");
8514 /* first, move mouse pointer inside of the window client area */
8515 GetClientRect(hwnd
, &rc
);
8516 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
8517 rc
.left
+= (rc
.right
- rc
.left
)/2;
8518 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
8519 SetCursorPos(rc
.left
, rc
.top
);
8520 SetActiveWindow(hwnd
);
8525 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
8528 keybd_event(VK_SHIFT
, 0, 0, 0);
8529 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
8530 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
8531 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
8532 pump_msg_loop(hwnd
, 0);
8533 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
8534 if (i
< sequence_cnt
)
8535 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
8537 skip( "Shift+MouseButton event didn't get to the window\n" );
8541 if (hAccel
) DestroyAcceleratorTable(hAccel
);
8542 DestroyWindow(hwnd
);
8545 /************* window procedures ********************/
8547 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
8548 WPARAM wParam
, LPARAM lParam
)
8550 static LONG defwndproc_counter
= 0;
8551 static LONG beginpaint_counter
= 0;
8553 struct recvd_message msg
;
8555 if (ignore_message( message
)) return 0;
8561 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
8562 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
8563 "wrong WS_DISABLED state: %ld != %d\n", wParam
, !(style
& WS_DISABLED
));
8567 case WM_CAPTURECHANGED
:
8568 if (test_DestroyWindow_flag
)
8570 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
8571 if (style
& WS_CHILD
)
8572 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
8573 else if (style
& WS_POPUP
)
8574 lParam
= WND_POPUP_ID
;
8576 lParam
= WND_PARENT_ID
;
8584 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
8585 capture
= GetCapture();
8588 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
8589 trace("current capture %p, releasing...\n", capture
);
8596 ok(pGetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
8597 if (test_DestroyWindow_flag
)
8599 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
8600 if (style
& WS_CHILD
)
8601 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
8602 else if (style
& WS_POPUP
)
8603 lParam
= WND_POPUP_ID
;
8605 lParam
= WND_PARENT_ID
;
8609 /* test_accelerators() depends on this */
8615 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo
;
8616 HANDLE handle
, event
= (HANDLE
)lParam
;
8619 handle
= (void*)0xdeadbeef;
8620 ret
= pGetCurrentActCtx(&handle
);
8621 ok(ret
, "failed to get current context, %u\n", GetLastError());
8622 ok(handle
== 0, "got active context %p\n", handle
);
8624 memset(&basicinfo
, 0xff, sizeof(basicinfo
));
8625 ret
= pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
, handle
, 0, ActivationContextBasicInformation
,
8626 &basicinfo
, sizeof(basicinfo
), NULL
);
8627 ok(ret
, "got %d, error %d\n", ret
, GetLastError());
8628 ok(basicinfo
.hActCtx
== NULL
, "got %p\n", basicinfo
.hActCtx
);
8629 ok(basicinfo
.dwFlags
== 0, "got %x\n", basicinfo
.dwFlags
);
8631 if (event
) SetEvent(event
);
8637 case WM_MOUSEACTIVATE
:
8638 case WM_NCMOUSEMOVE
:
8645 msg
.message
= message
;
8646 msg
.flags
= sent
|wparam
|lparam
;
8647 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
8648 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
8649 msg
.wParam
= wParam
;
8650 msg
.lParam
= lParam
;
8651 msg
.descr
= "MsgCheckProc";
8654 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
8656 HWND parent
= GetParent(hwnd
);
8658 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
8660 GetClientRect(parent
, &rc
);
8661 trace("parent %p client size = (%d x %d)\n", parent
, rc
.right
, rc
.bottom
);
8662 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
8663 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
8664 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
8665 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
8666 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
8667 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
8669 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %d != %d\n",
8670 minmax
->ptMaxSize
.x
, rc
.right
);
8671 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %d != %d\n",
8672 minmax
->ptMaxSize
.y
, rc
.bottom
);
8675 if (message
== WM_PAINT
)
8678 beginpaint_counter
++;
8679 BeginPaint( hwnd
, &ps
);
8680 beginpaint_counter
--;
8681 EndPaint( hwnd
, &ps
);
8685 if (message
== WM_CONTEXTMENU
)
8687 /* don't create context menu */
8691 defwndproc_counter
++;
8692 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
8693 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8694 defwndproc_counter
--;
8699 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8701 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
8704 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8706 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
8709 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8711 static LONG defwndproc_counter
= 0;
8713 struct recvd_message msg
;
8715 if (ignore_message( message
)) return 0;
8719 case WM_QUERYENDSESSION
:
8721 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
8726 msg
.message
= message
;
8727 msg
.flags
= sent
|wparam
|lparam
;
8728 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
8729 msg
.wParam
= wParam
;
8730 msg
.lParam
= lParam
;
8731 msg
.descr
= "popup";
8734 if (message
== WM_CREATE
)
8736 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
8737 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
8740 defwndproc_counter
++;
8741 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8742 defwndproc_counter
--;
8747 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8749 static LONG defwndproc_counter
= 0;
8750 static LONG beginpaint_counter
= 0;
8752 struct recvd_message msg
;
8754 if (ignore_message( message
)) return 0;
8756 if (log_all_parent_messages
||
8757 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
8758 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
8759 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
8760 message
== WM_DRAWITEM
|| message
== WM_COMMAND
||
8761 message
== WM_IME_SETCONTEXT
)
8770 case WM_NCMOUSEMOVE
:
8776 INT ret
= GetClipBox((HDC
)wParam
, &rc
);
8778 trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret
, wine_dbgstr_rect(&rc
));
8784 msg
.message
= message
;
8785 msg
.flags
= sent
|parent
|wparam
|lparam
;
8786 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
8787 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
8788 msg
.wParam
= wParam
;
8789 msg
.lParam
= lParam
;
8790 msg
.descr
= "parent";
8794 if (message
== WM_PAINT
)
8797 beginpaint_counter
++;
8798 BeginPaint( hwnd
, &ps
);
8799 beginpaint_counter
--;
8800 EndPaint( hwnd
, &ps
);
8804 defwndproc_counter
++;
8805 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8806 defwndproc_counter
--;
8811 static INT_PTR CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
8813 if (message
== WM_CREATE
)
8814 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
8815 else if (message
== WM_CLOSE
)
8817 /* Only the first WM_QUIT will survive the window destruction */
8818 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
8819 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
8820 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
8823 return DefWindowProcA(hwnd
, message
, wp
, lp
);
8826 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8828 static LONG defwndproc_counter
= 0;
8830 struct recvd_message msg
;
8832 if (ignore_message( message
)) return 0;
8836 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
8837 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
8838 if (after_end_dialog
)
8839 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret
);
8841 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret
);
8845 msg
.message
= message
;
8846 msg
.flags
= sent
|wparam
|lparam
;
8847 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
8848 msg
.wParam
= wParam
;
8849 msg
.lParam
= lParam
;
8850 msg
.descr
= "dialog";
8853 defwndproc_counter
++;
8854 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
8855 defwndproc_counter
--;
8860 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8862 static LONG defwndproc_counter
= 0;
8864 struct recvd_message msg
;
8866 /* log only specific messages we are interested in */
8869 #if 0 /* probably log these as well */
8877 case WM_GETMINMAXINFO
:
8878 case WM_WINDOWPOSCHANGING
:
8879 case WM_WINDOWPOSCHANGED
:
8882 default: /* ignore */
8883 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
8884 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8888 msg
.message
= message
;
8889 msg
.flags
= sent
|wparam
|lparam
;
8890 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
8891 msg
.wParam
= wParam
;
8892 msg
.lParam
= lParam
;
8896 defwndproc_counter
++;
8897 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8898 defwndproc_counter
--;
8903 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
8907 case WM_CREATE
: return 0;
8916 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
8918 TranslateMessage(&msg2
);
8919 DispatchMessageA(&msg2
);
8923 else ok(broken(1), "infinite loop\n");
8925 paint_loop_done
= TRUE
;
8926 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
8929 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
8932 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8934 static LONG defwndproc_counter
= 0;
8936 struct recvd_message msg
;
8939 if (ignore_message( message
)) return 0;
8941 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
8942 message
== WM_HOTKEY
|| message
>= WM_APP
)
8945 msg
.message
= message
;
8946 msg
.flags
= sent
|wparam
|lparam
;
8947 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
8948 msg
.wParam
= wParam
;
8949 msg
.lParam
= lParam
;
8950 msg
.descr
= "HotkeyMsgCheckProcA";
8954 defwndproc_counter
++;
8955 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8956 defwndproc_counter
--;
8958 if (message
== WM_APP
)
8960 queue_status
= GetQueueStatus(QS_HOTKEY
);
8961 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
8962 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
8963 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
8964 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
8966 else if (message
== WM_APP
+1)
8968 queue_status
= GetQueueStatus(QS_HOTKEY
);
8969 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
8975 static BOOL
RegisterWindowClasses(void)
8981 cls
.lpfnWndProc
= MsgCheckProcA
;
8984 cls
.hInstance
= GetModuleHandleA(0);
8986 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
8987 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
8988 cls
.lpszMenuName
= NULL
;
8989 cls
.lpszClassName
= "TestWindowClass";
8990 if(!RegisterClassA(&cls
)) return FALSE
;
8992 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
8993 cls
.lpszClassName
= "HotkeyWindowClass";
8994 if(!RegisterClassA(&cls
)) return FALSE
;
8996 cls
.lpfnWndProc
= ShowWindowProcA
;
8997 cls
.lpszClassName
= "ShowWindowClass";
8998 if(!RegisterClassA(&cls
)) return FALSE
;
9000 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
9001 cls
.lpszClassName
= "TestPopupClass";
9002 if(!RegisterClassA(&cls
)) return FALSE
;
9004 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
9005 cls
.lpszClassName
= "TestParentClass";
9006 if(!RegisterClassA(&cls
)) return FALSE
;
9008 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
9009 cls
.lpszClassName
= "StopQuitClass";
9010 if(!RegisterClassA(&cls
)) return FALSE
;
9012 cls
.lpfnWndProc
= DefWindowProcA
;
9013 cls
.lpszClassName
= "SimpleWindowClass";
9014 if(!RegisterClassA(&cls
)) return FALSE
;
9016 cls
.lpfnWndProc
= PaintLoopProcA
;
9017 cls
.lpszClassName
= "PaintLoopWindowClass";
9018 if(!RegisterClassA(&cls
)) return FALSE
;
9020 cls
.style
= CS_NOCLOSE
;
9021 cls
.lpszClassName
= "NoCloseWindowClass";
9022 if(!RegisterClassA(&cls
)) return FALSE
;
9024 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
9026 cls
.hInstance
= GetModuleHandleA(0);
9027 cls
.hbrBackground
= 0;
9028 cls
.lpfnWndProc
= TestDlgProcA
;
9029 cls
.lpszClassName
= "TestDialogClass";
9030 if(!RegisterClassA(&cls
)) return FALSE
;
9033 clsW
.lpfnWndProc
= MsgCheckProcW
;
9034 clsW
.cbClsExtra
= 0;
9035 clsW
.cbWndExtra
= 0;
9036 clsW
.hInstance
= GetModuleHandleW(0);
9038 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
9039 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
9040 clsW
.lpszMenuName
= NULL
;
9041 clsW
.lpszClassName
= testWindowClassW
;
9042 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
9047 static BOOL
is_our_logged_class(HWND hwnd
)
9051 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
9053 if (!lstrcmpiA(buf
, "TestWindowClass") ||
9054 !lstrcmpiA(buf
, "ShowWindowClass") ||
9055 !lstrcmpiA(buf
, "TestParentClass") ||
9056 !lstrcmpiA(buf
, "TestPopupClass") ||
9057 !lstrcmpiA(buf
, "SimpleWindowClass") ||
9058 !lstrcmpiA(buf
, "TestDialogClass") ||
9059 !lstrcmpiA(buf
, "MDI_frame_class") ||
9060 !lstrcmpiA(buf
, "MDI_client_class") ||
9061 !lstrcmpiA(buf
, "MDI_child_class") ||
9062 !lstrcmpiA(buf
, "my_button_class") ||
9063 !lstrcmpiA(buf
, "my_edit_class") ||
9064 !lstrcmpiA(buf
, "static") ||
9065 !lstrcmpiA(buf
, "ListBox") ||
9066 !lstrcmpiA(buf
, "ComboBox") ||
9067 !lstrcmpiA(buf
, "MyDialogClass") ||
9068 !lstrcmpiA(buf
, "#32770") ||
9069 !lstrcmpiA(buf
, "#32768"))
9075 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
9079 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
9081 if (nCode
== HCBT_CLICKSKIPPED
)
9083 /* ignore this event, XP sends it a lot when switching focus between windows */
9084 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9087 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
9089 struct recvd_message msg
;
9092 msg
.message
= nCode
;
9093 msg
.flags
= hook
|wparam
|lparam
;
9094 msg
.wParam
= wParam
;
9095 msg
.lParam
= lParam
;
9099 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9102 if (nCode
== HCBT_DESTROYWND
)
9104 if (test_DestroyWindow_flag
)
9106 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
9107 if (style
& WS_CHILD
)
9108 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
9109 else if (style
& WS_POPUP
)
9110 lParam
= WND_POPUP_ID
;
9112 lParam
= WND_PARENT_ID
;
9116 /* Log also SetFocus(0) calls */
9117 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
9119 if (is_our_logged_class(hwnd
))
9121 struct recvd_message msg
;
9124 msg
.message
= nCode
;
9125 msg
.flags
= hook
|wparam
|lparam
;
9126 msg
.wParam
= wParam
;
9127 msg
.lParam
= lParam
;
9131 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
9134 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
9142 ok(thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
9144 /* ignore mouse cursor events */
9145 if (object_id
== OBJID_CURSOR
) return;
9147 if (!hwnd
|| is_our_logged_class(hwnd
))
9149 struct recvd_message msg
;
9152 msg
.message
= event
;
9153 msg
.flags
= winevent_hook
|wparam
|lparam
;
9154 msg
.wParam
= object_id
;
9155 msg
.lParam
= child_id
;
9161 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
9162 static const WCHAR wszAnsi
[] = {'U',0};
9164 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
9168 case CB_FINDSTRINGEXACT
:
9169 trace("String: %p\n", (LPCWSTR
)lParam
);
9170 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
9172 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
9176 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
9179 static const struct message WmGetTextLengthAfromW
[] = {
9180 { WM_GETTEXTLENGTH
, sent
},
9181 { WM_GETTEXT
, sent
|optional
},
9185 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
9187 /* dummy window proc for WM_GETTEXTLENGTH test */
9188 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
9192 case WM_GETTEXTLENGTH
:
9193 return lstrlenW(dummy_window_text
) + 37; /* some random length */
9195 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
9196 return lstrlenW( (LPWSTR
)lp
);
9198 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
9202 static void test_message_conversion(void)
9204 static const WCHAR wszMsgConversionClass
[] =
9205 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
9209 WNDPROC wndproc
, newproc
;
9213 cls
.lpfnWndProc
= MsgConversionProcW
;
9216 cls
.hInstance
= GetModuleHandleW(NULL
);
9218 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
9219 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
9220 cls
.lpszMenuName
= NULL
;
9221 cls
.lpszClassName
= wszMsgConversionClass
;
9222 /* this call will fail on Win9x, but that doesn't matter as this test is
9223 * meaningless on those platforms */
9224 if(!RegisterClassW(&cls
)) return;
9226 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
9227 100, 100, 200, 200, 0, 0, 0, NULL
);
9228 ok(hwnd
!= NULL
, "Window creation failed\n");
9232 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
9233 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9234 ok(lRes
== 0, "String should have been converted\n");
9235 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9236 ok(lRes
== 1, "String shouldn't have been converted\n");
9240 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
9241 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9242 ok(lRes
== 1, "String shouldn't have been converted\n");
9243 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9244 ok(lRes
== 1, "String shouldn't have been converted\n");
9246 /* Synchronous messages */
9248 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9249 ok(lRes
== 0, "String should have been converted\n");
9250 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9251 ok(lRes
== 1, "String shouldn't have been converted\n");
9253 /* Asynchronous messages */
9256 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9257 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9258 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9260 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9261 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9262 "PostMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9264 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9265 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9266 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9268 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9269 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9270 "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9272 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9273 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9274 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9276 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
9277 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9278 "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9280 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
9281 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9282 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9284 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
9285 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
9286 "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes
, GetLastError());
9288 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
9290 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
9291 WS_OVERLAPPEDWINDOW
,
9292 100, 100, 200, 200, 0, 0, 0, NULL
);
9295 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
9296 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
9297 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
9298 "got bad length %ld\n", lRes
);
9301 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
9302 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
9303 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
9304 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
9305 "got bad length %ld\n", lRes
);
9307 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
9308 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
9309 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
9310 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
9311 NULL
, 0, NULL
, NULL
) ||
9312 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
9313 "got bad length %ld\n", lRes
);
9315 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
9316 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
9317 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
9318 NULL
, 0, NULL
, NULL
) ||
9319 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
9320 "got bad length %ld\n", lRes
);
9322 ret
= DestroyWindow(hwnd
);
9323 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
9333 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
9337 #define TIMER_ID 0x19
9338 #define TIMER_COUNT_EXPECTED 100
9339 #define TIMER_COUNT_TOLERANCE 10
9341 static int count
= 0;
9342 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
9347 static DWORD exception
;
9348 static void CALLBACK
callback_exception(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
9351 RaiseException(exception
, 0, 0, NULL
);
9354 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
9356 struct timer_info
*info
= x
;
9359 r
= KillTimer(info
->hWnd
, 0x19);
9360 ok(r
,"KillTimer failed in thread\n");
9361 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
9362 ok(r
,"SetTimer failed in thread\n");
9363 ok(r
==TIMER_ID
,"SetTimer id different\n");
9364 r
= SetEvent(info
->handles
[0]);
9365 ok(r
,"SetEvent failed in thread\n");
9369 static void test_timers(void)
9371 struct timer_info info
;
9376 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
9377 WS_OVERLAPPEDWINDOW
,
9378 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
9381 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
9382 ok(info
.id
, "SetTimer failed\n");
9383 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
9384 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
9385 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
9387 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
9389 WaitForSingleObject(info
.handles
[1], INFINITE
);
9391 CloseHandle(info
.handles
[0]);
9392 CloseHandle(info
.handles
[1]);
9394 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
9396 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
9397 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
9398 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
9399 * ±9 counts (~4 ms) around the expected value.
9402 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
9403 ok(id
!= 0, "did not get id from SetTimer.\n");
9404 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
9405 start
= GetTickCount();
9406 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
9407 DispatchMessageA(&msg
);
9408 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
9409 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
9410 || broken(abs(count
-43) < TIMER_COUNT_TOLERANCE
) /* w2k3, win8 */,
9411 "did not get expected count for minimum timeout (%d != ~%d).\n",
9412 count
, TIMER_COUNT_EXPECTED
);
9413 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
9414 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
9415 if (pSetSystemTimer
)
9420 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
9421 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
9422 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
9423 start
= GetTickCount();
9424 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, info
.hWnd
, 0, 0))
9426 if (msg
.message
== WM_SYSTIMER
)
9428 DispatchMessageA(&msg
);
9430 ok(abs(syscount
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
9431 || broken(abs(syscount
-64) < TIMER_COUNT_TOLERANCE
) /* most common */
9432 || broken(syscount
> 4000 && syscount
< 12000) /* win2k3sp0 */,
9433 "did not get expected count for minimum timeout (%d != ~%d).\n",
9434 syscount
, TIMER_COUNT_EXPECTED
);
9435 todo_wine
ok(count
== 0, "did not get expected count for callback timeout (%d != 0).\n",
9437 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
9440 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
9443 static void test_timers_no_wnd(void)
9445 static UINT_PTR ids
[0xffff];
9452 id
= SetTimer(NULL
, 0, 100, callback_count
);
9453 ok(id
!= 0, "did not get id from SetTimer.\n");
9454 id2
= SetTimer(NULL
, id
, 200, callback_count
);
9455 ok(id2
== id
, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2
, id
);
9457 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9458 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
9460 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9461 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
9462 KillTimer(NULL
, id
);
9464 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9465 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
9467 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
9468 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
9469 * 15.6 ms. Since there is some measurement error between test runs we are allowing for
9470 * ±9 counts (~4 ms) around the expected value.
9473 id
= SetTimer(NULL
, 0, 0, callback_count
);
9474 ok(id
!= 0, "did not get id from SetTimer.\n");
9475 start
= GetTickCount();
9476 while (GetTickCount()-start
< 1001 && GetMessageA(&msg
, NULL
, 0, 0))
9477 DispatchMessageA(&msg
);
9478 ok(abs(count
-TIMER_COUNT_EXPECTED
) < TIMER_COUNT_TOLERANCE
/* xp */
9479 || broken(abs(count
-64) < TIMER_COUNT_TOLERANCE
) /* most common */,
9480 "did not get expected count for minimum timeout (%d != ~%d).\n",
9481 count
, TIMER_COUNT_EXPECTED
);
9482 KillTimer(NULL
, id
);
9483 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
9485 if (pSetCoalescableTimer
)
9488 id
= pSetCoalescableTimer(NULL
, 0, 0, callback_count
, 0);
9489 ok(id
!= 0, "SetCoalescableTimer failed with %u.\n", GetLastError());
9490 start
= GetTickCount();
9491 while (GetTickCount()-start
< 100 && GetMessageA(&msg
, NULL
, 0, 0))
9492 DispatchMessageA(&msg
);
9493 ok(count
> 1, "expected count > 1, got %d.\n", count
);
9494 KillTimer(NULL
, id
);
9497 win_skip("SetCoalescableTimer not available.\n");
9499 /* Check what happens when we're running out of timers */
9500 for (i
=0; i
<sizeof(ids
)/sizeof(ids
[0]); i
++)
9502 SetLastError(0xdeadbeef);
9503 ids
[i
] = SetTimer(NULL
, 0, USER_TIMER_MAXIMUM
, tfunc
);
9506 ok(i
!= sizeof(ids
)/sizeof(ids
[0]), "all timers were created successfully\n");
9507 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES
|| broken(GetLastError()==0xdeadbeef),
9508 "GetLastError() = %d\n", GetLastError());
9509 while (i
> 0) KillTimer(NULL
, ids
[--i
]);
9512 static void test_timers_exception(DWORD code
)
9518 id
= SetTimer(NULL
, 0, 1000, callback_exception
);
9519 ok(id
!= 0, "did not get id from SetTimer.\n");
9521 memset(&msg
, 0, sizeof(msg
));
9522 msg
.message
= WM_TIMER
;
9524 msg
.lParam
= (LPARAM
)callback_exception
;
9527 DispatchMessageA(&msg
);
9528 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
9530 KillTimer(NULL
, id
);
9533 static void test_timers_exceptions(void)
9535 test_timers_exception(EXCEPTION_ACCESS_VIOLATION
);
9536 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT
);
9537 test_timers_exception(EXCEPTION_BREAKPOINT
);
9538 test_timers_exception(EXCEPTION_SINGLE_STEP
);
9539 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED
);
9540 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND
);
9541 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO
);
9542 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT
);
9543 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION
);
9544 test_timers_exception(0xE000BEEF); /* customer exception */
9547 /* Various win events with arbitrary parameters */
9548 static const struct message WmWinEventsSeq
[] = {
9549 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
9550 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
9551 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
9552 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
9553 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
9554 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
9555 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
9556 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
9557 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
9558 /* our win event hook ignores OBJID_CURSOR events */
9559 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
9560 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
9561 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
9562 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
9563 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
9564 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
9565 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
9566 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
9567 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
9568 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
9569 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
9570 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
9571 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
9572 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
9575 static const struct message WmWinEventCaretSeq
[] = {
9576 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
9577 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
9578 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
9579 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
9582 static const struct message WmWinEventCaretSeq_2
[] = {
9583 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
9584 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
9585 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
9588 static const struct message WmWinEventAlertSeq
[] = {
9589 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
9592 static const struct message WmWinEventAlertSeq_2
[] = {
9593 /* create window in the thread proc */
9594 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
9595 /* our test event */
9596 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
9599 static const struct message WmGlobalHookSeq_1
[] = {
9600 /* create window in the thread proc */
9601 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
9602 /* our test events */
9603 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
9604 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
9607 static const struct message WmGlobalHookSeq_2
[] = {
9608 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
9609 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
9610 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
9611 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
9615 static const struct message WmMouseLLHookSeq
[] = {
9616 { WM_MOUSEMOVE
, hook
},
9617 { WM_LBUTTONUP
, hook
},
9618 { WM_MOUSEMOVE
, hook
},
9622 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
9632 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
9634 if (!lstrcmpiA(buf
, "TestWindowClass") ||
9635 !lstrcmpiA(buf
, "static"))
9637 struct recvd_message msg
;
9640 msg
.message
= event
;
9641 msg
.flags
= winevent_hook
|wparam
|lparam
;
9642 msg
.wParam
= object_id
;
9643 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
9644 msg
.descr
= "WEH_2";
9650 static HHOOK hCBT_global_hook
;
9651 static DWORD cbt_global_hook_thread_id
;
9653 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
9658 if (nCode
== HCBT_SYSCOMMAND
)
9660 struct recvd_message msg
;
9663 msg
.message
= nCode
;
9664 msg
.flags
= hook
|wparam
|lparam
;
9665 msg
.wParam
= wParam
;
9666 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
9667 msg
.descr
= "CBT_2";
9670 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
9672 /* WH_MOUSE_LL hook */
9673 if (nCode
== HC_ACTION
)
9675 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
9677 /* we can't test for real mouse events */
9678 if (mhll
->flags
& LLMHF_INJECTED
)
9680 struct recvd_message msg
;
9682 memset (&msg
, 0, sizeof (msg
));
9683 msg
.message
= wParam
;
9685 msg
.descr
= "CBT_2";
9688 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
9691 /* Log also SetFocus(0) calls */
9692 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
9694 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
9696 if (!lstrcmpiA(buf
, "TestWindowClass") ||
9697 !lstrcmpiA(buf
, "static"))
9699 struct recvd_message msg
;
9702 msg
.message
= nCode
;
9703 msg
.flags
= hook
|wparam
|lparam
;
9704 msg
.wParam
= wParam
;
9705 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
9706 msg
.descr
= "CBT_2";
9710 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
9713 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
9717 HANDLE hevent
= *(HANDLE
*)param
;
9719 assert(pNotifyWinEvent
);
9721 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
9723 trace("created thread window %p\n", hwnd
);
9725 *(HWND
*)param
= hwnd
;
9728 /* this event should be received only by our new hook proc,
9729 * an old one does not expect an event from another thread.
9731 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
9734 while (GetMessageA(&msg
, 0, 0, 0))
9736 TranslateMessage(&msg
);
9737 DispatchMessageA(&msg
);
9742 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
9746 HANDLE hevent
= *(HANDLE
*)param
;
9749 /* these events should be received only by our new hook proc,
9750 * an old one does not expect an event from another thread.
9753 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
9755 trace("created thread window %p\n", hwnd
);
9757 *(HWND
*)param
= hwnd
;
9759 /* Windows doesn't like when a thread plays games with the focus,
9760 that leads to all kinds of misbehaviours and failures to activate
9761 a window. So, better keep next lines commented out.
9765 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
9766 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
9770 while (GetMessageA(&msg
, 0, 0, 0))
9772 TranslateMessage(&msg
);
9773 DispatchMessageA(&msg
);
9778 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
9782 HANDLE hevent
= *(HANDLE
*)param
;
9784 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
9786 trace("created thread window %p\n", hwnd
);
9788 *(HWND
*)param
= hwnd
;
9792 /* Windows doesn't like when a thread plays games with the focus,
9793 * that leads to all kinds of misbehaviours and failures to activate
9794 * a window. So, better don't generate a mouse click message below.
9796 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
9797 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
9798 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
9801 while (GetMessageA(&msg
, 0, 0, 0))
9803 TranslateMessage(&msg
);
9804 DispatchMessageA(&msg
);
9809 static void test_winevents(void)
9815 HANDLE hthread
, hevent
;
9817 HWINEVENTHOOK hhook
;
9818 const struct message
*events
= WmWinEventsSeq
;
9820 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
9821 WS_OVERLAPPEDWINDOW
,
9822 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
9826 /****** start of global hook test *************/
9827 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
9828 if (!hCBT_global_hook
)
9830 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
9831 skip( "cannot set global hook\n" );
9835 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
9839 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
9840 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
9842 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9844 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
9847 /* this one should be received only by old hook proc */
9848 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
9849 /* this one should be received only by old hook proc */
9850 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
9852 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
9854 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
9855 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
9857 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
9858 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9859 CloseHandle(hthread
);
9860 CloseHandle(hevent
);
9861 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
9862 /****** end of global hook test *************/
9864 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
9866 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
9874 /* this test doesn't pass under Win9x */
9875 /* win2k ignores events with hwnd == 0 */
9876 SetLastError(0xdeadbeef);
9877 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
9878 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
9879 GetLastError() == 0xdeadbeef, /* Win9x */
9880 "unexpected error %d\n", GetLastError());
9881 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
9884 for (i
= 0; i
< sizeof(WmWinEventsSeq
)/sizeof(WmWinEventsSeq
[0]); i
++)
9885 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
9887 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
9889 /****** start of event filtering test *************/
9890 hhook
= pSetWinEventHook(
9891 EVENT_OBJECT_SHOW
, /* 0x8002 */
9892 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
9893 GetModuleHandleA(0), win_event_global_hook_proc
,
9894 GetCurrentProcessId(), 0,
9895 WINEVENT_INCONTEXT
);
9896 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
9898 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
9902 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
9903 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
9905 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9907 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
9910 /* this one should be received only by old hook proc */
9911 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
9912 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
9913 /* this one should be received only by old hook proc */
9914 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
9916 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
9918 ret
= pUnhookWinEvent(hhook
);
9919 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
9921 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
9922 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9923 CloseHandle(hthread
);
9924 CloseHandle(hevent
);
9925 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
9926 /****** end of event filtering test *************/
9928 /****** start of out of context event test *************/
9929 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
9930 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
9931 WINEVENT_OUTOFCONTEXT
);
9932 ok(hhook
!= 0, "SetWinEventHook error %d\n", GetLastError());
9934 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
9940 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
9941 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
9943 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9945 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
9946 /* process pending winevent messages */
9947 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
9948 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
9951 /* this one should be received only by old hook proc */
9952 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
9953 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
9954 /* this one should be received only by old hook proc */
9955 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
9957 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
9958 /* process pending winevent messages */
9959 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
9960 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
9962 ret
= pUnhookWinEvent(hhook
);
9963 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
9965 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
9966 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
9967 CloseHandle(hthread
);
9968 CloseHandle(hevent
);
9969 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
9970 /****** end of out of context event test *************/
9972 /****** start of MOUSE_LL hook test *************/
9973 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
9974 /* WH_MOUSE_LL is not supported on Win9x platforms */
9975 if (!hCBT_global_hook
)
9977 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
9978 goto skip_mouse_ll_hook_test
;
9981 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
9985 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
9986 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
9988 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
9989 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
9991 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
9994 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
9995 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
9996 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
9998 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
10000 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
10001 ok( ret
, "UnhookWindowsHookEx error %d\n", GetLastError());
10003 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
10004 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10005 CloseHandle(hthread
);
10006 CloseHandle(hevent
);
10007 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
10008 /****** end of MOUSE_LL hook test *************/
10009 skip_mouse_ll_hook_test
:
10011 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10014 static void test_set_hook(void)
10018 HWINEVENTHOOK hwinevent_hook
;
10020 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
10021 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
10022 UnhookWindowsHookEx(hhook
);
10026 /* this test doesn't pass under Win9x: BUG! */
10027 SetLastError(0xdeadbeef);
10028 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
10029 ok(!hhook
, "global hook requires hModule != 0\n");
10030 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %d\n", GetLastError());
10033 SetLastError(0xdeadbeef);
10034 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
10035 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
10036 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
|| /* Win2k */
10037 GetLastError() == 0xdeadbeef, /* Win9x */
10038 "unexpected error %d\n", GetLastError());
10040 SetLastError(0xdeadbeef);
10041 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
10042 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
|| /* Win2k */
10043 GetLastError() == 0xdeadbeef, /* Win9x */
10044 "unexpected error %d\n", GetLastError());
10046 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
10048 /* even process local incontext hooks require hmodule */
10049 SetLastError(0xdeadbeef);
10050 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10051 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
10052 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
10053 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
10054 GetLastError() == 0xdeadbeef, /* Win9x */
10055 "unexpected error %d\n", GetLastError());
10057 /* even thread local incontext hooks require hmodule */
10058 SetLastError(0xdeadbeef);
10059 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10060 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
10061 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
10062 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
|| /* Win2k */
10063 GetLastError() == 0xdeadbeef, /* Win9x */
10064 "unexpected error %d\n", GetLastError());
10068 /* these 3 tests don't pass under Win9x */
10069 SetLastError(0xdeadbeef);
10070 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
10071 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10072 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
10073 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
10075 SetLastError(0xdeadbeef);
10076 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
10077 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10078 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
10079 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %d\n", GetLastError());
10081 SetLastError(0xdeadbeef);
10082 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10083 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
10084 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
10085 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %d\n", GetLastError());
10088 SetLastError(0xdeadbeef);
10089 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
10090 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
10091 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10092 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10093 ret
= pUnhookWinEvent(hwinevent_hook
);
10094 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10097 /* This call succeeds under win2k SP4, but fails under Wine.
10098 Does win2k test/use passed process id? */
10099 SetLastError(0xdeadbeef);
10100 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
10101 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
10102 ok(hwinevent_hook
!= 0, "SetWinEventHook error %d\n", GetLastError());
10103 ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError());
10104 ret
= pUnhookWinEvent(hwinevent_hook
);
10105 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
10108 SetLastError(0xdeadbeef);
10109 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
10110 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
10111 GetLastError() == 0xdeadbeef, /* Win9x */
10112 "unexpected error %d\n", GetLastError());
10115 static HWND hook_hwnd
;
10116 static HHOOK recursive_hook
;
10117 static int hook_depth
, max_hook_depth
;
10119 static LRESULT WINAPI
rec_get_message_hook(int code
, WPARAM w
, LPARAM l
)
10126 if(hook_depth
> max_hook_depth
)
10127 max_hook_depth
= hook_depth
;
10129 b
= PeekMessageW(&msg
, hook_hwnd
, 0, 0, PM_NOREMOVE
);
10130 ok(b
, "PeekMessage failed\n");
10132 res
= CallNextHookEx(recursive_hook
, code
, w
, l
);
10138 static void test_recursive_hook(void)
10143 hook_hwnd
= CreateWindowA("Static", NULL
, WS_POPUP
, 0, 0, 200, 60, NULL
, NULL
, NULL
, NULL
);
10144 ok(hook_hwnd
!= NULL
, "CreateWindow failed\n");
10146 recursive_hook
= SetWindowsHookExW(WH_GETMESSAGE
, rec_get_message_hook
, NULL
, GetCurrentThreadId());
10147 ok(recursive_hook
!= NULL
, "SetWindowsHookEx failed\n");
10149 PostMessageW(hook_hwnd
, WM_USER
, 0, 0);
10150 PostMessageW(hook_hwnd
, WM_USER
+1, 0, 0);
10153 GetMessageW(&msg
, hook_hwnd
, 0, 0);
10154 ok(15 <= max_hook_depth
&& max_hook_depth
< 45, "max_hook_depth = %d\n", max_hook_depth
);
10155 trace("max_hook_depth = %d\n", max_hook_depth
);
10157 b
= UnhookWindowsHookEx(recursive_hook
);
10158 ok(b
, "UnhokWindowsHookEx failed\n");
10160 DestroyWindow(hook_hwnd
);
10163 static const struct message ScrollWindowPaint1
[] = {
10164 { WM_PAINT
, sent
},
10165 { WM_ERASEBKGND
, sent
|beginpaint
},
10166 { WM_GETTEXTLENGTH
, sent
|optional
},
10167 { WM_PAINT
, sent
|optional
},
10168 { WM_NCPAINT
, sent
|beginpaint
|optional
},
10169 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10170 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10171 { WM_GETTEXT
, sent
|beginpaint
|optional
},
10172 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
10173 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
10177 static const struct message ScrollWindowPaint2
[] = {
10178 { WM_PAINT
, sent
},
10182 static void test_scrollwindowex(void)
10185 RECT rect
={0,0,130,130};
10187 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
10188 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
10189 100, 100, 200, 200, 0, 0, 0, NULL
);
10190 ok (hwnd
!= 0, "Failed to create overlapped window\n");
10191 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
10192 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
10193 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
10194 ok (hchild
!= 0, "Failed to create child\n");
10195 UpdateWindow(hwnd
);
10199 /* scroll without the child window */
10200 trace("start scroll\n");
10201 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
10202 SW_ERASE
|SW_INVALIDATE
);
10203 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
10204 trace("end scroll\n");
10207 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
10211 /* Now without the SW_ERASE flag */
10212 trace("start scroll\n");
10213 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
10214 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
10215 trace("end scroll\n");
10218 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
10222 /* now scroll the child window as well */
10223 trace("start scroll\n");
10224 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
10225 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
10226 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
10227 /* windows sometimes a WM_MOVE */
10228 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
10229 trace("end scroll\n");
10232 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
10236 /* now scroll with ScrollWindow() */
10237 trace("start scroll with ScrollWindow\n");
10238 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
10239 trace("end scroll\n");
10242 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
10244 ok(DestroyWindow(hchild
), "failed to destroy window\n");
10245 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
10249 static const struct message destroy_window_with_children
[] = {
10250 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
10251 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10252 { 0x0090, sent
|optional
},
10253 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10254 { 0x0090, sent
|optional
},
10255 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* popup */
10256 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10257 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10258 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
10259 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* parent */
10260 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10261 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
10262 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
10263 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
10264 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
10265 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
10266 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
10267 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
10271 static void test_DestroyWindow(void)
10274 HWND parent
, child1
, child2
, child3
, child4
, test
;
10275 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
10277 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
10278 100, 100, 200, 200, 0, 0, 0, NULL
);
10279 assert(parent
!= 0);
10280 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10281 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
10282 assert(child1
!= 0);
10283 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10284 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
10285 assert(child2
!= 0);
10286 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
10287 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
10288 assert(child3
!= 0);
10289 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
10290 0, 0, 50, 50, parent
, 0, 0, NULL
);
10291 assert(child4
!= 0);
10293 /* test owner/parent of child2 */
10294 test
= GetParent(child2
);
10295 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10296 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
10298 test
= pGetAncestor(child2
, GA_PARENT
);
10299 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10301 test
= GetWindow(child2
, GW_OWNER
);
10302 ok(!test
, "wrong owner %p\n", test
);
10304 test
= SetParent(child2
, parent
);
10305 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
10307 /* test owner/parent of the parent */
10308 test
= GetParent(parent
);
10309 ok(!test
, "wrong parent %p\n", test
);
10310 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
10312 test
= pGetAncestor(parent
, GA_PARENT
);
10313 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10315 test
= GetWindow(parent
, GW_OWNER
);
10316 ok(!test
, "wrong owner %p\n", test
);
10318 /* test owner/parent of child1 */
10319 test
= GetParent(child1
);
10320 ok(test
== parent
, "wrong parent %p\n", test
);
10321 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
10323 test
= pGetAncestor(child1
, GA_PARENT
);
10324 ok(test
== parent
, "wrong parent %p\n", test
);
10326 test
= GetWindow(child1
, GW_OWNER
);
10327 ok(!test
, "wrong owner %p\n", test
);
10329 /* test owner/parent of child2 */
10330 test
= GetParent(child2
);
10331 ok(test
== parent
, "wrong parent %p\n", test
);
10332 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
10334 test
= pGetAncestor(child2
, GA_PARENT
);
10335 ok(test
== parent
, "wrong parent %p\n", test
);
10337 test
= GetWindow(child2
, GW_OWNER
);
10338 ok(!test
, "wrong owner %p\n", test
);
10340 /* test owner/parent of child3 */
10341 test
= GetParent(child3
);
10342 ok(test
== child1
, "wrong parent %p\n", test
);
10343 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
10345 test
= pGetAncestor(child3
, GA_PARENT
);
10346 ok(test
== child1
, "wrong parent %p\n", test
);
10348 test
= GetWindow(child3
, GW_OWNER
);
10349 ok(!test
, "wrong owner %p\n", test
);
10351 /* test owner/parent of child4 */
10352 test
= GetParent(child4
);
10353 ok(test
== parent
, "wrong parent %p\n", test
);
10354 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
10356 test
= pGetAncestor(child4
, GA_PARENT
);
10357 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
10359 test
= GetWindow(child4
, GW_OWNER
);
10360 ok(test
== parent
, "wrong owner %p\n", test
);
10364 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
10365 parent
, child1
, child2
, child3
, child4
);
10367 SetCapture(child4
);
10368 test
= GetCapture();
10369 ok(test
== child4
, "wrong capture window %p\n", test
);
10371 test_DestroyWindow_flag
= TRUE
;
10372 ret
= DestroyWindow(parent
);
10373 ok( ret
, "DestroyWindow() error %d\n", GetLastError());
10374 test_DestroyWindow_flag
= FALSE
;
10375 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
10377 ok(!IsWindow(parent
), "parent still exists\n");
10378 ok(!IsWindow(child1
), "child1 still exists\n");
10379 ok(!IsWindow(child2
), "child2 still exists\n");
10380 ok(!IsWindow(child3
), "child3 still exists\n");
10381 ok(!IsWindow(child4
), "child4 still exists\n");
10383 test
= GetCapture();
10384 ok(!test
, "wrong capture window %p\n", test
);
10388 static const struct message WmDispatchPaint
[] = {
10389 { WM_NCPAINT
, sent
},
10390 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10391 { WM_GETTEXT
, sent
|defwinproc
|optional
},
10392 { WM_ERASEBKGND
, sent
},
10396 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10398 if (message
== WM_PAINT
) return 0;
10399 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
10402 static void test_DispatchMessage(void)
10407 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
10408 100, 100, 200, 200, 0, 0, 0, NULL
);
10409 ShowWindow( hwnd
, SW_SHOW
);
10410 UpdateWindow( hwnd
);
10413 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
10415 SetRect( &rect
, -5, -5, 5, 5 );
10416 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
10418 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
10420 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
10424 DispatchMessageA( &msg
);
10425 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
10426 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
10427 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
10428 if (++count
> 10) break;
10431 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
10433 trace("now without DispatchMessage\n");
10435 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
10437 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
10439 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
10442 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
10444 /* this will send WM_NCCPAINT just like DispatchMessage does */
10445 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
10446 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
10447 DeleteObject( hrgn
);
10448 GetClientRect( hwnd
, &rect
);
10449 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
10450 ok( !count
, "Got multiple WM_PAINTs\n" );
10451 if (++count
> 10) break;
10456 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
10458 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
10460 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
10466 hdc
= BeginPaint( hwnd
, NULL
);
10467 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
10468 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
10469 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
10470 ok( !count
, "Got multiple WM_PAINTs\n" );
10471 if (++count
> 10) break;
10474 DestroyWindow(hwnd
);
10478 static const struct message WmUser
[] = {
10483 struct sendmsg_info
10490 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
10492 struct sendmsg_info
*info
= arg
;
10493 SetLastError( 0xdeadbeef );
10494 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
10495 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
10496 broken(GetLastError() == 0), /* win9x */
10497 "unexpected error %d\n", GetLastError());
10501 static void wait_for_thread( HANDLE thread
)
10503 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
10506 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10510 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10512 if (message
== WM_USER
) Sleep(200);
10513 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
10516 static void test_SendMessageTimeout(void)
10519 struct sendmsg_info info
;
10523 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
10524 100, 100, 200, 200, 0, 0, 0, NULL
);
10528 info
.timeout
= 1000;
10529 info
.ret
= 0xdeadbeef;
10530 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
10531 wait_for_thread( thread
);
10532 CloseHandle( thread
);
10533 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
10534 ok_sequence( WmUser
, "WmUser", FALSE
);
10537 info
.ret
= 0xdeadbeef;
10538 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
10539 Sleep(100); /* SendMessageTimeout should time out here */
10540 wait_for_thread( thread
);
10541 CloseHandle( thread
);
10542 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
10543 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
10545 /* 0 means infinite timeout (but not on win9x) */
10547 info
.ret
= 0xdeadbeef;
10548 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
10550 wait_for_thread( thread
);
10551 CloseHandle( thread
);
10552 is_win9x
= !info
.ret
;
10553 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
10554 else ok_sequence( WmUser
, "WmUser", FALSE
);
10556 /* timeout is treated as signed despite the prototype (but not on win9x) */
10557 info
.timeout
= 0x7fffffff;
10558 info
.ret
= 0xdeadbeef;
10559 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
10561 wait_for_thread( thread
);
10562 CloseHandle( thread
);
10563 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
10564 ok_sequence( WmUser
, "WmUser", FALSE
);
10566 info
.timeout
= 0x80000000;
10567 info
.ret
= 0xdeadbeef;
10568 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
10570 wait_for_thread( thread
);
10571 CloseHandle( thread
);
10574 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
10575 ok_sequence( WmUser
, "WmUser", FALSE
);
10579 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
10580 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
10583 /* now check for timeout during message processing */
10584 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
10585 info
.timeout
= 100;
10586 info
.ret
= 0xdeadbeef;
10587 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
10588 wait_for_thread( thread
);
10589 CloseHandle( thread
);
10590 /* we should time out but still get the message */
10591 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
10592 ok_sequence( WmUser
, "WmUser", FALSE
);
10594 DestroyWindow( info
.hwnd
);
10598 /****************** edit message test *************************/
10599 #define ID_EDIT 0x1234
10600 static const struct message sl_edit_setfocus
[] =
10602 { HCBT_SETFOCUS
, hook
},
10603 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
10604 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
10605 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
10606 { WM_SETFOCUS
, sent
|wparam
, 0 },
10607 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
10608 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
10609 { WM_CTLCOLOREDIT
, sent
|parent
},
10610 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
10611 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10612 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10613 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
10616 static const struct message sl_edit_invisible
[] =
10618 { HCBT_SETFOCUS
, hook
},
10619 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
10620 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
10621 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
10622 { WM_KILLFOCUS
, sent
|parent
},
10623 { WM_SETFOCUS
, sent
},
10624 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
10627 static const struct message ml_edit_setfocus
[] =
10629 { HCBT_SETFOCUS
, hook
},
10630 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
10631 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
10632 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
10633 { WM_SETFOCUS
, sent
|wparam
, 0 },
10634 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
10635 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
10636 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10637 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10638 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
10641 static const struct message sl_edit_killfocus
[] =
10643 { HCBT_SETFOCUS
, hook
},
10644 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
10645 { WM_KILLFOCUS
, sent
|wparam
, 0 },
10646 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10647 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10648 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
10649 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
10650 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
10653 static const struct message sl_edit_lbutton_dblclk
[] =
10655 { WM_LBUTTONDBLCLK
, sent
},
10656 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
10659 static const struct message sl_edit_lbutton_down
[] =
10661 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
10662 { HCBT_SETFOCUS
, hook
},
10663 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
10664 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
10665 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
10666 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
10667 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
10668 { WM_CTLCOLOREDIT
, sent
|parent
},
10669 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
10670 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10671 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10672 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10673 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
10674 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
10675 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10676 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
10677 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
10678 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10679 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10682 static const struct message ml_edit_lbutton_down
[] =
10684 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
10685 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
10686 { HCBT_SETFOCUS
, hook
},
10687 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
10688 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
10689 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
10690 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
10691 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
10692 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
10693 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10694 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10695 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
10698 static const struct message sl_edit_lbutton_up
[] =
10700 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
10701 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10702 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
10703 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10704 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
10707 static const struct message ml_edit_lbutton_up
[] =
10709 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
10710 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
10711 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10715 static WNDPROC old_edit_proc
;
10717 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10719 static LONG defwndproc_counter
= 0;
10721 struct recvd_message msg
;
10723 if (ignore_message( message
)) return 0;
10726 msg
.message
= message
;
10727 msg
.flags
= sent
|wparam
|lparam
;
10728 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10729 msg
.wParam
= wParam
;
10730 msg
.lParam
= lParam
;
10731 msg
.descr
= "edit";
10734 defwndproc_counter
++;
10735 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
10736 defwndproc_counter
--;
10741 static void subclass_edit(void)
10745 if (!GetClassInfoA(0, "edit", &cls
)) assert(0);
10747 old_edit_proc
= cls
.lpfnWndProc
;
10749 cls
.hInstance
= GetModuleHandleA(NULL
);
10750 cls
.lpfnWndProc
= edit_hook_proc
;
10751 cls
.lpszClassName
= "my_edit_class";
10752 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
10753 if (!RegisterClassA(&cls
)) assert(0);
10756 static void test_edit_messages(void)
10762 log_all_parent_messages
++;
10764 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
10765 100, 100, 200, 200, 0, 0, 0, NULL
);
10766 ok (parent
!= 0, "Failed to create parent window\n");
10768 /* test single line edit */
10769 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
10770 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
10771 ok(hwnd
!= 0, "Failed to create edit window\n");
10773 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
10774 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08x\n", dlg_code
);
10778 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
10780 ShowWindow(hwnd
, SW_SHOW
);
10781 UpdateWindow(hwnd
);
10786 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
10789 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
10795 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
10796 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
10802 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
10803 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
10805 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
10806 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
10808 DestroyWindow(hwnd
);
10810 /* test multiline edit */
10811 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
10812 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
10813 ok(hwnd
!= 0, "Failed to create edit window\n");
10815 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
10816 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
10817 "wrong dlg_code %08x\n", dlg_code
);
10819 ShowWindow(hwnd
, SW_SHOW
);
10820 UpdateWindow(hwnd
);
10825 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
10828 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
10834 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
10835 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
10841 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
10842 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
10844 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
10845 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
10847 DestroyWindow(hwnd
);
10848 DestroyWindow(parent
);
10850 log_all_parent_messages
--;
10853 /**************************** End of Edit test ******************************/
10855 static const struct message WmKeyDownSkippedSeq
[] =
10857 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10860 static const struct message WmKeyDownWasDownSkippedSeq
[] =
10862 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
10865 static const struct message WmKeyUpSkippedSeq
[] =
10867 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10870 static const struct message WmUserKeyUpSkippedSeq
[] =
10873 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10878 #define EV_SENDMSG 1
10881 struct peekmsg_info
10884 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
10887 static DWORD CALLBACK
send_msg_thread_2(void *param
)
10890 struct peekmsg_info
*info
= param
;
10892 trace("thread: looping\n");
10893 SetEvent(info
->hevent
[EV_ACK
]);
10897 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
10901 case WAIT_OBJECT_0
+ EV_STOP
:
10902 trace("thread: exiting\n");
10905 case WAIT_OBJECT_0
+ EV_SENDMSG
:
10906 trace("thread: sending message\n");
10907 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
10908 ok(ret
, "SendNotifyMessageA failed error %u\n", GetLastError());
10909 SetEvent(info
->hevent
[EV_ACK
]);
10913 trace("unexpected return: %04x\n", ret
);
10921 static void test_PeekMessage(void)
10925 DWORD tid
, qstatus
;
10926 UINT qs_all_input
= QS_ALLINPUT
;
10927 UINT qs_input
= QS_INPUT
;
10929 struct peekmsg_info info
;
10931 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
10932 100, 100, 200, 200, 0, 0, 0, NULL
);
10934 ShowWindow(info
.hwnd
, SW_SHOW
);
10935 UpdateWindow(info
.hwnd
);
10936 SetFocus(info
.hwnd
);
10938 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
10939 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
10940 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
10942 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
10943 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
10948 SetLastError(0xdeadbeef);
10949 qstatus
= GetQueueStatus(qs_all_input
);
10950 if (GetLastError() == ERROR_INVALID_FLAGS
)
10952 trace("QS_RAWINPUT not supported on this platform\n");
10953 qs_all_input
&= ~QS_RAWINPUT
;
10954 qs_input
&= ~QS_RAWINPUT
;
10956 if (qstatus
& QS_POSTMESSAGE
)
10958 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
10959 qstatus
= GetQueueStatus(qs_all_input
);
10961 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10963 trace("signalling to send message\n");
10964 SetEvent(info
.hevent
[EV_SENDMSG
]);
10965 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
10967 /* pass invalid QS_xxxx flags */
10968 SetLastError(0xdeadbeef);
10969 qstatus
= GetQueueStatus(0xffffffff);
10970 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus
);
10973 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %d\n", GetLastError());
10974 qstatus
= GetQueueStatus(qs_all_input
);
10976 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
10977 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
),
10978 "wrong qstatus %08x\n", qstatus
);
10981 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
10983 "PeekMessageA should have returned FALSE instead of msg %04x\n",
10985 ok_sequence(WmUser
, "WmUser", FALSE
);
10987 qstatus
= GetQueueStatus(qs_all_input
);
10988 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
10990 keybd_event('N', 0, 0, 0);
10991 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10992 qstatus
= GetQueueStatus(qs_all_input
);
10993 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
10995 skip( "queuing key events not supported\n" );
10998 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
10999 /* keybd_event seems to trigger a sent message on NT4 */
11000 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
11001 "wrong qstatus %08x\n", qstatus
);
11003 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11004 qstatus
= GetQueueStatus(qs_all_input
);
11005 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
11006 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
11007 "wrong qstatus %08x\n", qstatus
);
11009 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
11010 qstatus
= GetQueueStatus(qs_all_input
);
11011 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
11012 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
11013 "wrong qstatus %08x\n", qstatus
);
11015 trace("signalling to send message\n");
11016 SetEvent(info
.hevent
[EV_SENDMSG
]);
11017 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11019 qstatus
= GetQueueStatus(qs_all_input
);
11020 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11021 "wrong qstatus %08x\n", qstatus
);
11024 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
11025 if (ret
&& msg
.message
== WM_CHAR
)
11027 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11031 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11033 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
11035 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
11038 ok_sequence(WmUser
, "WmUser", FALSE
);
11040 qstatus
= GetQueueStatus(qs_all_input
);
11041 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11042 "wrong qstatus %08x\n", qstatus
);
11044 trace("signalling to send message\n");
11045 SetEvent(info
.hevent
[EV_SENDMSG
]);
11046 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11048 qstatus
= GetQueueStatus(qs_all_input
);
11049 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11050 "wrong qstatus %08x\n", qstatus
);
11053 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11055 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11057 ok_sequence(WmUser
, "WmUser", FALSE
);
11059 qstatus
= GetQueueStatus(qs_all_input
);
11060 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
11061 "wrong qstatus %08x\n", qstatus
);
11064 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11065 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11066 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11067 ret
, msg
.message
, msg
.wParam
);
11068 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11070 qstatus
= GetQueueStatus(qs_all_input
);
11071 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
11072 "wrong qstatus %08x\n", qstatus
);
11075 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
11077 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11079 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11081 qstatus
= GetQueueStatus(qs_all_input
);
11082 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
11083 "wrong qstatus %08x\n", qstatus
);
11086 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
11087 ok(ret
&& msg
.message
== WM_PAINT
,
11088 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
11089 DispatchMessageA(&msg
);
11090 ok_sequence(WmPaint
, "WmPaint", FALSE
);
11092 qstatus
= GetQueueStatus(qs_all_input
);
11093 ok(qstatus
== MAKELONG(0, QS_KEY
),
11094 "wrong qstatus %08x\n", qstatus
);
11097 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
11099 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11101 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11103 qstatus
= GetQueueStatus(qs_all_input
);
11104 ok(qstatus
== MAKELONG(0, QS_KEY
),
11105 "wrong qstatus %08x\n", qstatus
);
11107 trace("signalling to send message\n");
11108 SetEvent(info
.hevent
[EV_SENDMSG
]);
11109 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11111 qstatus
= GetQueueStatus(qs_all_input
);
11112 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
11113 "wrong qstatus %08x\n", qstatus
);
11115 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11117 qstatus
= GetQueueStatus(qs_all_input
);
11118 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11119 "wrong qstatus %08x\n", qstatus
);
11122 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
11123 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11124 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11125 ret
, msg
.message
, msg
.wParam
);
11126 ok_sequence(WmUser
, "WmUser", FALSE
);
11128 qstatus
= GetQueueStatus(qs_all_input
);
11129 ok(qstatus
== MAKELONG(0, QS_KEY
),
11130 "wrong qstatus %08x\n", qstatus
);
11133 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
11135 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11137 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11139 qstatus
= GetQueueStatus(qs_all_input
);
11140 ok(qstatus
== MAKELONG(0, QS_KEY
),
11141 "wrong qstatus %08x\n", qstatus
);
11143 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11145 qstatus
= GetQueueStatus(qs_all_input
);
11146 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
11147 "wrong qstatus %08x\n", qstatus
);
11149 trace("signalling to send message\n");
11150 SetEvent(info
.hevent
[EV_SENDMSG
]);
11151 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11153 qstatus
= GetQueueStatus(qs_all_input
);
11154 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11155 "wrong qstatus %08x\n", qstatus
);
11158 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
11160 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11162 ok_sequence(WmUser
, "WmUser", FALSE
);
11164 qstatus
= GetQueueStatus(qs_all_input
);
11165 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
11166 "wrong qstatus %08x\n", qstatus
);
11169 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
11170 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
11171 else /* workaround for a missing QS_RAWINPUT support */
11172 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
11173 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11174 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11175 ret
, msg
.message
, msg
.wParam
);
11176 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
11178 qstatus
= GetQueueStatus(qs_all_input
);
11179 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
11180 "wrong qstatus %08x\n", qstatus
);
11183 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
11184 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
11185 else /* workaround for a missing QS_RAWINPUT support */
11186 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
11187 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
11188 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n",
11189 ret
, msg
.message
, msg
.wParam
);
11190 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
11192 qstatus
= GetQueueStatus(qs_all_input
);
11193 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11194 "wrong qstatus %08x\n", qstatus
);
11197 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
11199 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11201 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11203 qstatus
= GetQueueStatus(qs_all_input
);
11204 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11205 "wrong qstatus %08x\n", qstatus
);
11208 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11209 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11210 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11211 ret
, msg
.message
, msg
.wParam
);
11212 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11214 qstatus
= GetQueueStatus(qs_all_input
);
11216 "wrong qstatus %08x\n", qstatus
);
11219 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11221 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11223 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11225 qstatus
= GetQueueStatus(qs_all_input
);
11227 "wrong qstatus %08x\n", qstatus
);
11229 /* test whether presence of the quit flag in the queue affects
11232 PostQuitMessage(0x1234abcd);
11234 qstatus
= GetQueueStatus(qs_all_input
);
11235 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
11236 "wrong qstatus %08x\n", qstatus
);
11238 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
11240 qstatus
= GetQueueStatus(qs_all_input
);
11241 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
11242 "wrong qstatus %08x\n", qstatus
);
11245 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11246 ok(ret
&& msg
.message
== WM_USER
,
11247 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
11248 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11250 qstatus
= GetQueueStatus(qs_all_input
);
11251 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11252 "wrong qstatus %08x\n", qstatus
);
11255 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11256 ok(ret
&& msg
.message
== WM_QUIT
,
11257 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
11258 ok(msg
.wParam
== 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg
.wParam
);
11259 ok(msg
.lParam
== 0, "got lParam %08lx instead of 0\n", msg
.lParam
);
11260 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11262 qstatus
= GetQueueStatus(qs_all_input
);
11264 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
11265 "wrong qstatus %08x\n", qstatus
);
11269 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
11271 "PeekMessageA should have returned FALSE instead of msg %04x\n",
11273 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
11275 qstatus
= GetQueueStatus(qs_all_input
);
11277 "wrong qstatus %08x\n", qstatus
);
11279 /* some GetMessage tests */
11281 keybd_event('N', 0, 0, 0);
11282 qstatus
= GetQueueStatus(qs_all_input
);
11283 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11285 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11286 qstatus
= GetQueueStatus(qs_all_input
);
11287 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11291 ret
= GetMessageA( &msg
, 0, 0, 0 );
11292 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11293 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11294 ret
, msg
.message
, msg
.wParam
);
11295 qstatus
= GetQueueStatus(qs_all_input
);
11296 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11301 ret
= GetMessageA( &msg
, 0, 0, 0 );
11302 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11303 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11304 ret
, msg
.message
, msg
.wParam
);
11305 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
11306 qstatus
= GetQueueStatus(qs_all_input
);
11307 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11310 keybd_event('N', 0, 0, 0);
11311 qstatus
= GetQueueStatus(qs_all_input
);
11312 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11314 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11315 qstatus
= GetQueueStatus(qs_all_input
);
11316 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11318 if (qstatus
& (QS_KEY
<< 16))
11320 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
11321 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
11322 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11323 ret
, msg
.message
, msg
.wParam
);
11324 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
11325 qstatus
= GetQueueStatus(qs_all_input
);
11326 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
11331 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
11332 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11333 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11334 ret
, msg
.message
, msg
.wParam
);
11335 qstatus
= GetQueueStatus(qs_all_input
);
11336 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11339 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
11340 qstatus
= GetQueueStatus(qs_all_input
);
11341 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11343 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
11344 qstatus
= GetQueueStatus(qs_all_input
);
11345 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08x\n", qstatus
);
11347 trace("signalling to send message\n");
11348 SetEvent(info
.hevent
[EV_SENDMSG
]);
11349 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
11350 qstatus
= GetQueueStatus(qs_all_input
);
11351 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
11352 "wrong qstatus %08x\n", qstatus
);
11354 if (qstatus
& (QS_KEY
<< 16))
11356 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
11357 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
11358 "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n",
11359 ret
, msg
.message
, msg
.wParam
);
11360 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
11361 qstatus
= GetQueueStatus(qs_all_input
);
11362 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08x\n", qstatus
);
11367 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
11368 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
11369 "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n",
11370 ret
, msg
.message
, msg
.wParam
);
11371 qstatus
= GetQueueStatus(qs_all_input
);
11372 ok(qstatus
== 0, "wrong qstatus %08x\n", qstatus
);
11375 trace("signalling to exit\n");
11376 SetEvent(info
.hevent
[EV_STOP
]);
11378 WaitForSingleObject(hthread
, INFINITE
);
11380 CloseHandle(hthread
);
11381 CloseHandle(info
.hevent
[0]);
11382 CloseHandle(info
.hevent
[1]);
11383 CloseHandle(info
.hevent
[2]);
11385 DestroyWindow(info
.hwnd
);
11388 static void wait_move_event(HWND hwnd
, int x
, int y
)
11394 time
= GetTickCount();
11395 while (GetTickCount() - time
< 200) {
11396 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
11397 if (ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
) break;
11398 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, GetTickCount() - time
, QS_ALLINPUT
);
11399 else Sleep( GetTickCount() - time
);
11404 static void test_PeekMessage2(void)
11410 DWORD time1
, time2
, time3
;
11411 int x1
, y1
, x2
, y2
, x3
, y3
;
11414 time1
= time2
= time3
= 0;
11415 x1
= y1
= x2
= y2
= x3
= y3
= 0;
11417 /* Initialise window and make sure it is ready for events */
11418 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
11419 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
11421 trace("Window for test_PeekMessage2 %p\n", hwnd
);
11422 ShowWindow(hwnd
, SW_SHOW
);
11423 UpdateWindow(hwnd
);
11425 GetCursorPos(&pos
);
11426 SetCursorPos(100, 100);
11427 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
11430 /* Do initial mousemove, wait until we can see it
11431 and then do our test peek with PM_NOREMOVE. */
11432 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
11433 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
11435 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
11438 skip( "queuing mouse events not supported\n" );
11443 trace("1st move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
11444 message
= msg
.message
;
11448 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
11451 /* Allow time to advance a bit, and then simulate the user moving their
11452 * mouse around. After that we peek again with PM_NOREMOVE.
11453 * Although the previous mousemove message was never removed, the
11454 * mousemove we now peek should reflect the recent mouse movements
11455 * because the input queue will merge the move events. */
11457 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
11458 wait_move_event(hwnd
, x1
, y1
);
11460 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
11461 ok(ret
, "no message available\n");
11463 trace("2nd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
11464 message
= msg
.message
;
11468 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
11469 ok(time2
> time1
, "message time not advanced: %x %x\n", time1
, time2
);
11470 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
11473 /* Have another go, to drive the point home */
11475 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
11476 wait_move_event(hwnd
, x2
, y2
);
11478 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
11479 ok(ret
, "no message available\n");
11481 trace("3rd move event: %04x %x %d %d\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
11482 message
= msg
.message
;
11486 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
11487 ok(time3
> time2
, "message time not advanced: %x %x\n", time2
, time3
);
11488 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
11492 DestroyWindow(hwnd
);
11493 SetCursorPos(pos
.x
, pos
.y
);
11497 static void test_PeekMessage3(void)
11503 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW
,
11504 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
11505 ok(hwnd
!= NULL
, "expected hwnd != NULL\n");
11508 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
11509 * were already seen. */
11511 SetTimer(hwnd
, 1, 0, NULL
);
11512 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
11513 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11514 PostMessageA(hwnd
, WM_USER
, 0, 0);
11515 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
11517 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11518 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11520 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11521 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11523 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
11524 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
11525 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
11527 SetTimer(hwnd
, 1, 0, NULL
);
11528 while (!PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
));
11529 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11530 PostMessageA(hwnd
, WM_USER
, 0, 0);
11531 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
11533 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11534 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
11536 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
11537 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
11538 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
11540 /* It doesn't matter if a message range is specified or not. */
11542 SetTimer(hwnd
, 1, 0, NULL
);
11543 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
11544 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11545 PostMessageA(hwnd
, WM_USER
, 0, 0);
11546 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11548 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11549 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11551 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
11552 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
11553 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
11555 /* But not if the post messages were added before the PeekMessage() call. */
11557 PostMessageA(hwnd
, WM_USER
, 0, 0);
11558 SetTimer(hwnd
, 1, 0, NULL
);
11559 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
11560 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11561 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11562 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
11563 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11564 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11565 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
11566 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
11568 /* More complicated test with multiple messages. */
11570 PostMessageA(hwnd
, WM_USER
, 0, 0);
11571 SetTimer(hwnd
, 1, 0, NULL
);
11572 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
11573 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11574 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
11575 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11576 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
11577 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11579 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11580 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11582 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
11583 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
11584 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
11586 /* Also works for posted messages, but the situation is a bit different,
11587 * because both messages are in the same queue. */
11589 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
11590 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
11591 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11592 PostMessageA(hwnd
, WM_USER
, 0, 0);
11593 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11594 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11595 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11596 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
11597 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
11598 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
11600 PostMessageA(hwnd
, WM_USER
, 0, 0);
11601 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
11602 while (!PeekMessageA(&msg
, NULL
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
11603 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11604 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11605 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
11606 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11607 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
11608 ret
= PeekMessageA(&msg
, NULL
, 0, 0, 0);
11609 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
11611 DestroyWindow(hwnd
);
11615 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
11617 struct recvd_message msg
;
11619 if (ignore_message( message
)) return 0;
11622 msg
.message
= message
;
11623 msg
.flags
= sent
|wparam
|lparam
;
11626 msg
.descr
= "dialog";
11631 case WM_INITDIALOG
:
11632 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
11633 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
11636 case WM_GETDLGCODE
:
11640 EndDialog(hwnd
, 0);
11647 static const struct message WmQuitDialogSeq
[] = {
11648 { HCBT_CREATEWND
, hook
},
11649 { WM_SETFONT
, sent
},
11650 { WM_INITDIALOG
, sent
},
11651 { WM_CHANGEUISTATE
, sent
|optional
},
11652 { HCBT_DESTROYWND
, hook
},
11653 { 0x0090, sent
|optional
}, /* Vista */
11654 { WM_DESTROY
, sent
},
11655 { WM_NCDESTROY
, sent
},
11659 static const struct message WmStopQuitSeq
[] = {
11660 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
11661 { WM_CLOSE
, posted
},
11662 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
11666 static void test_quit_message(void)
11671 /* test using PostQuitMessage */
11673 PostQuitMessage(0xbeef);
11676 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_QS_SENDMESSAGE
);
11677 ok(!ret
, "got %x message\n", msg
.message
);
11679 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
11680 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
11681 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
11682 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
11684 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
11685 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
11687 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11688 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
11689 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
11691 /* note: WM_QUIT message received after WM_USER message */
11692 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11693 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
11694 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
11695 ok(msg
.wParam
== 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg
.wParam
);
11697 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
11698 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
11700 /* now test with PostThreadMessage - different behaviour! */
11701 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
11703 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
11704 ok(ret
, "PeekMessage failed with error %d\n", GetLastError());
11705 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
11706 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
11708 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
11709 ok(ret
, "PostMessage failed with error %d\n", GetLastError());
11711 /* note: we receive the WM_QUIT message first this time */
11712 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11713 ok(!ret
, "GetMessage return %d with error %d instead of FALSE\n", ret
, GetLastError());
11714 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
11715 ok(msg
.wParam
== 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg
.wParam
);
11717 ret
= GetMessageA(&msg
, NULL
, 0, 0);
11718 ok(ret
> 0, "GetMessage failed with error %d\n", GetLastError());
11719 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
11723 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
11724 ok(ret
== 1, "expected 1, got %d\n", ret
);
11725 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
11726 memset(&msg
, 0xab, sizeof(msg
));
11727 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
11728 ok(ret
, "PeekMessage failed\n");
11729 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
11730 ok(msg
.wParam
== 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg
.wParam
);
11731 ok(msg
.lParam
== 0, "lParam was 0x%lx instead of 0\n", msg
.lParam
);
11733 /* Check what happens to a WM_QUIT message posted to a window that gets
11736 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
11737 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
11739 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
11741 struct recvd_message rmsg
;
11742 rmsg
.hwnd
= msg
.hwnd
;
11743 rmsg
.message
= msg
.message
;
11744 rmsg
.flags
= posted
|wparam
|lparam
;
11745 rmsg
.wParam
= msg
.wParam
;
11746 rmsg
.lParam
= msg
.lParam
;
11747 rmsg
.descr
= "stop/quit";
11748 if (msg
.message
== WM_QUIT
)
11749 /* The hwnd can only be checked here */
11750 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
11751 add_message(&rmsg
);
11752 DispatchMessageA(&msg
);
11754 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
11757 static const struct message WmNotifySeq
[] = {
11758 { WM_NOTIFY
, sent
|wparam
|lparam
, 0x1234, 0xdeadbeef },
11762 static void test_notify_message(void)
11768 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
11769 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0, NULL
, NULL
, 0);
11770 ok(hwnd
!= 0, "Failed to create window\n");
11774 ret
= SendNotifyMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
11775 ok(ret
== TRUE
, "SendNotifyMessageA failed with error %u\n", GetLastError());
11776 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11778 ret
= SendNotifyMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
11779 ok(ret
== TRUE
, "SendNotifyMessageW failed with error %u\n", GetLastError());
11780 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11782 ret
= SendMessageCallbackA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
11783 ok(ret
== TRUE
, "SendMessageCallbackA failed with error %u\n", GetLastError());
11784 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11786 ret
= SendMessageCallbackW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
11787 ok(ret
== TRUE
, "SendMessageCallbackW failed with error %u\n", GetLastError());
11788 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11790 ret
= PostMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
11791 ok(ret
== TRUE
, "PostMessageA failed with error %u\n", GetLastError());
11793 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11795 ret
= PostMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
11796 ok(ret
== TRUE
, "PostMessageW failed with error %u\n", GetLastError());
11798 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11800 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
11801 ok(ret
== TRUE
, "PostThreadMessageA failed with error %u\n", GetLastError());
11802 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
11805 DispatchMessageA(&msg
);
11807 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11809 ret
= PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
11810 ok(ret
== TRUE
, "PostThreadMessageW failed with error %u\n", GetLastError());
11811 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
11814 DispatchMessageA(&msg
);
11816 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
11818 DestroyWindow(hwnd
);
11821 static const struct message WmMouseHoverSeq
[] = {
11822 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
11823 { WM_MOUSEACTIVATE
, sent
|optional
},
11824 { WM_TIMER
, sent
|optional
}, /* XP sends it */
11825 { WM_SYSTIMER
, sent
},
11826 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
11830 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
11833 DWORD start_ticks
, end_ticks
;
11835 start_ticks
= GetTickCount();
11836 /* add some deviation (50%) to cover not expected delays */
11837 start_ticks
+= timeout
/ 2;
11841 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
11843 /* Timer proc messages are not dispatched to the window proc,
11844 * and therefore not logged.
11846 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
11848 struct recvd_message s_msg
;
11850 s_msg
.hwnd
= msg
.hwnd
;
11851 s_msg
.message
= msg
.message
;
11852 s_msg
.flags
= sent
|wparam
|lparam
;
11853 s_msg
.wParam
= msg
.wParam
;
11854 s_msg
.lParam
= msg
.lParam
;
11855 s_msg
.descr
= "msg_loop";
11856 add_message(&s_msg
);
11858 DispatchMessageA(&msg
);
11861 end_ticks
= GetTickCount();
11863 /* inject WM_MOUSEMOVE to see how it changes tracking */
11864 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
11866 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
11867 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
11869 inject_mouse_move
= FALSE
;
11871 } while (start_ticks
+ timeout
>= end_ticks
);
11874 static void test_TrackMouseEvent(void)
11876 TRACKMOUSEEVENT tme
;
11879 RECT rc_parent
, rc_child
;
11880 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
11882 #define track_hover(track_hwnd, track_hover_time) \
11883 tme.cbSize = sizeof(tme); \
11884 tme.dwFlags = TME_HOVER; \
11885 tme.hwndTrack = track_hwnd; \
11886 tme.dwHoverTime = track_hover_time; \
11887 SetLastError(0xdeadbeef); \
11888 ret = pTrackMouseEvent(&tme); \
11889 ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError())
11891 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
11892 tme.cbSize = sizeof(tme); \
11893 tme.dwFlags = TME_QUERY; \
11894 tme.hwndTrack = (HWND)0xdeadbeef; \
11895 tme.dwHoverTime = 0xdeadbeef; \
11896 SetLastError(0xdeadbeef); \
11897 ret = pTrackMouseEvent(&tme); \
11898 ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\
11899 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \
11900 ok(tme.dwFlags == (expected_track_flags), \
11901 "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
11902 ok(tme.hwndTrack == (expected_track_hwnd), \
11903 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
11904 ok(tme.dwHoverTime == (expected_hover_time), \
11905 "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time))
11907 #define track_hover_cancel(track_hwnd) \
11908 tme.cbSize = sizeof(tme); \
11909 tme.dwFlags = TME_HOVER | TME_CANCEL; \
11910 tme.hwndTrack = track_hwnd; \
11911 tme.dwHoverTime = 0xdeadbeef; \
11912 SetLastError(0xdeadbeef); \
11913 ret = pTrackMouseEvent(&tme); \
11914 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError())
11916 default_hover_time
= 0xdeadbeef;
11917 SetLastError(0xdeadbeef);
11918 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
11919 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
11920 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError());
11921 if (!ret
) default_hover_time
= 400;
11922 trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
11924 SetLastError(0xdeadbeef);
11925 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
11926 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
11927 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError());
11928 if (!ret
) hover_width
= 4;
11929 SetLastError(0xdeadbeef);
11930 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
11931 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
11932 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError());
11933 if (!ret
) hover_height
= 4;
11934 trace("hover rect is %u x %d\n", hover_width
, hover_height
);
11936 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
11937 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
11938 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
11942 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
11943 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
11944 50, 50, 200, 200, hwnd
,
11948 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
11953 tme
.dwFlags
= TME_QUERY
;
11954 tme
.hwndTrack
= (HWND
)0xdeadbeef;
11955 tme
.dwHoverTime
= 0xdeadbeef;
11956 SetLastError(0xdeadbeef);
11957 ret
= pTrackMouseEvent(&tme
);
11958 ok(!ret
, "TrackMouseEvent should fail\n");
11959 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
11960 "not expected error %u\n", GetLastError());
11962 tme
.cbSize
= sizeof(tme
);
11963 tme
.dwFlags
= TME_HOVER
;
11964 tme
.hwndTrack
= (HWND
)0xdeadbeef;
11965 tme
.dwHoverTime
= 0xdeadbeef;
11966 SetLastError(0xdeadbeef);
11967 ret
= pTrackMouseEvent(&tme
);
11968 ok(!ret
, "TrackMouseEvent should fail\n");
11969 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
11970 "not expected error %u\n", GetLastError());
11972 tme
.cbSize
= sizeof(tme
);
11973 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
11974 tme
.hwndTrack
= (HWND
)0xdeadbeef;
11975 tme
.dwHoverTime
= 0xdeadbeef;
11976 SetLastError(0xdeadbeef);
11977 ret
= pTrackMouseEvent(&tme
);
11978 ok(!ret
, "TrackMouseEvent should fail\n");
11979 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
11980 "not expected error %u\n", GetLastError());
11982 GetWindowRect(hwnd
, &rc_parent
);
11983 GetWindowRect(hchild
, &rc_child
);
11984 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
11986 /* Process messages so that the system updates its internal current
11987 * window and hittest, otherwise TrackMouseEvent calls don't have any
11993 track_query(0, NULL
, 0);
11994 track_hover(hchild
, 0);
11995 track_query(0, NULL
, 0);
12000 track_hover(hwnd
, 0);
12001 tme
.cbSize
= sizeof(tme
);
12002 tme
.dwFlags
= TME_QUERY
;
12003 tme
.hwndTrack
= (HWND
)0xdeadbeef;
12004 tme
.dwHoverTime
= 0xdeadbeef;
12005 SetLastError(0xdeadbeef);
12006 ret
= pTrackMouseEvent(&tme
);
12007 ok(ret
, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());
12008 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %u\n", tme
.cbSize
);
12011 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
12012 DestroyWindow( hwnd
);
12015 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme
.dwFlags
);
12016 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
12017 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %u, expected %u\n",
12018 tme
.dwHoverTime
, default_hover_time
);
12020 pump_msg_loop_timeout(default_hover_time
, FALSE
);
12021 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12023 track_query(0, NULL
, 0);
12025 track_hover(hwnd
, HOVER_DEFAULT
);
12026 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12028 Sleep(default_hover_time
/ 2);
12029 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12030 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12032 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12034 pump_msg_loop_timeout(default_hover_time
, FALSE
);
12035 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12037 track_query(0, NULL
, 0);
12039 track_hover(hwnd
, HOVER_DEFAULT
);
12040 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12042 pump_msg_loop_timeout(default_hover_time
, TRUE
);
12043 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
12045 track_query(0, NULL
, 0);
12047 track_hover(hwnd
, HOVER_DEFAULT
);
12048 track_query(TME_HOVER
, hwnd
, default_hover_time
);
12049 track_hover_cancel(hwnd
);
12051 DestroyWindow(hwnd
);
12055 #undef track_hover_cancel
12059 static const struct message WmSetWindowRgn
[] = {
12060 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12061 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12062 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
12063 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12064 { WM_ERASEBKGND
, sent
|optional
},
12065 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12066 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12070 static const struct message WmSetWindowRgn_no_redraw
[] = {
12071 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
12072 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12073 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
12074 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12078 static const struct message WmSetWindowRgn_clear
[] = {
12079 { WM_WINDOWPOSCHANGING
, sent
/*|wparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ },
12080 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
12081 { WM_NCPAINT
, sent
|optional
},
12082 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12083 { WM_ERASEBKGND
, sent
|optional
}, /* FIXME: remove optional once Wine is fixed */
12084 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12085 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
12086 { WM_NCPAINT
, sent
|optional
},
12087 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12088 { WM_ERASEBKGND
, sent
|optional
},
12089 { WM_WINDOWPOSCHANGING
, sent
|optional
},
12090 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
12091 { WM_NCPAINT
, sent
|optional
},
12092 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12093 { WM_ERASEBKGND
, sent
|optional
},
12094 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
12095 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
12096 { WM_NCPAINT
, sent
|optional
},
12097 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12098 { WM_ERASEBKGND
, sent
|optional
},
12099 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12100 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12104 static void test_SetWindowRgn(void)
12107 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
12108 100, 100, 200, 200, 0, 0, 0, NULL
);
12109 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
12111 ShowWindow( hwnd
, SW_SHOW
);
12112 UpdateWindow( hwnd
);
12116 trace("testing SetWindowRgn\n");
12117 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
12118 SetWindowRgn( hwnd
, hrgn
, TRUE
);
12119 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
12121 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
12122 SetWindowRgn( hwnd
, hrgn
, FALSE
);
12123 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
12125 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
12126 SetWindowRgn( hwnd
, hrgn
, TRUE
);
12127 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
12129 SetWindowRgn( hwnd
, 0, TRUE
);
12130 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
12132 DestroyWindow( hwnd
);
12135 /*************************** ShowWindow() test ******************************/
12136 static const struct message WmShowNormal
[] = {
12137 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12138 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12139 { HCBT_ACTIVATE
, hook
},
12140 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12141 { HCBT_SETFOCUS
, hook
},
12142 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12145 static const struct message WmShow
[] = {
12146 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12147 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12148 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12149 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12150 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12151 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12154 static const struct message WmShowNoActivate_1
[] = {
12155 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
12156 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12157 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12158 { WM_MOVE
, sent
|defwinproc
|optional
},
12159 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12162 static const struct message WmShowNoActivate_2
[] = {
12163 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
12164 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12165 { HCBT_ACTIVATE
, hook
|optional
},
12166 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12167 { HCBT_SETFOCUS
, hook
|optional
},
12168 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12169 { WM_MOVE
, sent
|defwinproc
},
12170 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12171 { HCBT_SETFOCUS
, hook
|optional
},
12172 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
12173 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12174 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12175 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
12178 static const struct message WmShowNA_1
[] = {
12179 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12180 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
12181 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12184 static const struct message WmShowNA_2
[] = {
12185 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12186 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
12187 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12190 static const struct message WmRestore_1
[] = {
12191 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
12192 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12193 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12194 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12195 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12196 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12197 { WM_MOVE
, sent
|defwinproc
},
12198 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
12199 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
12202 static const struct message WmRestore_2
[] = {
12203 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
12204 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12205 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12206 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12207 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12208 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12211 static const struct message WmRestore_3
[] = {
12212 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
12213 { WM_GETMINMAXINFO
, sent
},
12214 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12215 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
12216 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
12217 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
12218 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12219 { WM_MOVE
, sent
|defwinproc
},
12220 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12221 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
12224 static const struct message WmRestore_4
[] = {
12225 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
12226 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12227 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12228 { WM_MOVE
, sent
|defwinproc
|optional
},
12229 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
12232 static const struct message WmRestore_5
[] = {
12233 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
12234 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12235 { HCBT_ACTIVATE
, hook
|optional
},
12236 { HCBT_SETFOCUS
, hook
|optional
},
12237 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12238 { WM_MOVE
, sent
|defwinproc
|optional
},
12239 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
12242 static const struct message WmHide_1
[] = {
12243 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12244 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
12245 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
12246 { HCBT_ACTIVATE
, hook
|optional
},
12247 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
12250 static const struct message WmHide_2
[] = {
12251 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12252 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
12253 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
12254 { HCBT_ACTIVATE
, hook
|optional
},
12257 static const struct message WmHide_3
[] = {
12258 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
12259 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
12260 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12261 { HCBT_SETFOCUS
, hook
|optional
},
12262 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12265 static const struct message WmShowMinimized_1
[] = {
12266 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
12267 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12268 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12269 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12270 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12271 { WM_MOVE
, sent
|defwinproc
},
12272 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12275 static const struct message WmMinimize_1
[] = {
12276 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12277 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12278 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12279 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12280 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12281 { WM_MOVE
, sent
|defwinproc
},
12282 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12285 static const struct message WmMinimize_2
[] = {
12286 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12287 { HCBT_SETFOCUS
, hook
|optional
},
12288 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12289 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12290 { WM_MOVE
, sent
|defwinproc
},
12291 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12294 static const struct message WmMinimize_3
[] = {
12295 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12296 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12297 { HCBT_ACTIVATE
, hook
|optional
},
12298 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12299 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
12300 { WM_MOVE
, sent
|defwinproc
},
12301 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
12304 static const struct message WmShowMinNoActivate
[] = {
12305 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
12306 { WM_WINDOWPOSCHANGING
, sent
},
12307 { WM_WINDOWPOSCHANGED
, sent
},
12308 { WM_MOVE
, sent
|defwinproc
|optional
},
12309 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
12312 static const struct message WmMinMax_1
[] = {
12313 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
12316 static const struct message WmMinMax_2
[] = {
12317 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12318 { WM_GETMINMAXINFO
, sent
|optional
},
12319 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
12320 { HCBT_ACTIVATE
, hook
|optional
},
12321 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12322 { HCBT_SETFOCUS
, hook
|optional
},
12323 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
12324 { WM_MOVE
, sent
|defwinproc
|optional
},
12325 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
12326 { HCBT_SETFOCUS
, hook
|optional
},
12329 static const struct message WmMinMax_3
[] = {
12330 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
12331 { HCBT_SETFOCUS
, hook
|optional
},
12332 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12333 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12334 { WM_MOVE
, sent
|defwinproc
|optional
},
12335 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
12338 static const struct message WmMinMax_4
[] = {
12339 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
12342 static const struct message WmShowMaximized_1
[] = {
12343 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12344 { WM_GETMINMAXINFO
, sent
},
12345 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12346 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12347 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12348 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12349 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12350 { WM_MOVE
, sent
|defwinproc
},
12351 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12352 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
12355 static const struct message WmShowMaximized_2
[] = {
12356 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12357 { WM_GETMINMAXINFO
, sent
},
12358 { WM_WINDOWPOSCHANGING
, sent
|optional
},
12359 { HCBT_ACTIVATE
, hook
|optional
},
12360 { WM_WINDOWPOSCHANGED
, sent
|optional
},
12361 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
12362 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
12363 { WM_WINDOWPOSCHANGING
, sent
|optional
},
12364 { HCBT_SETFOCUS
, hook
|optional
},
12365 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
12366 { WM_MOVE
, sent
|defwinproc
},
12367 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12368 { HCBT_SETFOCUS
, hook
|optional
},
12371 static const struct message WmShowMaximized_3
[] = {
12372 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
12373 { WM_GETMINMAXINFO
, sent
|optional
},
12374 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12375 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
12376 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
12377 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
12378 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
12379 { WM_MOVE
, sent
|defwinproc
|optional
},
12380 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
12384 static void test_ShowWindow(void)
12386 /* ShowWindow commands in random order */
12387 static const struct
12389 INT cmd
; /* ShowWindow command */
12390 LPARAM ret
; /* ShowWindow return value */
12391 DWORD style
; /* window style after the command */
12392 const struct message
*msg
; /* message sequence the command produces */
12393 INT wp_cmd
, wp_flags
; /* window placement after the command */
12394 POINT wp_min
, wp_max
; /* window placement after the command */
12395 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
12398 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
12399 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12400 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12401 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12402 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
12403 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12404 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
12405 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
12406 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
12407 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12408 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
12409 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12410 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
12411 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12412 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
12413 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12414 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
12415 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12416 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
12417 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12418 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
12419 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12420 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
12421 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12422 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
12423 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12424 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12425 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12426 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
12427 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12428 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
12429 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12430 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
12431 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12432 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12433 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12434 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
12435 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12436 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
12437 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12438 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
12439 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12440 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
12441 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
12442 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
12443 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12444 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
12445 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12446 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
12447 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12448 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
12449 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12450 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
12451 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12452 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
12453 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12454 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
12455 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12456 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
12457 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12458 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12459 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12460 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
12461 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12462 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
12463 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12464 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
12465 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12466 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
12467 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12468 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
12469 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12470 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
12471 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12472 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12473 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12474 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12475 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12476 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
12477 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12478 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
12479 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12480 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
12481 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12482 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
12483 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12484 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
12485 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12486 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
12487 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12488 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
12489 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12490 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
12491 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12492 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
12493 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12494 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
12495 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12496 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
12497 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12498 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
12499 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12500 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
12501 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12502 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
12503 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
12504 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
12505 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12506 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
12507 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12508 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
12509 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
12510 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
12511 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
12517 WINDOWPLACEMENT wp
;
12518 RECT win_rc
, work_rc
= {0, 0, 0, 0};
12520 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
12521 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
12526 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
12527 ok(style
== 0, "expected style 0, got %08x\n", style
);
12532 if (pGetMonitorInfoA
&& pMonitorFromPoint
)
12538 SetLastError(0xdeadbeef);
12539 hmon
= pMonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
12540 ok(hmon
!= 0, "MonitorFromPoint error %u\n", GetLastError());
12542 mi
.cbSize
= sizeof(mi
);
12543 SetLastError(0xdeadbeef);
12544 ret
= pGetMonitorInfoA(hmon
, &mi
);
12545 ok(ret
, "GetMonitorInfo error %u\n", GetLastError());
12546 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi
.rcMonitor
),
12547 wine_dbgstr_rect(&mi
.rcWork
));
12548 work_rc
= mi
.rcWork
;
12551 GetWindowRect(hwnd
, &win_rc
);
12552 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
12554 wp
.length
= sizeof(wp
);
12555 SetLastError(0xdeadbeaf);
12556 ret
= GetWindowPlacement(hwnd
, &wp
);
12557 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
12558 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
12559 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
12560 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
12561 "expected -1,-1 got %d,%d\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
12562 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
12563 "expected -1,-1 got %d,%d\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
12564 todo_wine_if (work_rc
.left
|| work_rc
.top
) /* FIXME: remove once Wine is fixed */
12565 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n", wine_dbgstr_rect(&win_rc
),
12566 wine_dbgstr_rect(&wp
.rcNormalPosition
));
12568 for (i
= 0; i
< sizeof(sw
)/sizeof(sw
[0]); i
++)
12570 static const char * const sw_cmd_name
[13] =
12572 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
12573 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
12574 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
12575 "SW_NORMALNA" /* 0xCC */
12578 INT idx
; /* index into the above array of names */
12580 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
12582 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
12583 trace("%d: sending %s, current window style %08x\n", i
+1, sw_cmd_name
[idx
], style
);
12584 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
12585 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %lu, got %lu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
12586 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
12587 ok(style
== sw
[i
].style
, "%d: expected style %08x, got %08x\n", i
+1, sw
[i
].style
, style
);
12589 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
12590 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
12592 wp
.length
= sizeof(wp
);
12593 SetLastError(0xdeadbeaf);
12594 ret
= GetWindowPlacement(hwnd
, &wp
);
12595 ok(ret
, "GetWindowPlacement error %u\n", GetLastError());
12596 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
12597 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
12599 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
12600 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
12601 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
12603 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
12604 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
12605 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
12609 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
12610 "expected %d,%d got %d,%d\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
12613 todo_wine_if(wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
12614 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
12615 "expected %d,%d got %d,%d\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
12617 if (0) /* FIXME: Wine behaves completely different here */
12618 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n",
12619 wine_dbgstr_rect(&win_rc
), wine_dbgstr_rect(&wp
.rcNormalPosition
));
12621 DestroyWindow(hwnd
);
12625 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12627 struct recvd_message msg
;
12629 if (ignore_message( message
)) return 0;
12632 msg
.message
= message
;
12633 msg
.flags
= sent
|wparam
|lparam
;
12634 msg
.wParam
= wParam
;
12635 msg
.lParam
= lParam
;
12636 msg
.descr
= "dialog";
12639 /* calling DefDlgProc leads to a recursion under XP */
12643 case WM_INITDIALOG
:
12644 case WM_GETDLGCODE
:
12650 static WNDPROC orig_edit_proc
;
12651 static LRESULT WINAPI
dlg_creation_edit_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12653 struct recvd_message msg
;
12655 if (ignore_message( message
)) return 0;
12658 msg
.message
= message
;
12659 msg
.flags
= sent
|wparam
|lparam
;
12662 msg
.descr
= "edit";
12665 return CallWindowProcW(orig_edit_proc
, hwnd
, message
, wp
, lp
);
12668 static INT_PTR WINAPI
test_dlg_proc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12670 struct recvd_message msg
;
12672 if (ignore_message( message
)) return 0;
12675 msg
.message
= message
;
12676 msg
.flags
= sent
|wparam
|lparam
|parent
;
12677 msg
.wParam
= wParam
;
12678 msg
.lParam
= lParam
;
12679 msg
.descr
= "dialog";
12682 if (message
== WM_INITDIALOG
)
12684 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
12685 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
12691 static INT_PTR WINAPI
test_dlg_proc3(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12693 ok( 0, "should not be called since DefDlgProc is not used\n" );
12697 static LRESULT WINAPI
test_dlg_proc4(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12699 struct recvd_message msg
;
12701 if (!ignore_message( message
))
12704 msg
.message
= message
;
12705 msg
.flags
= sent
|wparam
|lparam
|parent
;
12706 msg
.wParam
= wParam
;
12707 msg
.lParam
= lParam
;
12708 msg
.descr
= "dialog";
12711 if (message
== WM_INITDIALOG
)
12713 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
12714 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
12717 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
12720 static const struct message WmDefDlgSetFocus_1
[] = {
12721 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
12722 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
12723 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
12724 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
12725 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
12726 { HCBT_SETFOCUS
, hook
},
12727 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
12728 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
12729 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
12730 { WM_SETFOCUS
, sent
|wparam
, 0 },
12731 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
12732 { WM_CTLCOLOREDIT
, sent
},
12733 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
12734 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
12735 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
12736 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
12737 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
12740 static const struct message WmDefDlgSetFocus_2
[] = {
12741 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
12742 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
12743 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
12744 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
12745 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
12746 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
12747 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
12748 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 },
12751 /* Creation of a dialog */
12752 static const struct message WmCreateDialogParamSeq_1
[] = {
12753 { HCBT_CREATEWND
, hook
},
12754 { WM_NCCREATE
, sent
},
12755 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
12756 { WM_CREATE
, sent
},
12757 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12758 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
12760 { WM_SETFONT
, sent
},
12761 { WM_INITDIALOG
, sent
},
12762 { WM_CHANGEUISTATE
, sent
|optional
},
12765 /* Creation of a dialog */
12766 static const struct message WmCreateDialogParamSeq_2
[] = {
12767 { HCBT_CREATEWND
, hook
},
12768 { WM_NCCREATE
, sent
},
12769 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
12770 { WM_CREATE
, sent
},
12771 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12772 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
12774 { WM_CHANGEUISTATE
, sent
|optional
},
12778 static const struct message WmCreateDialogParamSeq_3
[] = {
12779 { HCBT_CREATEWND
, hook
},
12780 { WM_SETFONT
, sent
|parent
},
12781 { WM_INITDIALOG
, sent
|parent
},
12782 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
12783 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
12784 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
12785 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
12786 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
12787 { HCBT_ACTIVATE
, hook
},
12788 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
12789 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12790 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12791 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
12792 { WM_NCACTIVATE
, sent
|parent
},
12793 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
12794 { WM_SETFOCUS
, sent
},
12795 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
12796 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
12797 { WM_USER
, sent
|parent
},
12798 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
12802 static const struct message WmCreateDialogParamSeq_4
[] = {
12803 { HCBT_CREATEWND
, hook
},
12804 { WM_NCCREATE
, sent
|parent
},
12805 { WM_NCCALCSIZE
, sent
|parent
|wparam
, 0 },
12806 { WM_CREATE
, sent
|parent
},
12807 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
12808 { WM_SIZE
, sent
|parent
|wparam
, SIZE_RESTORED
},
12809 { WM_MOVE
, sent
|parent
},
12810 { WM_SETFONT
, sent
|parent
},
12811 { WM_INITDIALOG
, sent
|parent
},
12812 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
12813 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
12814 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
12815 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
12816 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
12817 { HCBT_ACTIVATE
, hook
},
12818 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
12819 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12820 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
12821 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
12822 { WM_NCACTIVATE
, sent
|parent
},
12823 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
12824 { HCBT_SETFOCUS
, hook
},
12825 { WM_SETFOCUS
, sent
|parent
},
12826 { WM_KILLFOCUS
, sent
|parent
},
12827 { WM_SETFOCUS
, sent
},
12828 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
12829 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
12830 { WM_USER
, sent
|parent
},
12831 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
12832 { WM_UPDATEUISTATE
, sent
|parent
|optional
},
12833 { WM_UPDATEUISTATE
, sent
|optional
},
12837 static void test_dialog_messages(void)
12840 HWND hdlg
, hedit1
, hedit2
, hfocus
, parent
, child
, child2
;
12843 #define set_selection(hctl, start, end) \
12844 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
12845 ok(ret == 1, "EM_SETSEL returned %ld\n", ret);
12847 #define check_selection(hctl, start, end) \
12848 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
12849 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
12853 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
12854 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
12855 0, 0, 100, 100, 0, 0, 0, NULL
);
12856 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
12858 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
12859 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
12860 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
12861 ok(hedit1
!= 0, "Failed to create edit control\n");
12862 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
12863 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
12864 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
12865 ok(hedit2
!= 0, "Failed to create edit control\n");
12867 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
12868 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
12870 hfocus
= GetFocus();
12871 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
12874 hfocus
= GetFocus();
12875 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
12877 check_selection(hedit1
, 0, 0);
12878 check_selection(hedit2
, 0, 0);
12880 set_selection(hedit2
, 0, -1);
12881 check_selection(hedit2
, 0, 3);
12884 hfocus
= GetFocus();
12885 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
12888 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
12889 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
12890 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
12892 hfocus
= GetFocus();
12893 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
12895 check_selection(hedit1
, 0, 5);
12896 check_selection(hedit2
, 0, 3);
12899 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
12900 ok(ret
== 0, "WM_SETFOCUS returned %ld\n", ret
);
12901 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
12903 hfocus
= GetFocus();
12904 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
12906 check_selection(hedit1
, 0, 5);
12907 check_selection(hedit2
, 0, 3);
12909 EndDialog(hdlg
, 0);
12910 DestroyWindow(hedit1
);
12911 DestroyWindow(hedit2
);
12912 DestroyWindow(hdlg
);
12915 #undef set_selection
12916 #undef check_selection
12918 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
12919 cls
.lpszClassName
= "MyDialogClass";
12920 cls
.hInstance
= GetModuleHandleA(NULL
);
12921 /* need a cast since a dlgproc is used as a wndproc */
12922 cls
.lpfnWndProc
= test_dlg_proc
;
12923 if (!RegisterClassA(&cls
)) assert(0);
12925 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
12926 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
12927 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
12928 EndDialog(hdlg
, 0);
12929 DestroyWindow(hdlg
);
12932 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
12933 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
12934 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
12935 EndDialog(hdlg
, 0);
12936 DestroyWindow(hdlg
);
12939 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2
, 0);
12940 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
12941 ok_sequence(WmCreateDialogParamSeq_3
, "CreateDialogParam_3", TRUE
);
12942 EndDialog(hdlg
, 0);
12943 DestroyWindow(hdlg
);
12946 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
12947 cls
.lpfnWndProc
= test_dlg_proc4
;
12948 ok( RegisterClassA(&cls
), "failed to register class again\n" );
12949 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3
, 0);
12950 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
12951 ok_sequence(WmCreateDialogParamSeq_4
, "CreateDialogParam_4", TRUE
);
12952 EndDialog(hdlg
, 0);
12953 DestroyWindow(hdlg
);
12956 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
12958 parent
= CreateWindowExA(0, "TestParentClass", "Test parent",
12959 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12960 100, 100, 200, 200, 0, 0, 0, NULL
);
12961 ok (parent
!= 0, "Failed to create parent window\n");
12963 /* This child has no parent set. We will later call SetParent on it,
12964 * so that it will have a parent set, but no WS_CHILD style. */
12965 child
= CreateWindowExA(0, "TestWindowClass", "Test child",
12966 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
12967 100, 100, 200, 200, 0, 0, 0, NULL
);
12968 ok (child
!= 0, "Failed to create child window\n");
12970 /* This is a regular child window. When used as an owner, the other
12971 * child window will be used. */
12972 child2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2",
12973 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CHILD
,
12974 100, 100, 200, 200, child
, 0, 0, NULL
);
12975 ok (child2
!= 0, "Failed to create child window\n");
12977 SetParent(child
, parent
);
12981 DialogBoxA( 0, "TEST_DIALOG", child2
, TestModalDlgProc2
);
12982 ok_sequence(WmModalDialogSeq_2
, "ModalDialog2", TRUE
);
12984 DestroyWindow(child2
);
12985 DestroyWindow(child
);
12986 DestroyWindow(parent
);
12990 static void test_enddialog_seq(HWND dialog
, HWND owner
)
12992 const struct message seq
[] = {
12993 { WM_ENABLE
, sent
},
12994 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
12995 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
12996 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
12997 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
12998 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */
12999 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13000 { WM_QUERYNEWPALETTE
, sent
|optional
},
13001 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
13002 { WM_GETTEXT
, sent
|optional
|defwinproc
},
13003 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
13004 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
13005 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
13006 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, (WPARAM
)dialog
},
13011 EndDialog(dialog
, 0);
13012 ok_sequence(seq
, "EndDialog", FALSE
);
13015 static void test_enddialog_seq2(HWND dialog
, HWND owner
)
13017 const struct message seq
[] = {
13018 { WM_ENABLE
, parent
|sent
},
13019 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13020 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
13021 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13022 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
13023 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13024 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
13025 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
13026 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
13027 { WM_SETFOCUS
, sent
|parent
|defwinproc
|wparam
, (WPARAM
)dialog
},
13032 EndDialog(dialog
, 0);
13033 ok_sequence(seq
, "EndDialog2", FALSE
);
13036 static void test_EndDialog(void)
13038 HWND hparent
, hother
, hactive
, hdlg
, hchild
;
13041 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13042 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
13043 100, 100, 200, 200, 0, 0, 0, NULL
);
13044 ok (hparent
!= 0, "Failed to create parent window\n");
13046 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
13047 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13048 200, 100, 200, 200, 0, 0, 0, NULL
);
13049 ok (hother
!= 0, "Failed to create parent window\n");
13051 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
13052 cls
.lpszClassName
= "MyDialogClass";
13053 cls
.hInstance
= GetModuleHandleA(NULL
);
13054 cls
.lpfnWndProc
= test_dlg_proc
;
13055 if (!RegisterClassA(&cls
)) assert(0);
13058 SetForegroundWindow(hother
);
13059 hactive
= GetForegroundWindow();
13060 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
13062 /* create a dialog where the parent is disabled, this parent should be
13063 * enabled and receive focus when dialog exits */
13064 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
13065 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13066 SetForegroundWindow(hdlg
);
13067 hactive
= GetForegroundWindow();
13068 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
13069 EndDialog(hdlg
, 0);
13070 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
13071 hactive
= GetForegroundWindow();
13072 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
13073 DestroyWindow(hdlg
);
13076 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */
13077 EnableWindow(hparent
, FALSE
);
13078 hdlg
= CreateWindowExA(0, "TestDialogClass", NULL
,
13079 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
13080 0, 0, 100, 100, hparent
, 0, 0, NULL
);
13081 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13083 SetForegroundWindow(hother
);
13085 hactive
= GetForegroundWindow();
13086 ok(hactive
== hother
, "Wrong foreground (%p != %p)\n", hactive
, hother
);
13087 hactive
= GetActiveWindow();
13088 ok(hactive
== hother
, "Wrong active window (%p != %p)\n", hactive
, hother
);
13089 EndDialog(hdlg
, 0);
13090 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
13091 hactive
= GetForegroundWindow();
13092 ok(hother
== hactive
, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
13093 DestroyWindow(hdlg
);
13096 DestroyWindow( hparent
);
13098 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
13099 WS_POPUP
| WS_VISIBLE
| WS_DISABLED
,
13100 100, 100, 200, 200, 0, 0, 0, NULL
);
13101 ok (hparent
!= 0, "Failed to create parent window\n");
13103 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
13104 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
13105 0, 0, 0, 0, 0, 0, 0, NULL
);
13106 ok (hchild
!= 0, "Failed to create child window\n");
13108 SetParent(hchild
, hparent
);
13111 SetForegroundWindow(hother
);
13112 hactive
= GetForegroundWindow();
13113 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
13115 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
13116 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13118 SetForegroundWindow(hdlg
);
13119 test_enddialog_seq(hdlg
, hchild
);
13121 hactive
= GetForegroundWindow();
13122 ok(hactive
== hchild
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
13124 DestroyWindow(hdlg
);
13126 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */
13127 SetWindowLongW(hchild
, GWL_STYLE
, GetWindowLongW(hchild
, GWL_STYLE
) | WS_CHILD
);
13129 SetForegroundWindow(hother
);
13130 hactive
= GetForegroundWindow();
13131 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
13133 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
13134 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
13136 SetForegroundWindow(hdlg
);
13137 test_enddialog_seq2(hdlg
, hparent
);
13139 hactive
= GetForegroundWindow();
13140 ok(hactive
== hparent
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
13141 DestroyWindow(hdlg
);
13142 DestroyWindow(hchild
);
13143 DestroyWindow(hparent
);
13144 DestroyWindow(hother
);
13147 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
13150 static void test_nullCallback(void)
13154 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
13155 100, 100, 200, 200, 0, 0, 0, NULL
);
13156 ok (hwnd
!= 0, "Failed to create overlapped window\n");
13158 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
13160 DestroyWindow(hwnd
);
13163 /* SetActiveWindow( 0 ) hwnd visible */
13164 static const struct message SetActiveWindowSeq0
[] =
13166 { HCBT_ACTIVATE
, hook
|optional
},
13167 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13168 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13169 { WM_ACTIVATE
, sent
|wparam
, 0 },
13170 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13171 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
13172 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13173 { WM_KILLFOCUS
, sent
|optional
},
13174 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13175 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13176 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
13177 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13178 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
13179 { HCBT_SETFOCUS
, hook
|optional
},
13180 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
13181 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
13182 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
13183 { WM_IME_SETCONTEXT
, sent
|optional
},
13184 { WM_IME_SETCONTEXT
, sent
|optional
},
13185 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13186 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13187 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
13188 { WM_GETTEXT
, sent
|optional
},
13191 /* SetActiveWindow( hwnd ) hwnd visible */
13192 static const struct message SetActiveWindowSeq1
[] =
13194 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13197 /* SetActiveWindow( popup ) hwnd visible, popup visible */
13198 static const struct message SetActiveWindowSeq2
[] =
13200 { HCBT_ACTIVATE
, hook
},
13201 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13202 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13203 { WM_ACTIVATE
, sent
|wparam
, 0 },
13204 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13205 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
13206 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13207 { WM_NCPAINT
, sent
|optional
},
13208 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13209 { WM_ERASEBKGND
, sent
|optional
},
13210 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13211 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13212 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13213 { WM_ACTIVATE
, sent
|wparam
, 1 },
13214 { HCBT_SETFOCUS
, hook
},
13215 { WM_KILLFOCUS
, sent
|defwinproc
},
13216 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
13217 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13218 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13219 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13220 { WM_SETFOCUS
, sent
|defwinproc
},
13221 { WM_GETTEXT
, sent
|optional
},
13225 /* SetActiveWindow( hwnd ) hwnd not visible */
13226 static const struct message SetActiveWindowSeq3
[] =
13228 { HCBT_ACTIVATE
, hook
},
13229 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13230 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13231 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
13232 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13233 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13234 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13235 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
13236 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13237 { WM_ACTIVATE
, sent
|wparam
, 1 },
13238 { HCBT_SETFOCUS
, hook
},
13239 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13240 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13241 { WM_SETFOCUS
, sent
|defwinproc
},
13244 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
13245 static const struct message SetActiveWindowSeq4
[] =
13247 { HCBT_ACTIVATE
, hook
},
13248 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13249 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13250 { WM_ACTIVATE
, sent
|wparam
, 0 },
13251 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
13252 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
13253 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
13254 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13255 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
13256 { WM_NCACTIVATE
, sent
|wparam
, 1 },
13257 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13258 { WM_ACTIVATE
, sent
|wparam
, 1 },
13259 { HCBT_SETFOCUS
, hook
},
13260 { WM_KILLFOCUS
, sent
|defwinproc
},
13261 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
13262 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13263 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13264 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13265 { WM_SETFOCUS
, sent
|defwinproc
},
13270 static void test_SetActiveWindow(void)
13272 HWND hwnd
, popup
, ret
;
13274 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
13275 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13276 100, 100, 200, 200, 0, 0, 0, NULL
);
13278 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
13279 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
13280 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
13282 ok(hwnd
!= 0, "Failed to create overlapped window\n");
13283 ok(popup
!= 0, "Failed to create popup window\n");
13284 SetForegroundWindow( popup
);
13287 trace("SetActiveWindow(0)\n");
13288 ret
= SetActiveWindow(0);
13289 ok( ret
== popup
, "Failed to SetActiveWindow(0)\n");
13290 ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
13293 trace("SetActiveWindow(hwnd), hwnd visible\n");
13294 ret
= SetActiveWindow(hwnd
);
13295 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
13298 trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
13299 ret
= SetActiveWindow(popup
);
13300 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
13301 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
13304 ShowWindow(hwnd
, SW_HIDE
);
13305 ShowWindow(popup
, SW_HIDE
);
13308 trace("SetActiveWindow(hwnd), hwnd not visible\n");
13309 ret
= SetActiveWindow(hwnd
);
13310 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
13311 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
13314 trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
13315 ret
= SetActiveWindow(popup
);
13316 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
13317 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
13322 DestroyWindow(hwnd
);
13325 static const struct message SetForegroundWindowSeq
[] =
13327 { WM_NCACTIVATE
, sent
|wparam
, 0 },
13328 { WM_GETTEXT
, sent
|defwinproc
|optional
},
13329 { WM_ACTIVATE
, sent
|wparam
, 0 },
13330 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
13331 { WM_KILLFOCUS
, sent
},
13332 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
13333 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
13337 static void test_SetForegroundWindow(void)
13341 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
13342 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13343 100, 100, 200, 200, 0, 0, 0, NULL
);
13344 ok (hwnd
!= 0, "Failed to create overlapped window\n");
13345 SetForegroundWindow( hwnd
);
13348 trace("SetForegroundWindow( 0 )\n");
13349 SetForegroundWindow( 0 );
13350 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
13351 trace("SetForegroundWindow( GetDesktopWindow() )\n");
13352 SetForegroundWindow( GetDesktopWindow() );
13353 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
13354 "foreground top level window", FALSE
);
13357 DestroyWindow(hwnd
);
13360 static DWORD
get_input_codepage( void )
13364 HKL hkl
= GetKeyboardLayout( 0 );
13366 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
,
13367 (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
13368 if (!ret
) cp
= CP_ACP
;
13372 static void test_dbcs_wm_char(void)
13375 WCHAR wch
, bad_wch
;
13383 struct message wmCharSeq
[2];
13385 DWORD cp
= get_input_codepage();
13387 if (!pGetCPInfoExA
)
13389 win_skip("GetCPInfoExA is not available\n");
13393 pGetCPInfoExA( cp
, 0, &cpinfo
);
13394 if (cpinfo
.MaxCharSize
!= 2)
13396 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
13400 dbch
[0] = dbch
[1] = 0;
13402 bad_wch
= cpinfo
.UnicodeDefaultChar
;
13403 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
13404 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
13405 for (k
= 128; k
<= 255; k
++)
13411 if (MultiByteToWideChar( cp
, 0, str
, 2, wstr
, 2 ) == 1 &&
13412 WideCharToMultiByte( cp
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
13413 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
13414 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
13425 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
13428 trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
13429 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
13431 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
13432 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
13433 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
13434 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
13435 ok (hwnd
!= 0, "Failed to create overlapped window\n");
13436 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
13439 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
13440 wmCharSeq
[0].message
= WM_CHAR
;
13441 wmCharSeq
[0].flags
= sent
|wparam
;
13442 wmCharSeq
[0].wParam
= wch
;
13444 /* posted message */
13445 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
13446 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13447 ok( !ret
, "got message %x\n", msg
.message
);
13448 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13449 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13450 ok( ret
, "no message\n" );
13451 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13452 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
13453 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13454 ok( !ret
, "got message %x\n", msg
.message
);
13456 /* posted thread message */
13457 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
13458 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13459 ok( !ret
, "got message %x\n", msg
.message
);
13460 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13461 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13462 ok( ret
, "no message\n" );
13463 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13464 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
13465 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13466 ok( !ret
, "got message %x\n", msg
.message
);
13470 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
13471 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13472 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13473 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13474 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13475 ok( !ret
, "got message %x\n", msg
.message
);
13477 /* sent message with timeout */
13479 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
13480 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13481 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
13482 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13483 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13484 ok( !ret
, "got message %x\n", msg
.message
);
13486 /* sent message with timeout and callback */
13488 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
13489 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13490 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
13491 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13492 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13493 ok( !ret
, "got message %x\n", msg
.message
);
13495 /* sent message with callback */
13497 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
13498 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13499 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
13500 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13501 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13502 ok( !ret
, "got message %x\n", msg
.message
);
13504 /* direct window proc call */
13506 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
13507 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13508 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
13509 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13511 /* dispatch message */
13513 msg
.message
= WM_CHAR
;
13514 msg
.wParam
= dbch
[0];
13516 DispatchMessageA( &msg
);
13517 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13518 msg
.wParam
= dbch
[1];
13519 DispatchMessageA( &msg
);
13520 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13522 /* window handle is irrelevant */
13524 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
13525 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13526 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13527 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13528 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13529 ok( !ret
, "got message %x\n", msg
.message
);
13531 /* interleaved post and send */
13533 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
13534 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
13535 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13536 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13537 ok( !ret
, "got message %x\n", msg
.message
);
13538 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13539 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13540 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13541 ok( ret
, "no message\n" );
13542 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13543 ok( msg
.wParam
== wch
, "bad wparam %lx/%x\n", msg
.wParam
, wch
);
13544 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13545 ok( !ret
, "got message %x\n", msg
.message
);
13546 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13547 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13548 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13549 ok( !ret
, "got message %x\n", msg
.message
);
13551 /* interleaved sent message and winproc */
13553 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
13554 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
13555 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13556 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13557 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13558 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
13559 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13561 /* interleaved winproc and dispatch */
13563 msg
.message
= WM_CHAR
;
13564 msg
.wParam
= dbch
[0];
13566 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
13567 DispatchMessageA( &msg
);
13568 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13569 msg
.wParam
= dbch
[1];
13570 DispatchMessageA( &msg
);
13571 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13572 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
13573 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13575 /* interleaved sends */
13577 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
13578 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
13579 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
13580 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
13581 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13582 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
13583 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13587 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
13588 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
13589 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13590 ok( !ret
, "got message %x\n", msg
.message
);
13592 /* other char messages are not magic */
13593 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
13594 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13595 ok( ret
, "no message\n" );
13596 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
13597 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
13598 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13599 ok( !ret
, "got message %x\n", msg
.message
);
13600 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
13601 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13602 ok( ret
, "no message\n" );
13603 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
13604 ok( msg
.wParam
== bad_wch
, "bad wparam %lx/%x\n", msg
.wParam
, bad_wch
);
13605 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13606 ok( !ret
, "got message %x\n", msg
.message
);
13608 /* test retrieving messages */
13610 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
13611 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13612 ok( ret
, "no message\n" );
13613 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13614 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13615 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13616 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13617 ok( ret
, "no message\n" );
13618 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13619 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13620 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13621 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13622 ok( !ret
, "got message %x\n", msg
.message
);
13624 /* message filters */
13625 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
13626 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13627 ok( ret
, "no message\n" );
13628 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13629 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13630 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13631 /* message id is filtered, hwnd is not */
13632 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
13633 ok( !ret
, "no message\n" );
13634 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
13635 ok( ret
, "no message\n" );
13636 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13637 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13638 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13639 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13640 ok( !ret
, "got message %x\n", msg
.message
);
13642 /* mixing GetMessage and PostMessage */
13643 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
13644 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
13645 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13646 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13647 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13648 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
13651 ok( time
- GetTickCount() <= 100, "bad time %x\n", msg
.time
);
13652 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
13653 ok( ret
, "no message\n" );
13654 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13655 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13656 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13657 ok( msg
.lParam
== 0xbeef, "bad lparam %lx\n", msg
.lParam
);
13658 ok( msg
.time
== time
, "bad time %x/%x\n", msg
.time
, time
);
13659 ok( msg
.pt
.x
== pt
.x
&& msg
.pt
.y
== pt
.y
, "bad point %u,%u/%u,%u\n", msg
.pt
.x
, msg
.pt
.y
, pt
.x
, pt
.y
);
13660 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13661 ok( !ret
, "got message %x\n", msg
.message
);
13663 /* without PM_REMOVE */
13664 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
13665 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13666 ok( ret
, "no message\n" );
13667 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13668 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13669 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13670 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
13671 ok( ret
, "no message\n" );
13672 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13673 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13674 ok( msg
.wParam
== dbch
[0], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13675 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
13676 ok( ret
, "no message\n" );
13677 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13678 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13679 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13680 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
13681 ok( ret
, "no message\n" );
13682 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13683 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13684 ok( msg
.wParam
== dbch
[1], "bad wparam %lx/%x\n", msg
.wParam
, dbch
[0] );
13685 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
13686 ok( !ret
, "got message %x\n", msg
.message
);
13688 DestroyWindow(hwnd
);
13689 DestroyWindow(hwnd2
);
13692 static void test_unicode_wm_char(void)
13696 struct message seq
[2];
13697 HKL hkl_orig
, hkl_greek
;
13699 LCID thread_locale
;
13701 hkl_orig
= GetKeyboardLayout( 0 );
13702 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
13705 skip( "Default codepage %d\n", cp
);
13709 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
13710 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
13712 skip( "Unable to load Greek keyboard layout\n" );
13716 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
13717 100, 100, 200, 200, 0, 0, 0, NULL
);
13720 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
13722 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
13724 if (!ignore_message( msg
.message
)) break;
13727 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13728 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13729 ok( msg
.wParam
== 0x3b1, "bad wparam %lx\n", msg
.wParam
);
13730 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
13732 DispatchMessageW( &msg
);
13734 memset( seq
, 0, sizeof(seq
) );
13735 seq
[0].message
= WM_CHAR
;
13736 seq
[0].flags
= sent
|wparam
;
13737 seq
[0].wParam
= 0x3b1;
13739 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
13743 /* greek alpha -> 'a' in cp1252 */
13744 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
13746 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
13747 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13748 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13749 ok( msg
.wParam
== 0x61, "bad wparam %lx\n", msg
.wParam
);
13750 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
13752 DispatchMessageA( &msg
);
13754 seq
[0].wParam
= 0x61;
13755 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
13757 thread_locale
= GetThreadLocale();
13758 ActivateKeyboardLayout( hkl_greek
, 0 );
13759 ok( GetThreadLocale() == thread_locale
, "locale changed from %08x to %08x\n",
13760 thread_locale
, GetThreadLocale() );
13764 /* greek alpha -> 0xe1 in cp1253 */
13765 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
13767 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
13768 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
13769 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
13770 ok( msg
.wParam
== 0xe1, "bad wparam %lx\n", msg
.wParam
);
13771 ok( msg
.lParam
== 0, "bad lparam %lx\n", msg
.lParam
);
13773 DispatchMessageA( &msg
);
13775 seq
[0].wParam
= 0x3b1;
13776 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
13778 DestroyWindow( hwnd
);
13779 ActivateKeyboardLayout( hkl_orig
, 0 );
13780 UnloadKeyboardLayout( hkl_greek
);
13783 #define ID_LISTBOX 0x000f
13785 static const struct message wm_lb_setcursel_0
[] =
13787 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
13788 { WM_CTLCOLORLISTBOX
, sent
|parent
},
13789 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
13790 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
13791 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
13794 static const struct message wm_lb_setcursel_1
[] =
13796 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
13797 { WM_CTLCOLORLISTBOX
, sent
|parent
},
13798 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
13799 { WM_CTLCOLORLISTBOX
, sent
|parent
},
13800 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
13801 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
13802 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 2 },
13805 static const struct message wm_lb_setcursel_2
[] =
13807 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
13808 { WM_CTLCOLORLISTBOX
, sent
|parent
},
13809 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
13810 { WM_CTLCOLORLISTBOX
, sent
|parent
},
13811 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
13812 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
13813 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
13816 static const struct message wm_lb_click_0
[] =
13818 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
13819 { HCBT_SETFOCUS
, hook
},
13820 { WM_KILLFOCUS
, sent
|parent
},
13821 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
13822 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13823 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13824 { WM_SETFOCUS
, sent
|defwinproc
},
13826 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
13827 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
13828 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 3 },
13829 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
13830 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
13832 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
13833 { WM_CTLCOLORLISTBOX
, sent
|parent
},
13834 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
13835 { WM_CTLCOLORLISTBOX
, sent
|parent
},
13836 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
13837 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
13839 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
13840 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 1 },
13842 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
13843 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
13844 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
13845 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
13848 static const struct message wm_lb_deletestring
[] =
13850 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
13851 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
13852 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
13853 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
13856 static const struct message wm_lb_deletestring_reset
[] =
13858 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
13859 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
13860 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
13861 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
13862 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
13866 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
13868 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
13870 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
13872 static LONG defwndproc_counter
= 0;
13874 struct recvd_message msg
;
13876 /* do not log painting messages */
13877 if (message
!= WM_PAINT
&&
13878 message
!= WM_NCPAINT
&&
13879 message
!= WM_SYNCPAINT
&&
13880 message
!= WM_ERASEBKGND
&&
13881 message
!= WM_NCHITTEST
&&
13882 message
!= WM_GETTEXT
&&
13883 !ignore_message( message
))
13886 msg
.message
= message
;
13887 msg
.flags
= sent
|wparam
|lparam
;
13888 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
13891 msg
.descr
= "listbox";
13895 defwndproc_counter
++;
13896 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
13897 defwndproc_counter
--;
13902 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
13903 int caret_index
, int top_index
, int line
)
13907 /* calling an orig proc helps to avoid unnecessary message logging */
13908 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
13909 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %ld\n", count
, ret
);
13910 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
13911 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %ld\n", cur_sel
, ret
);
13912 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
13913 ok_(__FILE__
, line
)(ret
== caret_index
||
13914 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
13915 "expected caret index %d, got %ld\n", caret_index
, ret
);
13916 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
13917 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %ld\n", top_index
, ret
);
13920 static void test_listbox_messages(void)
13922 HWND parent
, listbox
;
13925 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13926 100, 100, 200, 200, 0, 0, 0, NULL
);
13927 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
13928 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
13929 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
13930 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
13932 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
13934 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
13935 ok(ret
== 0, "expected 0, got %ld\n", ret
);
13936 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
13937 ok(ret
== 1, "expected 1, got %ld\n", ret
);
13938 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
13939 ok(ret
== 2, "expected 2, got %ld\n", ret
);
13941 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
13945 log_all_parent_messages
++;
13947 trace("selecting item 0\n");
13948 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
13949 ok(ret
== 0, "expected 0, got %ld\n", ret
);
13950 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
13951 check_lb_state(listbox
, 3, 0, 0, 0);
13954 trace("selecting item 1\n");
13955 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
13956 ok(ret
== 1, "expected 1, got %ld\n", ret
);
13957 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
13958 check_lb_state(listbox
, 3, 1, 1, 0);
13960 trace("selecting item 2\n");
13961 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
13962 ok(ret
== 2, "expected 2, got %ld\n", ret
);
13963 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
13964 check_lb_state(listbox
, 3, 2, 2, 0);
13966 trace("clicking on item 0\n");
13967 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
13968 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
13969 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
13970 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %ld\n", ret
);
13971 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
13972 check_lb_state(listbox
, 3, 0, 0, 0);
13975 trace("deleting item 0\n");
13976 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
13977 ok(ret
== 2, "expected 2, got %ld\n", ret
);
13978 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
13979 check_lb_state(listbox
, 2, -1, 0, 0);
13982 trace("deleting item 0\n");
13983 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
13984 ok(ret
== 1, "expected 1, got %ld\n", ret
);
13985 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
13986 check_lb_state(listbox
, 1, -1, 0, 0);
13989 trace("deleting item 0\n");
13990 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
13991 ok(ret
== 0, "expected 0, got %ld\n", ret
);
13992 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
13993 check_lb_state(listbox
, 0, -1, 0, 0);
13996 trace("deleting item 0\n");
13997 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
13998 ok(ret
== LB_ERR
, "expected LB_ERR, got %ld\n", ret
);
13999 check_lb_state(listbox
, 0, -1, 0, 0);
14002 log_all_parent_messages
--;
14004 DestroyWindow(listbox
);
14005 DestroyWindow(parent
);
14008 /*************************** Menu test ******************************/
14009 static const struct message wm_popup_menu_1
[] =
14011 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14012 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14013 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
14014 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
14015 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
14016 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
14017 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14018 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14019 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
14020 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
14021 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
14022 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
14023 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
14024 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14025 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
14026 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
14027 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14028 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14029 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14030 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
14031 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14032 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14035 static const struct message wm_popup_menu_2
[] =
14037 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14038 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14039 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
14040 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
14041 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
14042 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
14043 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14044 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14045 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
14046 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
14047 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
14048 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
14049 { HCBT_CREATEWND
, hook
},
14050 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
14051 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
14052 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
14053 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14054 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
14055 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
14056 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
14057 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
14058 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
14059 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
14060 { HCBT_DESTROYWND
, hook
},
14061 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14062 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
14063 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14064 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14065 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14066 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
14067 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14068 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14071 static const struct message wm_popup_menu_3
[] =
14073 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14074 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14075 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
14076 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
14077 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
14078 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
14079 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14080 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14081 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
14082 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
14083 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
14084 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
14085 { HCBT_CREATEWND
, hook
},
14086 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
14087 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
14088 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
14089 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
14090 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
14091 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
14092 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
14093 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
14094 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
14095 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
14096 { HCBT_DESTROYWND
, hook
},
14097 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14098 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
14099 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
14100 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14101 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14102 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
14103 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
14104 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
14108 static const struct message wm_single_menu_item
[] =
14110 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
14111 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
14112 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
14113 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
14114 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
14115 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
14116 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14117 { WM_INITMENU
, sent
|lparam
, 0, 0 },
14118 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
14119 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
14120 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
14121 { WM_MENUCOMMAND
, sent
},
14122 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
14123 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
14124 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
14125 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
14127 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
14128 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
14129 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
14130 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
14131 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
14135 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14137 if (message
== WM_ENTERIDLE
||
14138 message
== WM_INITMENU
||
14139 message
== WM_INITMENUPOPUP
||
14140 message
== WM_MENUSELECT
||
14141 message
== WM_PARENTNOTIFY
||
14142 message
== WM_ENTERMENULOOP
||
14143 message
== WM_EXITMENULOOP
||
14144 message
== WM_UNINITMENUPOPUP
||
14145 message
== WM_KEYDOWN
||
14146 message
== WM_KEYUP
||
14147 message
== WM_CHAR
||
14148 message
== WM_SYSKEYDOWN
||
14149 message
== WM_SYSKEYUP
||
14150 message
== WM_SYSCHAR
||
14151 message
== WM_COMMAND
||
14152 message
== WM_MENUCOMMAND
)
14154 struct recvd_message msg
;
14157 msg
.message
= message
;
14158 msg
.flags
= sent
|wparam
|lparam
;
14161 msg
.descr
= "parent_menu_proc";
14165 return DefWindowProcA(hwnd
, message
, wp
, lp
);
14168 static void set_menu_style(HMENU hmenu
, DWORD style
)
14173 mi
.cbSize
= sizeof(mi
);
14174 mi
.fMask
= MIM_STYLE
;
14175 mi
.dwStyle
= style
;
14176 SetLastError(0xdeadbeef);
14177 ret
= pSetMenuInfo(hmenu
, &mi
);
14178 ok(ret
, "SetMenuInfo error %u\n", GetLastError());
14181 static DWORD
get_menu_style(HMENU hmenu
)
14186 mi
.cbSize
= sizeof(mi
);
14187 mi
.fMask
= MIM_STYLE
;
14189 SetLastError(0xdeadbeef);
14190 ret
= pGetMenuInfo(hmenu
, &mi
);
14191 ok(ret
, "GetMenuInfo error %u\n", GetLastError());
14196 static void test_menu_messages(void)
14200 HMENU hmenu
, hmenu_popup
;
14204 if (!pGetMenuInfo
|| !pSetMenuInfo
)
14206 win_skip("GetMenuInfo and/or SetMenuInfo are not available\n");
14210 cls
.lpfnWndProc
= parent_menu_proc
;
14211 cls
.cbClsExtra
= 0;
14212 cls
.cbWndExtra
= 0;
14213 cls
.hInstance
= GetModuleHandleA(0);
14215 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
14216 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
14217 cls
.lpszMenuName
= NULL
;
14218 cls
.lpszClassName
= "TestMenuClass";
14219 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
14220 if (!RegisterClassA(&cls
)) assert(0);
14222 SetLastError(0xdeadbeef);
14223 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14224 100, 100, 200, 200, 0, 0, 0, NULL
);
14225 ok(hwnd
!= 0, "LoadMenuA error %u\n", GetLastError());
14227 SetLastError(0xdeadbeef);
14228 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
14229 ok(hmenu
!= 0, "LoadMenuA error %u\n", GetLastError());
14231 SetMenu(hwnd
, hmenu
);
14232 SetForegroundWindow( hwnd
);
14235 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
14236 style
= get_menu_style(hmenu
);
14237 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
14239 hmenu_popup
= GetSubMenu(hmenu
, 0);
14240 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14241 style
= get_menu_style(hmenu_popup
);
14242 ok(style
== 0, "expected 0, got %u\n", style
);
14244 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
14245 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14246 style
= get_menu_style(hmenu_popup
);
14247 ok(style
== 0, "expected 0, got %u\n", style
);
14250 trace("testing a popup menu command\n");
14252 keybd_event(VK_MENU
, 0, 0, 0);
14253 keybd_event('E', 0, 0, 0);
14254 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
14255 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
14256 keybd_event(VK_RETURN
, 0, 0, 0);
14257 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
14258 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14260 TranslateMessage(&msg
);
14261 DispatchMessageA(&msg
);
14263 if (!sequence_cnt
) /* we didn't get any message */
14265 skip( "queuing key events not supported\n" );
14268 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
14269 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
14271 win_skip( "menu tracking through VK_MENU not supported\n" );
14274 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
14276 /* Alt+F, Right, Enter */
14277 trace("testing submenu of a popup menu command\n");
14279 keybd_event(VK_MENU
, 0, 0, 0);
14280 keybd_event('F', 0, 0, 0);
14281 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
14282 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
14283 keybd_event(VK_RIGHT
, 0, 0, 0);
14284 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
14285 keybd_event(VK_RETURN
, 0, 0, 0);
14286 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
14287 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14289 TranslateMessage(&msg
);
14290 DispatchMessageA(&msg
);
14292 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
14294 trace("testing single menu item command\n");
14296 keybd_event(VK_MENU
, 0, 0, 0);
14297 keybd_event('Q', 0, 0, 0);
14298 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
14299 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
14300 keybd_event(VK_ESCAPE
, 0, 0, 0);
14301 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
14302 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14304 TranslateMessage(&msg
);
14305 DispatchMessageA(&msg
);
14307 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
14309 set_menu_style(hmenu
, 0);
14310 style
= get_menu_style(hmenu
);
14311 ok(style
== 0, "expected 0, got %u\n", style
);
14313 hmenu_popup
= GetSubMenu(hmenu
, 0);
14314 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14315 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
14316 style
= get_menu_style(hmenu_popup
);
14317 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %u\n", style
);
14319 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
14320 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
14321 style
= get_menu_style(hmenu_popup
);
14322 ok(style
== 0, "expected 0, got %u\n", style
);
14324 /* Alt+F, Right, Enter */
14325 trace("testing submenu of a popup menu command\n");
14327 keybd_event(VK_MENU
, 0, 0, 0);
14328 keybd_event('F', 0, 0, 0);
14329 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
14330 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
14331 keybd_event(VK_RIGHT
, 0, 0, 0);
14332 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
14333 keybd_event(VK_RETURN
, 0, 0, 0);
14334 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
14335 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14337 TranslateMessage(&msg
);
14338 DispatchMessageA(&msg
);
14340 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
14343 DestroyWindow(hwnd
);
14344 DestroyMenu(hmenu
);
14348 static void test_paintingloop(void)
14352 paint_loop_done
= FALSE
;
14353 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
14354 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
14355 100, 100, 100, 100, 0, 0, 0, NULL
);
14356 ok(hwnd
!= 0, "PaintLoop window error %u\n", GetLastError());
14357 ShowWindow(hwnd
,SW_NORMAL
);
14360 while (!paint_loop_done
)
14363 if (PeekMessageA(&msg
, 0, 0, 0, 1))
14365 TranslateMessage(&msg
);
14366 DispatchMessageA(&msg
);
14369 DestroyWindow(hwnd
);
14372 static const struct message NCRBUTTONDOWNSeq
[] =
14374 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
14375 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
14376 { WM_CAPTURECHANGED
, sent
},
14377 { WM_CONTEXTMENU
, sent
, /*hwnd*/0, -1 },
14381 struct rbuttonup_thread_data
14384 HANDLE wndproc_finished
;
14387 static DWORD CALLBACK
post_rbuttonup_msg( void *arg
)
14389 struct rbuttonup_thread_data
*data
= arg
;
14392 ret
= WaitForSingleObject( data
->wndproc_finished
, 500 );
14393 todo_wine
ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %x\n", ret
);
14394 if( ret
== WAIT_OBJECT_0
) return 0;
14396 PostMessageA( data
->hwnd
, WM_RBUTTONUP
, 0, 0 );
14400 static void test_defwinproc(void)
14404 BOOL gotwmquit
= FALSE
;
14409 struct rbuttonup_thread_data data
;
14412 hwnd
= CreateWindowExA(0, "TestWindowClass", "test_defwndproc",
14413 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0,0,500,100,0,0,0, NULL
);
14417 GetCursorPos(&pos
);
14418 GetWindowRect(hwnd
, &rect
);
14419 x
= (rect
.left
+rect
.right
) / 2;
14420 y
= rect
.top
+ GetSystemMetrics(SM_CYFRAME
) + 1;
14421 SetCursorPos(x
, y
);
14423 res
= DefWindowProcA( hwnd
, WM_NCHITTEST
, 0, MAKELPARAM(x
, y
));
14424 ok(res
== HTCAPTION
, "WM_NCHITTEST returned %ld\n", res
);
14426 mouse_event( MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0 );
14427 mouse_event( MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0 );
14431 mouse_event( MOUSEEVENTF_RIGHTUP
, 0, 0, 0, 0 );
14432 /* workaround for missing support for clicking on window frame */
14434 data
.wndproc_finished
= CreateEventA( NULL
, FALSE
, FALSE
, NULL
);
14435 thread
= CreateThread( NULL
, 0, post_rbuttonup_msg
, (void*)&data
, 0, NULL
);
14437 DefWindowProcA( hwnd
, WM_NCRBUTTONDOWN
, HTCAPTION
, MAKELPARAM(x
, y
));
14438 ok_sequence(NCRBUTTONDOWNSeq
, "WM_NCRBUTTONDOWN on caption", FALSE
);
14440 SetEvent( data
.wndproc_finished
);
14441 WaitForSingleObject( thread
, 1000 );
14442 CloseHandle( data
.wndproc_finished
);
14443 CloseHandle( thread
);
14445 SetCursorPos(pos
.x
, pos
.y
);
14447 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
14448 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
14449 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
14450 DispatchMessageA( &msg
);
14452 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
14453 DestroyWindow( hwnd
);
14456 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
14457 static void clear_clipboard_(int line
, HWND hWnd
)
14460 succ
= OpenClipboard(hWnd
);
14461 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%u\n", GetLastError());
14462 succ
= EmptyClipboard();
14463 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%u\n", GetLastError());
14464 succ
= CloseClipboard();
14465 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%u\n", GetLastError());
14468 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
14469 static void expect_HWND_(int line
, HWND expected
, HWND got
)
14471 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
14474 static WNDPROC pOldViewerProc
;
14476 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14478 static BOOL recursion_guard
;
14480 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
14482 recursion_guard
= TRUE
;
14483 clear_clipboard(hWnd
);
14484 recursion_guard
= FALSE
;
14486 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
14489 static void test_clipboard_viewers(void)
14491 static struct message wm_change_cb_chain
[] =
14493 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
14496 static const struct message wm_clipboard_destroyed
[] =
14498 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
14501 static struct message wm_clipboard_changed
[] =
14503 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
14506 static struct message wm_clipboard_changed_and_owned
[] =
14508 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
14509 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
14513 HINSTANCE hInst
= GetModuleHandleA(NULL
);
14514 HWND hWnd1
, hWnd2
, hWnd3
;
14518 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
14519 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
14520 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
14521 GetDesktopWindow(), NULL
, hInst
, NULL
);
14522 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
14523 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
14524 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
14525 GetDesktopWindow(), NULL
, hInst
, NULL
);
14526 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
14527 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
14528 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
14529 GetDesktopWindow(), NULL
, hInst
, NULL
);
14530 trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
14531 assert(hWnd1
&& hWnd2
&& hWnd3
);
14533 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */
14536 /* Test getting the clipboard viewer and setting the viewer to NULL. */
14537 hOrigViewer
= GetClipboardViewer();
14538 hRet
= SetClipboardViewer(NULL
);
14539 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
14540 expect_HWND(hOrigViewer
, hRet
);
14541 expect_HWND(NULL
, GetClipboardViewer());
14543 /* Test registering hWnd1 as a viewer. */
14544 hRet
= SetClipboardViewer(hWnd1
);
14545 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
14546 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
14547 expect_HWND(NULL
, hRet
);
14548 expect_HWND(hWnd1
, GetClipboardViewer());
14550 /* Test that changing the clipboard actually refreshes the registered viewer. */
14551 clear_clipboard(hWnd1
);
14552 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
14553 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
14555 /* Again, but with different owner. */
14556 clear_clipboard(hWnd2
);
14557 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
14558 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
14560 /* Test re-registering same window. */
14561 hRet
= SetClipboardViewer(hWnd1
);
14562 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
14563 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
14564 expect_HWND(hWnd1
, hRet
);
14565 expect_HWND(hWnd1
, GetClipboardViewer());
14567 /* Test ChangeClipboardChain. */
14568 ChangeClipboardChain(hWnd2
, hWnd3
);
14569 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
14570 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
14571 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
14572 expect_HWND(hWnd1
, GetClipboardViewer());
14574 ChangeClipboardChain(hWnd2
, NULL
);
14575 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
14576 wm_change_cb_chain
[0].lParam
= 0;
14577 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
14578 expect_HWND(hWnd1
, GetClipboardViewer());
14580 ChangeClipboardChain(NULL
, hWnd2
);
14581 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", FALSE
);
14582 expect_HWND(hWnd1
, GetClipboardViewer());
14584 /* Actually change clipboard viewer with ChangeClipboardChain. */
14585 ChangeClipboardChain(hWnd1
, hWnd2
);
14586 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
14587 expect_HWND(hWnd2
, GetClipboardViewer());
14589 /* Test that no refresh messages are sent when viewer has unregistered. */
14590 clear_clipboard(hWnd2
);
14591 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
14593 /* Register hWnd1 again. */
14594 ChangeClipboardChain(hWnd2
, hWnd1
);
14595 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
14596 expect_HWND(hWnd1
, GetClipboardViewer());
14598 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
14599 * changes the clipboard. When this happens, the system shouldn't send
14600 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
14602 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
14603 clear_clipboard(hWnd2
);
14604 /* The clipboard owner is changed in recursive_viewer_proc: */
14605 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
14606 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
14608 /* Test unregistering. */
14609 ChangeClipboardChain(hWnd1
, NULL
);
14610 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
14611 expect_HWND(NULL
, GetClipboardViewer());
14613 clear_clipboard(hWnd1
);
14614 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
14616 DestroyWindow(hWnd1
);
14617 DestroyWindow(hWnd2
);
14618 DestroyWindow(hWnd3
);
14619 SetClipboardViewer(hOrigViewer
);
14622 static void test_PostMessage(void)
14624 static const struct
14630 { HWND_TOP
/* 0 */, TRUE
},
14631 { HWND_BROADCAST
, TRUE
},
14632 { HWND_BOTTOM
, TRUE
},
14633 { HWND_TOPMOST
, TRUE
},
14634 { HWND_NOTOPMOST
, FALSE
},
14635 { HWND_MESSAGE
, FALSE
},
14636 { (HWND
)0xdeadbeef, FALSE
}
14642 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
14644 SetLastError(0xdeadbeef);
14645 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
14646 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
14648 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
14655 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
14656 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
14658 for (i
= 0; i
< sizeof(data
)/sizeof(data
[0]); i
++)
14660 memset(&msg
, 0xab, sizeof(msg
));
14661 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
14662 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
14666 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
14667 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
14668 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
14669 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
14671 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
14672 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
14673 "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
14674 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
14678 DestroyWindow(hwnd
);
14682 static LPARAM g_broadcast_lparam
;
14683 static LRESULT WINAPI
broadcast_test_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
14685 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
14687 if (wParam
== 0xbaadbeef)
14688 g_broadcast_lparam
= wParam
;
14690 g_broadcast_lparam
= 0;
14692 return CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
14695 static void test_broadcast(void)
14697 static const UINT messages
[] =
14703 0xc000, /* lowest possible atom returned by RegisterWindowMessage */
14710 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0, 0, 0, 0, 0, 0, 0, NULL
);
14711 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
14713 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_proc
);
14714 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
14716 for (i
= 0; i
< sizeof(messages
)/sizeof(messages
[0]); i
++)
14722 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14725 /* post, broadcast */
14726 ret
= PostMessageA(HWND_BROADCAST
, messages
[i
], 0, 0);
14727 ok(ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
14729 memset(&msg
, 0xab, sizeof(msg
));
14730 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
14731 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
14733 ok(ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
14734 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
14738 ok(!ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
14741 /* post, topmost */
14742 ret
= PostMessageA(HWND_TOPMOST
, messages
[i
], 0, 0);
14743 ok(ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
14745 memset(&msg
, 0xab, sizeof(msg
));
14746 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
14747 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
14749 ok(ret
, "%d: message %04x, got %d, error %d\n", i
, messages
[i
], ret
, GetLastError());
14750 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
14754 ok(!ret
, "%d: got %d, error %d\n", i
, ret
, GetLastError());
14757 /* send, broadcast */
14758 g_broadcast_lparam
= 0xdead;
14759 ret
= SendMessageTimeoutA(HWND_BROADCAST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
14760 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
14761 win_skip("broadcasting test %d, timeout\n", i
);
14764 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
14766 ok(g_broadcast_lparam
== 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
14767 g_broadcast_lparam
, GetLastError());
14771 ok(g_broadcast_lparam
== 0xdead, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
14772 g_broadcast_lparam
, GetLastError());
14776 /* send, topmost */
14777 g_broadcast_lparam
= 0xdead;
14778 ret
= SendMessageTimeoutA(HWND_TOPMOST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
14779 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
14780 win_skip("broadcasting test %d, timeout\n", i
);
14783 if (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000)
14785 ok(g_broadcast_lparam
== 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
14786 g_broadcast_lparam
, GetLastError());
14790 ok(g_broadcast_lparam
== 0xdead, "%d: message %04x, got %#lx, error %d\n", i
, messages
[i
],
14791 g_broadcast_lparam
, GetLastError());
14796 DestroyWindow(hwnd
);
14799 static const struct
14803 } wait_idle_expect
[] =
14805 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
14806 { WAIT_TIMEOUT
, 0, FALSE
},
14807 { WAIT_TIMEOUT
, 0, FALSE
},
14808 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
14809 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
14810 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
14811 { WAIT_TIMEOUT
, 0, FALSE
},
14812 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
14815 /* 10 */ { 0, 0, FALSE
},
14817 { 0, WAIT_TIMEOUT
, FALSE
},
14820 /* 15 */ { 0, 0, FALSE
},
14821 { WAIT_TIMEOUT
, 0, FALSE
},
14822 { WAIT_TIMEOUT
, 0, FALSE
},
14823 { WAIT_TIMEOUT
, 0, FALSE
},
14824 { WAIT_TIMEOUT
, 0, FALSE
},
14825 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
14828 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
14832 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14834 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
14838 static void do_wait_idle_child( int arg
)
14845 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
14846 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
14848 memset( &cls
, 0, sizeof(cls
) );
14849 cls
.lpfnWndProc
= DefWindowProcA
;
14850 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
14851 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
14852 cls
.lpszClassName
= "TestClass";
14853 RegisterClassA( &cls
);
14855 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
14857 ok( start_event
!= 0, "failed to create start event, error %u\n", GetLastError() );
14858 ok( end_event
!= 0, "failed to create end event, error %u\n", GetLastError() );
14863 SetEvent( start_event
);
14866 SetEvent( start_event
);
14868 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14871 SetEvent( start_event
);
14873 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14874 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
14875 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
14878 SetEvent( start_event
);
14880 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
14883 SetEvent( start_event
);
14885 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
14886 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
14889 SetEvent( start_event
);
14891 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
14892 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
14895 SetEvent( start_event
);
14897 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
14898 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
14900 GetMessageA( &msg
, 0, 0, 0 );
14901 DispatchMessageA( &msg
);
14905 SetEvent( start_event
);
14907 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
14908 SetTimer( hwnd
, 3, 1, NULL
);
14910 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
14913 SetEvent( start_event
);
14915 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14916 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
14919 SetEvent( start_event
);
14921 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
14922 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
14923 for (;;) GetMessageA( &msg
, 0, 0, 0 );
14926 SetEvent( start_event
);
14928 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
14929 SetTimer( hwnd
, 3, 1, NULL
);
14931 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
14934 SetEvent( start_event
);
14936 return; /* exiting the process makes WaitForInputIdle return success too */
14938 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14940 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
14941 SetEvent( start_event
);
14944 SetEvent( start_event
);
14945 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
14947 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
14948 WaitForSingleObject( thread
, 10000 );
14949 CloseHandle( thread
);
14952 SetEvent( start_event
);
14954 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
14957 SetEvent( start_event
);
14959 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
14962 SetEvent( start_event
);
14964 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
14967 SetEvent( start_event
);
14969 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
14972 SetEvent( start_event
);
14974 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
14977 SetEvent( start_event
);
14979 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
14982 SetEvent( start_event
);
14984 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
14987 WaitForSingleObject( end_event
, 2000 );
14988 CloseHandle( start_event
);
14989 CloseHandle( end_event
);
14990 if (hwnd
) DestroyWindow( hwnd
);
14993 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
14995 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
14996 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
14999 static DWORD CALLBACK
wait_idle_thread( void *arg
)
15005 memset( &cls
, 0, sizeof(cls
) );
15006 cls
.lpfnWndProc
= wait_idle_proc
;
15007 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
15008 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
15009 cls
.lpszClassName
= "TestClass";
15010 RegisterClassA( &cls
);
15012 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
15013 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
15014 DestroyWindow(hwnd
);
15018 static void test_WaitForInputIdle( char *argv0
)
15020 char path
[MAX_PATH
];
15021 PROCESS_INFORMATION pi
;
15022 STARTUPINFOA startup
;
15024 HANDLE start_event
, end_event
, thread
;
15027 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
15028 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
15029 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
15031 if (console_app
) /* build the test with -mwindows for better coverage */
15032 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
15034 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
15035 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
15036 ok(start_event
!= 0, "failed to create start event, error %u\n", GetLastError());
15037 ok(end_event
!= 0, "failed to create end event, error %u\n", GetLastError());
15039 memset( &startup
, 0, sizeof(startup
) );
15040 startup
.cb
= sizeof(startup
);
15041 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
15042 startup
.wShowWindow
= SW_SHOWNORMAL
;
15044 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
15046 for (i
= 0; i
< sizeof(wait_idle_expect
)/sizeof(wait_idle_expect
[0]); i
++)
15048 ResetEvent( start_event
);
15049 ResetEvent( end_event
);
15050 sprintf( path
, "%s msg %u", argv0
, i
);
15051 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
15052 ok( ret
, "CreateProcess '%s' failed err %u.\n", path
, GetLastError() );
15055 ret
= WaitForSingleObject( start_event
, 5000 );
15056 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
15057 if (ret
== WAIT_OBJECT_0
)
15059 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
15060 if (ret
== WAIT_FAILED
)
15062 ret
== wait_idle_expect
[i
].exp
||
15063 broken(ret
== wait_idle_expect
[i
].broken
),
15064 "%u: WaitForInputIdle error %08x expected %08x\n",
15065 i
, ret
, wait_idle_expect
[i
].exp
);
15066 else todo_wine_if (wait_idle_expect
[i
].todo
)
15067 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
15068 "%u: WaitForInputIdle error %08x expected %08x\n",
15069 i
, ret
, wait_idle_expect
[i
].exp
);
15070 SetEvent( end_event
);
15071 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
15073 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
15074 winetest_wait_child_process( pi
.hProcess
);
15075 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
15076 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
15077 CloseHandle( pi
.hProcess
);
15078 CloseHandle( pi
.hThread
);
15081 CloseHandle( start_event
);
15082 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
15083 WaitForSingleObject( thread
, 10000 );
15084 CloseHandle( thread
);
15087 static const struct message WmSetParentSeq_1
[] = {
15088 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15089 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15090 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
15091 { WM_CHILDACTIVATE
, sent
},
15092 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
15093 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
15094 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15095 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15099 static const struct message WmSetParentSeq_2
[] = {
15100 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15101 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15102 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15103 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15104 { HCBT_SETFOCUS
, hook
|optional
},
15105 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
15106 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
15107 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
15108 { WM_KILLFOCUS
, sent
|wparam
, 0 },
15109 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15110 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
15111 { HCBT_ACTIVATE
, hook
|optional
},
15112 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15113 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15114 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
15115 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
15116 { HCBT_SETFOCUS
, hook
|optional
},
15117 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15118 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
15119 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
15120 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
15121 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15122 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15123 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15124 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15125 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15130 static void test_SetParent(void)
15132 HWND parent1
, parent2
, child
, popup
;
15135 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
15136 100, 100, 200, 200, 0, 0, 0, NULL
);
15137 ok(parent1
!= 0, "Failed to create parent1 window\n");
15139 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
15140 400, 100, 200, 200, 0, 0, 0, NULL
);
15141 ok(parent2
!= 0, "Failed to create parent2 window\n");
15143 /* WS_CHILD window */
15144 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
15145 10, 10, 150, 150, parent1
, 0, 0, NULL
);
15146 ok(child
!= 0, "Failed to create child window\n");
15148 GetWindowRect(parent1
, &rc
);
15149 trace("parent1 %s\n", wine_dbgstr_rect(&rc
));
15150 GetWindowRect(child
, &rc_old
);
15151 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
15152 trace("child %s\n", wine_dbgstr_rect(&rc_old
));
15156 SetParent(child
, parent2
);
15158 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", TRUE
);
15160 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
15161 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
15163 GetWindowRect(parent2
, &rc
);
15164 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
15165 GetWindowRect(child
, &rc
);
15166 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
15167 trace("child %s\n", wine_dbgstr_rect(&rc
));
15169 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
15170 wine_dbgstr_rect(&rc
));
15172 /* WS_POPUP window */
15173 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
15174 20, 20, 100, 100, 0, 0, 0, NULL
);
15175 ok(popup
!= 0, "Failed to create popup window\n");
15177 GetWindowRect(popup
, &rc_old
);
15178 trace("popup %s\n", wine_dbgstr_rect(&rc_old
));
15182 SetParent(popup
, child
);
15184 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
15186 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
15187 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
15189 GetWindowRect(child
, &rc
);
15190 trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
15191 GetWindowRect(popup
, &rc
);
15192 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
15193 trace("popup %s\n", wine_dbgstr_rect(&rc
));
15195 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
15196 wine_dbgstr_rect(&rc
));
15198 DestroyWindow(popup
);
15199 DestroyWindow(child
);
15200 DestroyWindow(parent1
);
15201 DestroyWindow(parent2
);
15206 static const struct message WmKeyReleaseOnly
[] = {
15207 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
15208 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
15211 static const struct message WmKeyPressNormal
[] = {
15212 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
15213 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
15216 static const struct message WmKeyPressRepeat
[] = {
15217 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
15218 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
15221 static const struct message WmKeyReleaseNormal
[] = {
15222 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
15223 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
15227 static void test_keyflags(void)
15231 BYTE keyboard_state
[256];
15234 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15235 100, 100, 200, 200, 0, 0, 0, NULL
);
15240 /* keyup without a keydown */
15241 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
15242 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15243 DispatchMessageA(&msg
);
15244 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
15246 key_state
= GetAsyncKeyState(0x41);
15247 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15249 key_state
= GetKeyState(0x41);
15250 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15253 keybd_event(0x41, 0, 0, 0);
15254 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15255 DispatchMessageA(&msg
);
15256 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
15258 key_state
= GetAsyncKeyState(0x41);
15259 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15261 key_state
= GetKeyState(0x41);
15262 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15264 /* keydown repeat */
15265 keybd_event(0x41, 0, 0, 0);
15266 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15267 DispatchMessageA(&msg
);
15268 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
15270 key_state
= GetAsyncKeyState(0x41);
15271 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15273 key_state
= GetKeyState(0x41);
15274 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15277 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
15278 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15279 DispatchMessageA(&msg
);
15280 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
15282 key_state
= GetAsyncKeyState(0x41);
15283 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15285 key_state
= GetKeyState(0x41);
15286 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15288 /* set the key state in this thread */
15289 GetKeyboardState(keyboard_state
);
15290 keyboard_state
[0x41] = 0x80;
15291 SetKeyboardState(keyboard_state
);
15293 key_state
= GetAsyncKeyState(0x41);
15294 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15297 keybd_event(0x41, 0, 0, 0);
15298 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15299 DispatchMessageA(&msg
);
15300 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
15302 key_state
= GetAsyncKeyState(0x41);
15303 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15305 key_state
= GetKeyState(0x41);
15306 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15308 /* clear the key state in this thread */
15309 GetKeyboardState(keyboard_state
);
15310 keyboard_state
[0x41] = 0;
15311 SetKeyboardState(keyboard_state
);
15313 key_state
= GetAsyncKeyState(0x41);
15314 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15317 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
15318 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
15319 DispatchMessageA(&msg
);
15320 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
15322 key_state
= GetAsyncKeyState(0x41);
15323 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15325 key_state
= GetKeyState(0x41);
15326 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
15328 DestroyWindow(test_window
);
15332 static const struct message WmHotkeyPressLWIN
[] = {
15333 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
15334 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
15335 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
15338 static const struct message WmHotkeyPress
[] = {
15339 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
15340 { WM_HOTKEY
, sent
|wparam
, 5 },
15343 static const struct message WmHotkeyRelease
[] = {
15344 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
15345 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
15346 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
15349 static const struct message WmHotkeyReleaseLWIN
[] = {
15350 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
15351 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
15352 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
15355 static const struct message WmHotkeyCombined
[] = {
15356 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
15357 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
15358 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
15359 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
15360 { WM_APP
, sent
, 0, 0 },
15361 { WM_HOTKEY
, sent
|wparam
, 5 },
15362 { WM_APP
+1, sent
, 0, 0 },
15363 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
15364 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
15365 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
15366 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
15367 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
15368 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
15371 static const struct message WmHotkeyPrevious
[] = {
15372 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
15373 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
15374 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
15375 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
15376 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
15377 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
15378 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
15379 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
15380 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
15381 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
15382 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
15383 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
15386 static const struct message WmHotkeyNew
[] = {
15387 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
15388 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
15389 { WM_HOTKEY
, sent
|wparam
, 5 },
15390 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
15391 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
15395 static int hotkey_letter
;
15397 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
15399 struct recvd_message msg
;
15401 if (nCode
== HC_ACTION
)
15403 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
15406 msg
.message
= wParam
;
15407 msg
.flags
= kbd_hook
|wparam
|lparam
;
15408 msg
.wParam
= kdbhookstruct
->vkCode
;
15409 msg
.lParam
= kdbhookstruct
->flags
;
15410 msg
.descr
= "KeyboardHookProc";
15413 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
)
15415 ok(kdbhookstruct
->vkCode
== VK_LWIN
|| kdbhookstruct
->vkCode
== hotkey_letter
,
15416 "unexpected keycode %x\n", kdbhookstruct
->vkCode
);
15420 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
15423 static void test_hotkey(void)
15425 HWND test_window
, taskbar_window
;
15428 DWORD queue_status
;
15431 SetLastError(0xdeadbeef);
15432 ret
= UnregisterHotKey(NULL
, 0);
15433 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
15434 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
15435 "unexpected error %d\n", GetLastError());
15439 skip("hotkeys not supported\n");
15443 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15444 100, 100, 200, 200, 0, 0, 0, NULL
);
15448 SetLastError(0xdeadbeef);
15449 ret
= UnregisterHotKey(test_window
, 0);
15450 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
15451 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
15452 "unexpected error %d\n", GetLastError());
15454 /* Search for a Windows Key + letter combination that hasn't been registered */
15455 for (hotkey_letter
= 0x41; hotkey_letter
<= 0x51; hotkey_letter
++)
15457 SetLastError(0xdeadbeef);
15458 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
15466 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
15467 "unexpected error %d\n", GetLastError());
15471 if (hotkey_letter
== 0x52)
15473 ok(0, "Couldn't find any free Windows Key + letter combination\n");
15477 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
15478 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
15480 /* Same key combination, different id */
15481 SetLastError(0xdeadbeef);
15482 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
15483 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
15484 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
15485 "unexpected error %d\n", GetLastError());
15487 /* Same key combination, different window */
15488 SetLastError(0xdeadbeef);
15489 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
15490 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
15491 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
15492 "unexpected error %d\n", GetLastError());
15494 /* Register the same hotkey twice */
15495 SetLastError(0xdeadbeef);
15496 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
15497 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
15498 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
15499 "unexpected error %d\n", GetLastError());
15501 /* Window on another thread */
15502 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
15503 if (!taskbar_window
)
15505 skip("no taskbar?\n");
15509 SetLastError(0xdeadbeef);
15510 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
15511 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
15512 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
15513 "unexpected error %d\n", GetLastError());
15516 /* Inject the appropriate key sequence */
15517 keybd_event(VK_LWIN
, 0, 0, 0);
15518 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15519 DispatchMessageA(&msg
);
15520 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
15522 keybd_event(hotkey_letter
, 0, 0, 0);
15523 queue_status
= GetQueueStatus(QS_HOTKEY
);
15524 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
15525 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15527 if (msg
.message
== WM_HOTKEY
)
15529 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
15530 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
15532 DispatchMessageA(&msg
);
15534 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
15536 queue_status
= GetQueueStatus(QS_HOTKEY
);
15537 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status
);
15539 key_state
= GetAsyncKeyState(hotkey_letter
);
15540 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
15542 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
15543 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15544 DispatchMessageA(&msg
);
15545 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
15547 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
15548 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15549 DispatchMessageA(&msg
);
15550 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
15552 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
15553 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
15554 queue_status
= GetQueueStatus(QS_HOTKEY
);
15555 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status
);
15556 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
15557 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status
);
15558 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15559 DispatchMessageA(&msg
);
15562 /* Send and process all messages at once */
15563 PostMessageA(test_window
, WM_APP
, 0, 0);
15564 keybd_event(VK_LWIN
, 0, 0, 0);
15565 keybd_event(hotkey_letter
, 0, 0, 0);
15566 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
15567 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
15569 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15571 if (msg
.message
== WM_HOTKEY
)
15573 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
15574 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
15576 DispatchMessageA(&msg
);
15578 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
15580 /* Register same hwnd/id with different key combination */
15581 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
15582 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
15584 /* Previous key combination does not work */
15585 keybd_event(VK_LWIN
, 0, 0, 0);
15586 keybd_event(hotkey_letter
, 0, 0, 0);
15587 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
15588 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
15590 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15591 DispatchMessageA(&msg
);
15592 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
15594 /* New key combination works */
15595 keybd_event(hotkey_letter
, 0, 0, 0);
15596 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
15598 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15600 if (msg
.message
== WM_HOTKEY
)
15602 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
15603 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
15605 DispatchMessageA(&msg
);
15607 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
15609 /* Unregister hotkey properly */
15610 ret
= UnregisterHotKey(test_window
, 5);
15611 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
15613 /* Unregister hotkey again */
15614 SetLastError(0xdeadbeef);
15615 ret
= UnregisterHotKey(test_window
, 5);
15616 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
15617 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
15618 "unexpected error %d\n", GetLastError());
15620 /* Register thread hotkey */
15621 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
15622 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
15624 /* Inject the appropriate key sequence */
15625 keybd_event(VK_LWIN
, 0, 0, 0);
15626 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15628 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
15629 DispatchMessageA(&msg
);
15631 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
15633 keybd_event(hotkey_letter
, 0, 0, 0);
15634 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15636 if (msg
.message
== WM_HOTKEY
)
15638 struct recvd_message message
;
15639 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
15640 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %lx\n", msg
.lParam
);
15641 message
.message
= msg
.message
;
15642 message
.flags
= sent
|wparam
|lparam
;
15643 message
.wParam
= msg
.wParam
;
15644 message
.lParam
= msg
.lParam
;
15645 message
.descr
= "test_hotkey thread message";
15646 add_message(&message
);
15649 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
15650 DispatchMessageA(&msg
);
15652 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
15654 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
15655 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15657 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
15658 DispatchMessageA(&msg
);
15660 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
15662 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
15663 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
15665 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
15666 DispatchMessageA(&msg
);
15668 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
15670 /* Unregister thread hotkey */
15671 ret
= UnregisterHotKey(NULL
, 5);
15672 ok(ret
== TRUE
, "expected TRUE, got %i, err=%d\n", ret
, GetLastError());
15674 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
15678 UnregisterHotKey(NULL
, 5);
15679 UnregisterHotKey(test_window
, 5);
15680 DestroyWindow(test_window
);
15685 static const struct message WmSetFocus_1
[] = {
15686 { HCBT_SETFOCUS
, hook
}, /* child */
15687 { HCBT_ACTIVATE
, hook
}, /* parent */
15688 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
15689 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
15690 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
15691 { WM_NCACTIVATE
, sent
|parent
},
15692 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
15693 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
15694 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
15695 { HCBT_SETFOCUS
, hook
}, /* parent */
15696 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
15697 { WM_KILLFOCUS
, sent
|parent
},
15698 { WM_SETFOCUS
, sent
},
15701 static const struct message WmSetFocus_2
[] = {
15702 { HCBT_SETFOCUS
, hook
}, /* parent */
15703 { WM_KILLFOCUS
, sent
},
15704 { WM_SETFOCUS
, sent
|parent
},
15707 static const struct message WmSetFocus_3
[] = {
15708 { HCBT_SETFOCUS
, hook
}, /* child */
15712 static void test_SetFocus(void)
15714 HWND parent
, old_parent
, child
, old_focus
, old_active
;
15716 struct wnd_event wnd_event
;
15720 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
15721 ok(wnd_event
.start_event
!= 0, "CreateEvent error %d\n", GetLastError());
15722 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
15723 ok(hthread
!= 0, "CreateThread error %d\n", GetLastError());
15724 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
15725 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
15726 CloseHandle(wnd_event
.start_event
);
15728 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
15729 0, 0, 0, 0, 0, 0, 0, NULL
);
15730 ok(parent
!= 0, "failed to create parent window\n");
15731 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
15732 0, 0, 0, 0, parent
, 0, 0, NULL
);
15733 ok(child
!= 0, "failed to create child window\n");
15735 trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
15738 SetActiveWindow(0);
15743 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
15744 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
15746 log_all_parent_messages
++;
15748 old_focus
= SetFocus(child
);
15749 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15750 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
15751 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
15752 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15753 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
15755 old_focus
= SetFocus(parent
);
15756 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15757 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
15758 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
15759 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15760 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15762 SetLastError(0xdeadbeef);
15763 old_focus
= SetFocus((HWND
)0xdeadbeef);
15764 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
15765 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
15766 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15767 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
15768 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
15769 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15770 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15772 SetLastError(0xdeadbeef);
15773 old_focus
= SetFocus(GetDesktopWindow());
15774 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
15775 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
15776 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15777 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
15778 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
15779 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15780 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15782 SetLastError(0xdeadbeef);
15783 old_focus
= SetFocus(wnd_event
.hwnd
);
15784 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
15785 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
15786 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15787 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
15788 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
15789 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15790 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15792 SetLastError(0xdeadbeef);
15793 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
15794 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
15795 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError());
15796 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15797 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
15798 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
15799 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15800 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15802 SetLastError(0xdeadbeef);
15803 old_active
= SetActiveWindow(GetDesktopWindow());
15805 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
15806 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15807 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
15808 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
15809 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15810 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15812 SetLastError(0xdeadbeef);
15813 old_active
= SetActiveWindow(wnd_event
.hwnd
);
15815 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
15816 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15817 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
15818 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
15819 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15820 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15822 SetLastError(0xdeadbeef);
15823 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
15824 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
15826 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15827 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15832 old_focus
= SetFocus(wnd_event
.hwnd
);
15833 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15834 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
15835 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
15836 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
15838 old_focus
= SetFocus(parent
);
15839 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15840 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
15841 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15842 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15847 old_active
= SetActiveWindow(wnd_event
.hwnd
);
15848 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15849 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
15850 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
15851 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
15853 SetLastError(0xdeadbeef);
15854 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
15855 ok(ret
, "AttachThreadInput error %d\n", GetLastError());
15857 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
15858 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
15860 old_parent
= SetParent(child
, GetDesktopWindow());
15861 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
15863 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
15864 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
15866 old_focus
= SetFocus(parent
);
15867 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15868 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
15869 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15870 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15875 SetLastError(0xdeadbeef);
15876 old_focus
= SetFocus(child
);
15878 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
15879 broken(GetLastError() == 0) /* XP */ ||
15880 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
15881 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15882 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
15883 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
15884 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15885 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15887 SetLastError(0xdeadbeef);
15888 old_active
= SetActiveWindow(child
);
15889 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
15890 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
15891 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
15892 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
15893 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
15894 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
15896 log_all_parent_messages
--;
15898 DestroyWindow(child
);
15899 DestroyWindow(parent
);
15901 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
15902 ok(ret
, "PostMessage(WM_QUIT) error %d\n", GetLastError());
15903 ret
= WaitForSingleObject(hthread
, INFINITE
);
15904 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
15905 CloseHandle(hthread
);
15908 static const struct message WmSetLayeredStyle
[] = {
15909 { WM_STYLECHANGING
, sent
},
15910 { WM_STYLECHANGED
, sent
},
15911 { WM_GETTEXT
, sent
|defwinproc
|optional
},
15915 static const struct message WmSetLayeredStyle2
[] = {
15916 { WM_STYLECHANGING
, sent
},
15917 { WM_STYLECHANGED
, sent
},
15918 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15919 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
15920 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15921 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
15922 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
15926 struct layered_window_info
15935 static DWORD CALLBACK
update_layered_proc( void *param
)
15937 struct layered_window_info
*info
= param
;
15938 POINT src
= { 0, 0 };
15940 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
15941 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
15942 ok( info
->ret
, "failed\n");
15943 SetEvent( info
->event
);
15947 static void test_layered_window(void)
15958 struct layered_window_info info
;
15960 if (!pUpdateLayeredWindow
)
15962 win_skip( "UpdateLayeredWindow not supported\n" );
15966 hdc
= CreateCompatibleDC( 0 );
15967 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
15968 SelectObject( hdc
, bmp
);
15970 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
15971 100, 100, 300, 300, 0, 0, 0, NULL
);
15972 ok( hwnd
!= 0, "failed to create window\n" );
15973 ShowWindow( hwnd
, SW_SHOWNORMAL
);
15974 UpdateWindow( hwnd
);
15978 GetWindowRect( hwnd
, &rect
);
15979 GetClientRect( hwnd
, &client
);
15980 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
15981 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
15984 pos
.x
= pos
.y
= 300;
15985 size
.cx
= size
.cy
= 250;
15986 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
15987 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
15988 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
15989 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
15990 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
15992 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
15993 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
15994 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
15995 GetWindowRect( hwnd
, &rect
);
15996 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
15997 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
15998 GetClientRect( hwnd
, &rect
);
15999 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
16000 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16004 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16005 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16006 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16007 GetWindowRect( hwnd
, &rect
);
16008 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
16009 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16010 GetClientRect( hwnd
, &rect
);
16011 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
16012 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16014 SetWindowLongA( hwnd
, GWL_STYLE
,
16015 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
16016 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
16020 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16021 ok( ret
, "UpdateLayeredWindow failed err %u\n", GetLastError() );
16022 ok_sequence( WmEmptySeq
, "UpdateLayeredWindow", FALSE
);
16023 GetWindowRect( hwnd
, &rect
);
16024 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
16025 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16026 GetClientRect( hwnd
, &rect
);
16027 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
16028 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
16029 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16032 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16033 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16034 ok( GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == ERROR_MR_MID_NOT_FOUND
) ||
16035 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win7 */, "wrong error %u\n", GetLastError() );
16038 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
16039 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
16040 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
16042 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
16043 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
16044 GetWindowRect( hwnd
, &rect
);
16045 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
16046 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16047 GetClientRect( hwnd
, &rect
);
16048 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
16049 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
16050 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16052 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
16055 info
.size
.cx
= 250;
16056 info
.size
.cy
= 300;
16057 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
16059 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
16060 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
16061 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
16062 WaitForSingleObject( thread
, 1000 );
16063 CloseHandle( thread
);
16064 GetWindowRect( hwnd
, &rect
);
16065 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
16066 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
16067 GetClientRect( hwnd
, &rect
);
16068 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
16069 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
16070 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
16072 DestroyWindow( hwnd
);
16074 DeleteObject( bmp
);
16077 static HMENU hpopupmenu
;
16079 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16081 if (ignore_message( message
)) return 0;
16085 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
16089 case WM_INITMENUPOPUP
:
16090 case WM_UNINITMENUPOPUP
:
16091 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %lx\n", hpopupmenu
, wParam
);
16093 case WM_CAPTURECHANGED
:
16094 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %lx\n", lParam
);
16098 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
16101 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
16103 if (ignore_message( message
)) return 0;
16106 case WM_ENTERMENULOOP
:
16107 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
16111 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
16114 static void test_TrackPopupMenu(void)
16120 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
16123 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
16125 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
16127 hpopupmenu
= CreatePopupMenu();
16128 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
16130 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
16131 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
16135 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16136 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
16137 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
16139 /* Test popup closing with an ESC-press */
16141 PostMessageW(hwnd
, WM_KEYDOWN
, VK_ESCAPE
, 0);
16142 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16143 ok(ret
== 1, "TrackPopupMenu failed with error %i\n", GetLastError());
16144 PostQuitMessage(0);
16146 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
16148 TranslateMessage(&msg
);
16149 DispatchMessageA(&msg
);
16151 ok_sequence(WmTrackPopupMenuEsc
, "TrackPopupMenuEsc", FALSE
); /* Shouldn't get any message */
16153 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
16157 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16158 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
16159 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
16161 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
16167 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16168 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
16169 ok(ret
== 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError());
16171 DestroyMenu(hpopupmenu
);
16172 DestroyWindow(hwnd
);
16175 static void test_TrackPopupMenuEmpty(void)
16180 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
16183 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
16185 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
16187 hpopupmenu
= CreatePopupMenu();
16188 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
16192 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
16193 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
16194 ok(ret
== 0, "TrackPopupMenu succeeded\n");
16196 DestroyMenu(hpopupmenu
);
16197 DestroyWindow(hwnd
);
16200 static const struct message send_message_1
[] = {
16201 { WM_USER
+2, sent
|wparam
|lparam
, 0, 0 },
16202 { WM_USER
, sent
|wparam
|lparam
, 0, 0 },
16205 static const struct message send_message_2
[] = {
16206 { WM_USER
+4, sent
|wparam
|lparam
, 0, 0 },
16209 static const struct message send_message_3
[] = {
16210 { WM_USER
+3, sent
|wparam
|lparam
, 0, 0 },
16213 static const struct message send_message_4
[] = {
16214 { WM_USER
+1, sent
|wparam
|lparam
, 0, 0 },
16218 static DWORD WINAPI
SendMessage_thread_1(void *param
)
16220 struct wnd_event
*wnd_event
= param
;
16222 trace("thread: starting\n");
16223 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
16225 trace("thread: call PostMessage\n");
16226 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
16228 trace("thread: call PostMessage\n");
16229 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
16231 trace("thread: call SendMessage\n");
16232 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
16234 trace("thread: call SendMessage\n");
16235 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
16240 static DWORD WINAPI
SendMessage_thread_2(void *param
)
16242 struct wnd_event
*wnd_event
= param
;
16244 trace("thread: starting\n");
16245 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
16247 trace("thread: call PostMessage\n");
16248 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
16250 trace("thread: call PostMessage\n");
16251 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
16253 /* this leads to sending an internal message under Wine */
16254 trace("thread: call EnableWindow\n");
16255 EnableWindow(wnd_event
->hwnd
, TRUE
);
16257 trace("thread: call SendMessage\n");
16258 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
16260 trace("thread: call SendMessage\n");
16261 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
16266 static void test_SendMessage_other_thread(int thread_n
)
16268 DWORD qs_all_input
= QS_ALLINPUT
& ~QS_RAWINPUT
;
16270 struct wnd_event wnd_event
;
16274 wnd_event
.start_event
= CreateEventA(NULL
, 0, 0, NULL
);
16276 wnd_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
16277 100, 100, 200, 200, 0, 0, 0, NULL
);
16278 ok(wnd_event
.hwnd
!= 0, "CreateWindowEx failed\n");
16280 hthread
= CreateThread(NULL
, 0, thread_n
== 1 ? SendMessage_thread_1
: SendMessage_thread_2
, &wnd_event
, 0, &tid
);
16281 ok(hthread
!= NULL
, "CreateThread failed, error %d\n", GetLastError());
16282 CloseHandle(hthread
);
16287 ret
= GetQueueStatus(QS_SENDMESSAGE
);
16288 ok(ret
== 0, "wrong status %08x\n", ret
);
16290 SetEvent(wnd_event
.start_event
);
16292 /* wait for other thread's SendMessage */
16295 ret
= GetQueueStatus(QS_SENDMESSAGE
);
16296 if (ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
)) break;
16300 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
16301 ok(ret
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08x\n", ret
);
16303 trace("main: call GetMessage\n");
16304 GetMessageA(&msg
, 0, 0, 0);
16305 ok(msg
.message
== WM_USER
, "expected WM_USER, got %04x\n", msg
.message
);
16306 DispatchMessageA(&msg
);
16307 ok_sequence(send_message_1
, "SendMessage from other thread 1", thread_n
== 2);
16309 /* intentionally yield */
16310 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
16312 trace("main: call SendMessage\n");
16313 SendMessageA(wnd_event
.hwnd
, WM_USER
+4, 0, 0);
16314 ok_sequence(send_message_2
, "SendMessage from other thread 2", FALSE
);
16316 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
16317 ok(ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08x\n", ret
);
16319 trace("main: call PeekMessage\n");
16320 ok(PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should not fail\n");
16321 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
16322 ok_sequence(send_message_3
, "SendMessage from other thread 3", thread_n
== 2);
16324 trace("main: call PeekMessage\n");
16325 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should not fail\n");
16326 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
16327 DispatchMessageA(&msg
);
16328 ok_sequence(send_message_4
, "SendMessage from other thread 4", FALSE
);
16330 /* intentionally yield */
16331 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
16333 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
16334 /* FIXME: remove once Wine is fixed */
16335 todo_wine_if (thread_n
== 2)
16336 ok(ret
== 0, "wrong status %08x\n", ret
);
16338 trace("main: call PeekMessage\n");
16339 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should fail\n");
16340 ok_sequence(WmEmptySeq
, "SendMessage from other thread 5", thread_n
== 2);
16342 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
16343 ok(ret
== 0, "wrong status %08x\n", ret
);
16345 trace("main: call DestroyWindow\n");
16346 DestroyWindow(msg
.hwnd
);
16352 static LRESULT CALLBACK
insendmessage_wnd_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
16354 DWORD flags
= InSendMessageEx( NULL
);
16360 ok( flags
== ISMEX_SEND
, "wrong flags %x\n", flags
);
16361 ok( InSendMessage(), "InSendMessage returned false\n" );
16362 ret
= ReplyMessage( msg
);
16363 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
16364 flags
= InSendMessageEx( NULL
);
16365 ok( flags
== (ISMEX_SEND
| ISMEX_REPLIED
), "wrong flags %x\n", flags
);
16366 ok( InSendMessage(), "InSendMessage returned false\n" );
16369 ok( flags
== ISMEX_NOTIFY
, "wrong flags %x\n", flags
);
16370 ok( InSendMessage(), "InSendMessage returned false\n" );
16371 ret
= ReplyMessage( msg
);
16372 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
16373 flags
= InSendMessageEx( NULL
);
16374 ok( flags
== ISMEX_NOTIFY
, "wrong flags %x\n", flags
);
16375 ok( InSendMessage(), "InSendMessage returned false\n" );
16378 ok( flags
== ISMEX_CALLBACK
, "wrong flags %x\n", flags
);
16379 ok( InSendMessage(), "InSendMessage returned false\n" );
16380 ret
= ReplyMessage( msg
);
16381 ok( ret
, "ReplyMessage failed err %u\n", GetLastError() );
16382 flags
= InSendMessageEx( NULL
);
16383 ok( flags
== (ISMEX_CALLBACK
| ISMEX_REPLIED
) || flags
== ISMEX_SEND
, "wrong flags %x\n", flags
);
16384 ok( InSendMessage(), "InSendMessage returned false\n" );
16387 ok( flags
== ISMEX_NOSEND
, "wrong flags %x\n", flags
);
16388 ok( !InSendMessage(), "InSendMessage returned true\n" );
16389 ret
= ReplyMessage( msg
);
16390 ok( !ret
, "ReplyMessage succeeded\n" );
16394 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
16397 static void CALLBACK
msg_callback( HWND hwnd
, UINT msg
, ULONG_PTR arg
, LRESULT result
)
16399 ok( msg
== WM_USER
+ 2, "wrong msg %x\n", msg
);
16400 ok( result
== WM_USER
+ 2, "wrong result %lx\n", result
);
16403 static DWORD WINAPI
send_message_thread( void *arg
)
16407 SendMessageA( win
, WM_USER
, 0, 0 );
16408 SendNotifyMessageA( win
, WM_USER
+ 1, 0, 0 );
16409 SendMessageCallbackA( win
, WM_USER
+ 2, 0, 0, msg_callback
, 0 );
16410 PostMessageA( win
, WM_USER
+ 3, 0, 0 );
16411 PostMessageA( win
, WM_QUIT
, 0, 0 );
16415 static void test_InSendMessage(void)
16423 memset(&cls
, 0, sizeof(cls
));
16424 cls
.lpfnWndProc
= insendmessage_wnd_proc
;
16425 cls
.hInstance
= GetModuleHandleA(NULL
);
16426 cls
.lpszClassName
= "InSendMessage_test";
16427 RegisterClassA(&cls
);
16429 win
= CreateWindowA( "InSendMessage_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
16430 ok( win
!= NULL
, "CreateWindow failed: %d\n", GetLastError() );
16432 thread
= CreateThread( NULL
, 0, send_message_thread
, win
, 0, &tid
);
16433 ok( thread
!= NULL
, "CreateThread failed: %d\n", GetLastError() );
16435 while (GetMessageA(&msg
, NULL
, 0, 0)) DispatchMessageA( &msg
);
16437 ok( WaitForSingleObject( thread
, 30000 ) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
16438 CloseHandle( thread
);
16440 DestroyWindow( win
);
16441 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL
) );
16444 static const struct message DoubleSetCaptureSeq
[] =
16446 { WM_CAPTURECHANGED
, sent
},
16450 static void test_DoubleSetCapture(void)
16454 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture",
16455 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16456 100, 100, 200, 200, 0, 0, 0, NULL
);
16457 ok (hwnd
!= 0, "Failed to create overlapped window\n");
16459 ShowWindow( hwnd
, SW_SHOW
);
16460 UpdateWindow( hwnd
);
16464 SetCapture( hwnd
);
16465 SetCapture( hwnd
);
16466 ok_sequence(DoubleSetCaptureSeq
, "SetCapture( hwnd ) twice", FALSE
);
16468 DestroyWindow(hwnd
);
16471 static void init_funcs(void)
16473 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
16475 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
16478 X(DeactivateActCtx
);
16479 X(GetCurrentActCtx
);
16489 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
16490 HMODULE hModuleImm32
;
16491 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
16496 argc
= winetest_get_mainargs( &test_argv
);
16500 /* Child process. */
16501 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
16502 do_wait_idle_child( arg
);
16506 InitializeCriticalSection( &sequence_cs
);
16509 hModuleImm32
= LoadLibraryA("imm32.dll");
16510 if (hModuleImm32
) {
16511 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
16512 if (pImmDisableIME
)
16515 pImmDisableIME
= NULL
;
16516 FreeLibrary(hModuleImm32
);
16518 if (!RegisterWindowClasses()) assert(0);
16520 if (pSetWinEventHook
)
16522 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
16523 GetModuleHandleA(0), win_event_proc
,
16524 0, GetCurrentThreadId(),
16525 WINEVENT_INCONTEXT
);
16526 if (pIsWinEventHookInstalled
&& hEvent_hook
)
16529 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
16530 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
16533 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
16535 cbt_hook_thread_id
= GetCurrentThreadId();
16536 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
16537 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
16541 /* Fix message sequences before removing 4 lines below */
16542 if (pUnhookWinEvent
&& hEvent_hook
)
16544 ret
= pUnhookWinEvent(hEvent_hook
);
16545 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
16546 pUnhookWinEvent
= 0;
16550 test_SendMessage_other_thread(1);
16551 test_SendMessage_other_thread(2);
16552 test_InSendMessage();
16555 test_PostMessage();
16558 test_PeekMessage();
16559 test_PeekMessage2();
16560 test_PeekMessage3();
16561 test_WaitForInputIdle( test_argv
[0] );
16562 test_scrollwindowex();
16564 test_setwindowpos();
16566 invisible_parent_tests();
16567 test_mdi_messages();
16568 test_button_messages();
16569 test_static_messages();
16570 test_listbox_messages();
16571 test_combobox_messages();
16572 test_wmime_keydown_message();
16573 test_paint_messages();
16574 test_interthread_messages();
16575 test_message_conversion();
16576 test_accelerators();
16578 test_timers_no_wnd();
16579 test_timers_exceptions();
16583 test_recursive_hook();
16585 test_DestroyWindow();
16586 test_DispatchMessage();
16587 test_SendMessageTimeout();
16588 test_edit_messages();
16589 test_quit_message();
16590 test_notify_message();
16591 test_SetActiveWindow();
16593 if (!pTrackMouseEvent
)
16594 win_skip("TrackMouseEvent is not available\n");
16596 test_TrackMouseEvent();
16598 test_SetWindowRgn();
16600 test_dialog_messages();
16602 test_nullCallback();
16603 test_dbcs_wm_char();
16604 test_unicode_wm_char();
16605 test_menu_messages();
16606 test_paintingloop();
16608 test_clipboard_viewers();
16611 test_layered_window();
16612 test_TrackPopupMenu();
16613 test_TrackPopupMenuEmpty();
16614 test_DoubleSetCapture();
16615 /* keep it the last test, under Windows it tends to break the tests
16616 * which rely on active/foreground windows being correct.
16618 test_SetForegroundWindow();
16620 UnhookWindowsHookEx(hCBT_hook
);
16621 if (pUnhookWinEvent
&& hEvent_hook
)
16623 ret
= pUnhookWinEvent(hEvent_hook
);
16624 ok( ret
, "UnhookWinEvent error %d\n", GetLastError());
16625 SetLastError(0xdeadbeef);
16626 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
16627 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
16628 GetLastError() == 0xdeadbeef, /* Win9x */
16629 "unexpected error %d\n", GetLastError());
16631 DeleteCriticalSection( &sequence_cs
);