2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2004,2005,2016 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
37 #include "wine/test.h"
39 #define MDI_FIRST_CHILD_ID 2004
41 /* undocumented SWP flags - from SDK 3.1 */
42 #define SWP_NOCLIENTSIZE 0x0800
43 #define SWP_NOCLIENTMOVE 0x1000
44 #define SWP_STATECHANGED 0x8000
46 #define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
49 #define WM_KEYF1 0x004d
53 #define WM_SYSTIMER 0x0118
56 #define WND_PARENT_ID 1
57 #define WND_POPUP_ID 2
58 #define WND_CHILD_ID 3
60 #ifndef WM_LBTRACKPOINT
61 #define WM_LBTRACKPOINT 0x0131
66 #elif defined __aarch64__ || defined__arm64ec__
68 #elif defined __x86_64__
76 /* encoded DRAWITEMSTRUCT into an LPARAM */
83 UINT type
: 4; /* ODT_* flags */
84 UINT ctl_id
: 4; /* Control ID */
85 UINT item_id
: 4; /* Menu item ID */
86 UINT action
: 4; /* ODA_* flags */
87 UINT state
: 16; /* ODS_* flags */
93 /* encoded MEASUREITEMSTRUCT into a WPARAM */
107 } MEASURE_ITEM_STRUCT
;
109 static BOOL test_DestroyWindow_flag
;
110 static BOOL test_context_menu
;
111 static HWINEVENTHOOK hEvent_hook
;
112 static HHOOK hKBD_hook
;
113 static HHOOK hCBT_hook
;
114 static DWORD cbt_hook_thread_id
;
115 static DWORD winevent_hook_thread_id
;
117 static const WCHAR testWindowClassW
[] =
118 { 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
120 static LRESULT WINAPI
ParentMsgCheckProcA(HWND
, UINT
, WPARAM
, LPARAM
);
122 static void register_class(const WNDCLASSA
*class)
124 BOOL ret
= RegisterClassA(class);
125 ok(ret
, "Failed to register class %s, error %lu.\n",
126 debugstr_a(class->lpszClassName
), GetLastError());
130 FIXME: add tests for these
131 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
132 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
133 WS_THICKFRAME: thick border
134 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
135 WS_BORDER (default for overlapped windows): single black border
136 none (default for child (and popup?) windows): no border
156 UINT message
; /* the WM_* code */
157 msg_flags_t flags
; /* message props */
158 WPARAM wParam
; /* expected value of wParam */
159 LPARAM lParam
; /* expected value of lParam */
160 WPARAM wp_mask
; /* mask for wParam checks */
161 LPARAM lp_mask
; /* mask for lParam checks */
164 struct recvd_message
{
165 UINT message
; /* the WM_* code */
166 msg_flags_t flags
; /* message props */
167 HWND hwnd
; /* window that received the message */
168 WPARAM wParam
; /* expected value of wParam */
169 LPARAM lParam
; /* expected value of lParam */
170 int line
; /* source line where logged */
171 const char *descr
; /* description for trace output */
172 char output
[512]; /* trace output */
175 /* Empty message sequence */
176 static const struct message WmEmptySeq
[] =
180 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
181 static const struct message WmCreateOverlappedSeq
[] = {
182 { HCBT_CREATEWND
, hook
},
183 { WM_GETMINMAXINFO
, sent
},
184 { WM_NCCREATE
, sent
},
185 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
186 { 0x0093, sent
|defwinproc
|optional
},
187 { 0x0094, sent
|defwinproc
|optional
},
188 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
190 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
193 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
194 * for a not visible overlapped window.
196 static const struct message WmSWP_ShowOverlappedSeq
[] = {
197 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
198 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
199 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
200 { WM_GETTEXT
, sent
|defwinproc
|optional
},
201 { WM_ERASEBKGND
, sent
|optional
},
202 { HCBT_ACTIVATE
, hook
},
203 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
204 { WM_NOTIFYFORMAT
, sent
|optional
},
205 { WM_QUERYUISTATE
, sent
|optional
},
206 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
207 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x: SWP_NOSENDCHANGING */
208 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
209 { WM_NCACTIVATE
, sent
},
210 { WM_GETTEXT
, sent
|defwinproc
|optional
},
211 { WM_ACTIVATE
, sent
|wparam
, 1 },
212 { HCBT_SETFOCUS
, hook
},
213 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
214 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
215 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
216 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
217 { WM_GETTEXT
, sent
|optional
},
218 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
219 { WM_GETTEXT
, sent
|defwinproc
|optional
},
220 { WM_ERASEBKGND
, sent
|optional
},
221 /* Win9x adds SWP_NOZORDER below */
222 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
223 { WM_GETTEXT
, sent
|optional
},
224 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
225 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
226 { WM_ERASEBKGND
, sent
|optional
},
227 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10 */
228 { WM_SYNCPAINT
, sent
|optional
},
229 { WM_GETTITLEBARINFOEX
, sent
|optional
},
230 { WM_PAINT
, sent
|optional
},
231 { WM_NCPAINT
, sent
|beginpaint
|optional
},
232 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
233 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
236 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
237 * for a visible overlapped window.
239 static const struct message WmSWP_HideOverlappedSeq
[] = {
240 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
241 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
242 { HCBT_ACTIVATE
, hook
|optional
},
243 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
244 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
245 { WM_NCACTIVATE
, sent
|optional
},
246 { WM_ACTIVATE
, sent
|optional
},
247 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
251 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
252 * for a visible overlapped window.
254 static const struct message WmSWP_ResizeSeq
[] = {
255 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
256 { WM_GETMINMAXINFO
, sent
|defwinproc
},
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
|optional
},
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 },
268 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
272 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE)
273 * for a visible popup window.
275 static const struct message WmSWP_ResizePopupSeq
[] = {
276 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
},
277 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* Win9x */
278 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
279 { WM_NCPAINT
, sent
|optional
},
280 { WM_GETTEXT
, sent
|defwinproc
|optional
},
281 { WM_ERASEBKGND
, sent
|optional
},
282 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
283 { WM_SIZE
, sent
|defwinproc
|wparam
|optional
, SIZE_RESTORED
},
284 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
285 { WM_NCPAINT
, sent
|optional
},
286 { WM_GETTEXT
, sent
|defwinproc
|optional
},
287 { WM_ERASEBKGND
, sent
|optional
},
288 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
292 /* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE)
293 * for a visible overlapped window.
295 static const struct message WmSWP_MoveSeq
[] = {
296 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
},
297 { WM_NCPAINT
, sent
|optional
},
298 { WM_GETTEXT
, sent
|defwinproc
|optional
},
299 { WM_ERASEBKGND
, sent
|optional
},
300 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
301 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
302 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
305 /* Resize with SetWindowPos(SWP_NOZORDER)
306 * for a visible overlapped window
307 * SWP_NOZORDER is stripped by the logging code
309 static const struct message WmSWP_ResizeNoZOrder
[] = {
310 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
},
311 { WM_GETMINMAXINFO
, sent
|defwinproc
},
312 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
313 { WM_NCPAINT
, sent
|optional
},
314 { WM_GETTEXT
, sent
|defwinproc
|optional
},
315 { WM_ERASEBKGND
, sent
|optional
},
316 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, /*SWP_NOZORDER|*/SWP_NOACTIVATE
, 0,
317 SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
318 { WM_MOVE
, sent
|defwinproc
|optional
},
319 { WM_SIZE
, sent
|defwinproc
|optional
},
320 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
321 { WM_NCPAINT
, sent
|optional
}, /* Win9x doesn't send it */
322 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
323 { WM_ERASEBKGND
, sent
|optional
}, /* Win9x doesn't send it */
324 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
325 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
329 /* Switch visible mdi children */
330 static const struct message WmSwitchChild
[] = {
331 /* Switch MDI child */
332 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
333 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 1st MDI child */
334 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
335 { WM_CHILDACTIVATE
, sent
},/* in the 1st MDI child */
336 /* Deactivate 2nd MDI child */
337 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
338 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
339 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
340 /* Preparing for maximize and maximize the 1st MDI child */
341 { WM_GETMINMAXINFO
, sent
|defwinproc
}, /* in the 1st MDI child */
342 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
}, /* in the 1st MDI child */
343 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
344 { WM_CHILDACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
345 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 1st MDI child */
346 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
}, /* in the 1st MDI child */
347 /* Lock redraw 2nd MDI child */
348 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 0 }, /* in the 2nd MDI child */
349 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
350 /* Restore 2nd MDI child */
351 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},/* in the 2nd MDI child */
352 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
353 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
354 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
}, /* in the 2nd MDI child */
355 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
}, /* in the 2nd MDI child */
356 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 2nd MDI child */
357 /* Redraw 2nd MDI child */
358 { WM_SETREDRAW
, sent
|wparam
|defwinproc
, 1 },/* in the 2nd MDI child */
359 /* Redraw MDI frame */
360 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},/* in MDI frame */
361 { WM_NCCALCSIZE
, sent
|wparam
, 1 },/* in MDI frame */
362 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in MDI frame */
363 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in MDI frame */
364 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
365 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
366 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 1st MDI child */
367 { HCBT_SETFOCUS
, hook
},
368 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
369 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },/* in the 1st MDI child */
370 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
371 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
372 { WM_SETFOCUS
, sent
},/* in the MDI client */
373 { HCBT_SETFOCUS
, hook
},
374 { WM_KILLFOCUS
, sent
},/* in the MDI client */
375 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
376 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 }, /* in the 1st MDI child */
377 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
378 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
379 { WM_MDIACTIVATE
, sent
|defwinproc
},/* in the 1st MDI child */
380 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 1st MDI child */
384 /* Switch visible not maximized mdi children */
385 static const struct message WmSwitchNotMaximizedChild
[] = {
386 /* Switch not maximized MDI child */
387 { WM_MDIACTIVATE
, sent
},/* in the MDI client */
388 { WM_WINDOWPOSCHANGING
, sent
|wparam
,SWP_NOSIZE
|SWP_NOMOVE
},/* in the 2nd MDI child */
389 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
390 { WM_CHILDACTIVATE
, sent
},/* in the 2nd MDI child */
391 /* Deactivate 1st MDI child */
392 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
393 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
394 /* Activate 2nd MDI child */
395 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
}, /* in the 2nd MDI child */
396 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 }, /* in the 2nd MDI child */
397 { HCBT_SETFOCUS
, hook
}, /* in the 1st MDI child */
398 { WM_KILLFOCUS
, sent
|defwinproc
}, /* in the 1st MDI child */
399 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
400 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
401 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
402 { WM_SETFOCUS
, sent
, 0 }, /* in the MDI client */
403 { HCBT_SETFOCUS
, hook
},
404 { WM_KILLFOCUS
, sent
}, /* in the MDI client */
405 { WM_IME_SETCONTEXT
, sent
|optional
}, /* in the MDI client */
406 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
407 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
408 { WM_SETFOCUS
, sent
|defwinproc
}, /* in the 2nd MDI child */
409 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 2nd MDI child */
410 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
}, /* in the 2nd MDI child */
415 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
416 SWP_NOZORDER|SWP_FRAMECHANGED)
417 * for a visible overlapped window with WS_CLIPCHILDREN style set.
419 static const struct message WmSWP_FrameChanged_clip
[] = {
420 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
421 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
422 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
423 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
424 { WM_ERASEBKGND
, sent
|parent
|msg_todo
},
425 { WM_NCPAINT
, sent
}, /* wparam != 1 */
426 { WM_ERASEBKGND
, sent
},
427 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
428 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
432 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
433 SWP_NOZORDER|SWP_FRAMECHANGED)
434 * for a visible overlapped window.
436 static const struct message WmSWP_FrameChangedDeferErase
[] = {
437 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
438 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
439 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_DEFERERASE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
440 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
441 { WM_PAINT
, sent
|parent
|optional
},
442 { WM_NCPAINT
, sent
|beginpaint
|parent
|optional
}, /* wparam != 1 */
443 { WM_GETTEXT
, sent
|beginpaint
|parent
|defwinproc
|optional
},
445 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
446 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
450 /* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
451 SWP_NOZORDER|SWP_FRAMECHANGED)
452 * for a visible overlapped window without WS_CLIPCHILDREN style set.
454 static const struct message WmSWP_FrameChanged_noclip
[] = {
455 { WM_WINDOWPOSCHANGING
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
},
456 { WM_NCCALCSIZE
, sent
|wparam
|parent
, 1 },
457 { WM_NCPAINT
, sent
|parent
|optional
}, /* wparam != 1 */
458 { WM_GETTEXT
, sent
|parent
|defwinproc
|optional
},
459 { WM_ERASEBKGND
, sent
|parent
|optional
},
460 { WM_WINDOWPOSCHANGED
, sent
|wparam
|parent
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
461 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
463 { WM_NCPAINT
, sent
|beginpaint
}, /* wparam != 1 */
464 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
468 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
469 static const struct message WmShowOverlappedSeq
[] = {
470 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
471 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
472 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
473 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
474 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
475 { WM_GETTEXT
, sent
|defwinproc
|optional
},
476 { WM_ERASEBKGND
, sent
|optional
},
477 { HCBT_ACTIVATE
, hook
|optional
},
478 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
479 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
480 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
481 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
482 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
483 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
484 { WM_GETTEXT
, sent
|defwinproc
|optional
},
485 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
486 { HCBT_SETFOCUS
, hook
|optional
},
487 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
488 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
489 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
490 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
491 { WM_GETTEXT
, sent
|optional
},
492 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
493 { WM_GETTEXT
, sent
|defwinproc
|optional
},
494 { WM_ERASEBKGND
, sent
|optional
},
495 /* Win9x adds SWP_NOZORDER below */
496 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
497 { WM_NCCALCSIZE
, sent
|optional
},
498 { WM_GETTEXT
, sent
|optional
},
499 { WM_NCPAINT
, sent
|optional
},
500 { WM_ERASEBKGND
, sent
|optional
},
501 { WM_SYNCPAINT
, sent
|optional
},
502 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
503 * messages. Does that mean that CreateWindow doesn't set initial
504 * window dimensions for overlapped windows?
509 { WM_PAINT
, sent
|optional
},
510 { WM_NCPAINT
, sent
|beginpaint
|optional
},
513 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
514 static const struct message WmShowMaxOverlappedSeq
[] = {
515 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
516 { WM_GETMINMAXINFO
, sent
},
517 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
518 { WM_GETMINMAXINFO
, sent
|defwinproc
},
519 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
520 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
521 { HCBT_ACTIVATE
, hook
|optional
},
522 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
523 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
524 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
525 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
526 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
527 { WM_GETTEXT
, sent
|defwinproc
|optional
},
528 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
529 { HCBT_SETFOCUS
, hook
|optional
},
530 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
531 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
532 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
533 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
534 { WM_GETTEXT
, sent
|optional
},
535 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
536 { WM_GETTEXT
, sent
|defwinproc
|optional
},
537 { WM_ERASEBKGND
, sent
|optional
},
538 /* Win9x adds SWP_NOZORDER below */
539 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
540 { WM_MOVE
, sent
|defwinproc
},
541 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
542 { WM_GETTEXT
, sent
|optional
},
543 { WM_NCCALCSIZE
, sent
|optional
},
544 { WM_NCPAINT
, sent
|optional
},
545 { WM_ERASEBKGND
, sent
|optional
},
546 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
547 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
548 { WM_SYNCPAINT
, sent
|optional
},
549 { WM_GETTITLEBARINFOEX
, sent
|optional
},
550 { WM_PAINT
, sent
|optional
},
551 { WM_NCPAINT
, sent
|beginpaint
|optional
},
552 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
555 /* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */
556 static const struct message WmShowRestoreMaxOverlappedSeq
[] = {
557 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
558 { WM_GETTEXT
, sent
|optional
},
559 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
560 { WM_GETMINMAXINFO
, sent
|defwinproc
},
561 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
562 { WM_NCPAINT
, sent
|optional
},
563 { WM_GETTEXT
, sent
|defwinproc
|optional
},
564 { WM_ERASEBKGND
, sent
|optional
},
565 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
566 { WM_MOVE
, sent
|defwinproc
|optional
},
567 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
568 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
569 { WM_NCPAINT
, sent
|optional
},
570 { WM_ERASEBKGND
, sent
|optional
},
571 { WM_PAINT
, sent
|optional
},
572 { WM_GETTITLEBARINFOEX
, sent
|optional
},
573 { WM_NCPAINT
, sent
|beginpaint
|optional
},
574 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
575 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
576 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
577 { WM_SYNCPAINT
, sent
|optional
},
580 /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
581 static const struct message WmShowRestoreMinOverlappedSeq
[] = {
582 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
583 { WM_QUERYOPEN
, sent
|optional
},
584 { WM_GETTEXT
, sent
|optional
},
585 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
586 { WM_WINDOWPOSCHANGING
, sent
|optional
}, /* SWP_NOSIZE|SWP_NOMOVE */
587 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
588 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
589 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
590 { WM_MOVE
, sent
|optional
},
591 { WM_SIZE
, sent
|wparam
|optional
, SIZE_RESTORED
},
592 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
593 { WM_GETTEXT
, sent
|optional
},
594 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
|SWP_NOCOPYBITS
},
595 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
},
596 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
597 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win10. */
598 { HCBT_ACTIVATE
, hook
|optional
},
599 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
600 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
601 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
602 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
603 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
604 { WM_GETTEXT
, sent
|defwinproc
|optional
},
605 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
606 { HCBT_SETFOCUS
, hook
|optional
},
607 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
608 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
609 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
610 { WM_SETFOCUS
, sent
|wparam
|defwinproc
|optional
, 0 },
611 { WM_GETTEXT
, sent
|optional
},
612 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
613 { WM_GETTEXT
, sent
|defwinproc
|optional
},
614 { WM_ERASEBKGND
, sent
},
615 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_STATECHANGED
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
},
616 { WM_MOVE
, sent
|defwinproc
},
617 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
618 { HCBT_SETFOCUS
, hook
|optional
},
619 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
620 { WM_NCCALCSIZE
, sent
|wparam
|optional
, TRUE
},
621 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
622 { WM_ERASEBKGND
, sent
|optional
},
623 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
624 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
625 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
626 { HCBT_SETFOCUS
, hook
|optional
},
627 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
628 { WM_SETFOCUS
, sent
|wparam
|optional
, 0 },
629 { WM_ACTIVATE
, sent
|wparam
, 1 },
630 { WM_GETTEXT
, sent
|optional
},
631 { WM_PAINT
, sent
|optional
},
632 { WM_GETTITLEBARINFOEX
, sent
|optional
},
633 { WM_NCPAINT
, sent
|beginpaint
|optional
},
634 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
637 /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
638 static const struct message WmShowMinOverlappedSeq
[] = {
639 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
640 { HCBT_SETFOCUS
, hook
|optional
},
641 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
642 { WM_KILLFOCUS
, sent
|optional
},
643 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
644 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
645 { WM_GETTEXT
, sent
|optional
},
646 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOCOPYBITS
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
647 { WM_GETMINMAXINFO
, sent
|defwinproc
},
648 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
649 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
650 { WM_NCPAINT
, sent
|optional
},
651 { WM_GETTEXT
, sent
|defwinproc
|optional
},
652 { WM_WINDOWPOSCHANGED
, sent
},
653 { WM_MOVE
, sent
|defwinproc
},
654 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
655 { WM_NCCALCSIZE
, sent
|optional
},
656 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
657 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on win10. */
658 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
659 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
660 { WM_GETTEXT
, sent
|defwinproc
|optional
},
661 { WM_ACTIVATE
, sent
|optional
},
662 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
664 /* Vista sometimes restores the window right away... */
665 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
666 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
667 { HCBT_MINMAX
, hook
|optional
|lparam
, 0, SW_RESTORE
},
668 { WM_QUERYOPEN
, sent
|optional
},
669 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
670 { WM_GETMINMAXINFO
, sent
|optional
|defwinproc
},
671 { WM_NCCALCSIZE
, sent
|optional
|wparam
, TRUE
},
672 { HCBT_ACTIVATE
, hook
|optional
},
673 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 1 },
674 { WM_NCACTIVATE
, sent
|optional
},
675 { WM_GETTEXT
, sent
|optional
},
676 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
677 { HCBT_SETFOCUS
, hook
|optional
},
678 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
679 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
680 { WM_SETFOCUS
, sent
|optional
},
681 { WM_NCPAINT
, sent
|optional
},
682 { WM_GETTEXT
, sent
|defwinproc
|optional
},
683 { WM_ERASEBKGND
, sent
|optional
},
684 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
685 { WM_MOVE
, sent
|defwinproc
|optional
},
686 { WM_SIZE
, sent
|defwinproc
|optional
|wparam
, SIZE_RESTORED
},
687 { WM_ACTIVATE
, sent
|optional
|wparam
, 1 },
688 { WM_SYSCOMMAND
, sent
|optional
|wparam
, SC_RESTORE
},
689 { HCBT_SYSCOMMAND
, hook
|optional
|wparam
, SC_RESTORE
},
691 { WM_PAINT
, sent
|optional
},
692 { WM_NCPAINT
, sent
|beginpaint
|optional
},
693 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
696 /* ShowWindow(SW_HIDE) for a visible overlapped window */
697 static const struct message WmHideOverlappedSeq
[] = {
698 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
699 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
700 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
701 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
702 { WM_SIZE
, sent
|optional
}, /* XP doesn't send it */
703 { WM_MOVE
, sent
|optional
}, /* XP doesn't send it */
704 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
705 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
706 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
707 { HCBT_SETFOCUS
, hook
|optional
},
708 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
709 { WM_KILLFOCUS
, sent
|wparam
|optional
, 0 },
710 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
711 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
714 /* DestroyWindow for a visible overlapped window */
715 static const struct message WmDestroyOverlappedSeq
[] = {
716 { HCBT_DESTROYWND
, hook
},
717 { 0x0090, sent
|optional
},
718 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
719 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
720 { 0x0090, sent
|optional
},
721 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
722 { WM_NCACTIVATE
, sent
|optional
|wparam
, 0 },
723 { WM_ACTIVATE
, sent
|optional
},
724 { WM_ACTIVATEAPP
, sent
|optional
|wparam
, 0 },
725 { WM_KILLFOCUS
, sent
|optional
|wparam
, 0 },
726 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
727 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
728 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
729 { WM_DESTROY
, sent
},
730 { WM_NCDESTROY
, sent
},
733 /* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
734 static const struct message WmCreateMaxPopupSeq
[] = {
735 { HCBT_CREATEWND
, hook
},
736 { WM_NCCREATE
, sent
},
737 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
739 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
740 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
742 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
743 { WM_GETMINMAXINFO
, sent
},
744 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
745 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
746 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
747 { WM_MOVE
, sent
|defwinproc
},
748 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
749 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
750 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
751 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
752 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
753 { HCBT_ACTIVATE
, hook
},
754 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
755 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
756 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
757 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
758 { WM_ERASEBKGND
, sent
|optional
},
759 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_NOMOVE
|SWP_NOSIZE
},
760 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
761 { WM_NCACTIVATE
, sent
},
762 { WM_ACTIVATE
, sent
|wparam
, 1 },
763 { HCBT_SETFOCUS
, hook
},
764 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
765 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
766 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
767 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
768 { WM_GETTEXT
, sent
|optional
},
769 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
770 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
771 { WM_ERASEBKGND
, sent
|optional
},
772 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
773 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
774 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
777 /* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
778 static const struct message WmCreateInvisibleMaxPopupSeq
[] = {
779 { HCBT_CREATEWND
, hook
},
780 { WM_NCCREATE
, sent
},
781 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
783 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
784 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
786 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
787 { WM_GETMINMAXINFO
, sent
},
788 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
789 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
790 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
791 { WM_MOVE
, sent
|defwinproc
},
792 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
793 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
796 /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
797 static const struct message WmShowMaxPopupResizedSeq
[] = {
798 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
799 { WM_GETMINMAXINFO
, sent
},
800 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
801 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
802 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
803 { HCBT_ACTIVATE
, hook
},
804 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
805 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
806 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
807 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
808 { WM_ERASEBKGND
, sent
|optional
},
809 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
810 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
811 { WM_NCACTIVATE
, sent
},
812 { WM_ACTIVATE
, sent
|wparam
, 1 },
813 { HCBT_SETFOCUS
, hook
},
814 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
815 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
816 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
817 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
818 { WM_GETTEXT
, sent
|optional
},
819 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
820 { WM_ERASEBKGND
, sent
|optional
},
821 { WM_WINDOWPOSCHANGED
, sent
},
822 /* WinNT4.0 sends WM_MOVE */
823 { WM_MOVE
, sent
|defwinproc
|optional
},
824 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
825 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
828 /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
829 static const struct message WmShowMaxPopupSeq
[] = {
830 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
831 { WM_GETMINMAXINFO
, sent
},
832 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
833 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
834 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
835 { HCBT_ACTIVATE
, hook
},
836 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
837 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
838 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
839 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
840 { WM_ERASEBKGND
, sent
|optional
},
841 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOMOVE
|SWP_NOSIZE
},
842 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
843 { WM_NCACTIVATE
, sent
},
844 { WM_ACTIVATE
, sent
|wparam
, 1 },
845 { HCBT_SETFOCUS
, hook
},
846 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
847 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
848 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
849 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
850 { WM_GETTEXT
, sent
|optional
},
851 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
852 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
853 { WM_ERASEBKGND
, sent
|optional
},
854 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
855 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
856 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOSIZE
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
857 { WM_SIZE
, sent
|defwinproc
|optional
},
858 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
861 /* CreateWindow(WS_VISIBLE) for popup window */
862 static const struct message WmCreatePopupSeq
[] = {
863 { HCBT_CREATEWND
, hook
},
864 { WM_NCCREATE
, sent
},
865 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
867 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
868 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
870 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
871 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
872 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
873 { HCBT_ACTIVATE
, hook
},
874 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
875 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
876 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
877 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
878 { WM_ERASEBKGND
, sent
|optional
},
879 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
880 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
881 { WM_NCACTIVATE
, sent
},
882 { WM_ACTIVATE
, sent
|wparam
, 1 },
883 { HCBT_SETFOCUS
, hook
},
884 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
885 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
886 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
887 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
888 { WM_GETTEXT
, sent
|optional
},
889 { WM_SYNCPAINT
, sent
|wparam
|optional
, 4 },
890 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
891 { WM_ERASEBKGND
, sent
|optional
},
892 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTMOVE
|SWP_NOCLIENTSIZE
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
},
895 /* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
896 static const struct message WmShowVisMaxPopupSeq
[] = {
897 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
898 { WM_GETMINMAXINFO
, sent
},
899 { WM_GETTEXT
, sent
|optional
},
900 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
901 { WM_GETTEXT
, sent
|optional
},
902 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
903 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
904 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
905 { WM_ERASEBKGND
, sent
|optional
},
906 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
907 { WM_MOVE
, sent
|defwinproc
},
908 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
909 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
912 /* ShowWindow(hwnd, SW_RESTORE) to a minimized window */
913 static const struct message WmShowRestoreMinimizedOverlappedSeq
[] =
915 { HCBT_MINMAX
, hook
},
916 { WM_QUERYOPEN
, sent
},
917 { WM_GETTEXT
, sent
|optional
},
918 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
919 { WM_GETMINMAXINFO
, sent
|defwinproc
},
920 { WM_NCCALCSIZE
, sent
},
921 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
922 { HCBT_ACTIVATE
, hook
},
923 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
924 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
925 { WM_NCACTIVATE
, sent
},
926 { WM_GETTEXT
, sent
|defwinproc
|optional
},
927 { WM_ACTIVATE
, sent
|wparam
, WA_ACTIVE
},
928 { HCBT_SETFOCUS
, hook
},
929 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
930 { WM_SETFOCUS
, sent
|defwinproc
},
931 { WM_NCPAINT
, sent
},
932 { WM_GETTEXT
, sent
|defwinproc
|optional
},
933 { WM_GETTEXT
, sent
|defwinproc
|optional
},
934 { WM_ERASEBKGND
, sent
},
935 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
936 { WM_MOVE
, sent
|defwinproc
},
937 { WM_SIZE
, sent
|defwinproc
},
938 { WM_NCCALCSIZE
, sent
|optional
},
939 { WM_NCPAINT
, sent
|optional
},
940 { WM_ERASEBKGND
, sent
|optional
},
941 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
942 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
943 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
944 /* Note this WM_ACTIVATE message even if the window is already active and focused */
945 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
946 { WM_SYNCPAINT
, sent
|optional
},
948 { WM_GETMINMAXINFO
, sent
|optional
},
951 /* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to a minimized window */
952 static const struct message WmShowNoActivateMinimizedOverlappedSeq
[] =
954 { HCBT_MINMAX
, hook
},
955 { WM_QUERYOPEN
, sent
},
956 { WM_GETTEXT
, sent
|optional
},
957 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
958 { WM_GETMINMAXINFO
, sent
|defwinproc
},
959 { WM_NCCALCSIZE
, sent
},
960 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
961 { WM_NCPAINT
, sent
},
962 { WM_GETTEXT
, sent
|defwinproc
|optional
},
963 { WM_ERASEBKGND
, sent
},
964 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
965 { WM_MOVE
, sent
|defwinproc
},
966 { WM_SIZE
, sent
|defwinproc
},
967 /* Following optional messages are on XP/2003 */
968 { WM_NCCALCSIZE
, sent
|optional
},
969 { WM_NCPAINT
, sent
|optional
},
970 { WM_ERASEBKGND
, sent
|optional
},
971 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
972 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
973 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
974 { HCBT_SETFOCUS
, hook
|optional
},
975 { WM_SETFOCUS
, sent
|optional
},
976 { HCBT_ACTIVATE
, hook
|optional
},
977 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
978 { WM_NCACTIVATE
, sent
|optional
},
979 { WM_GETTEXT
, sent
|defwinproc
|optional
},
980 { WM_ACTIVATE
, sent
|wparam
|optional
, WA_ACTIVE
},
981 { HCBT_SETFOCUS
, hook
|optional
},
982 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
983 { WM_KILLFOCUS
, sent
|optional
},
984 { WM_SETFOCUS
, sent
|optional
},
985 /* Note this WM_ACTIVATE message on XP even if the window is already active and focused */
986 { WM_ACTIVATE
, sent
|wparam
|lparam
|optional
, WA_ACTIVE
, 0 },
987 { WM_SYNCPAINT
, sent
|optional
},
989 { WM_GETMINMAXINFO
, sent
|optional
},
992 /* ShowWindow(hwnd, SW_RESTORE) to an active minimized window */
993 static const struct message WmShowRestoreActiveMinimizedOverlappedSeq
[] =
995 { HCBT_MINMAX
, hook
},
996 { WM_QUERYOPEN
, sent
},
997 { WM_GETTEXT
, sent
|optional
},
998 { WM_NCACTIVATE
, sent
},
999 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1000 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1001 { WM_NCCALCSIZE
, sent
|optional
},
1002 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1003 { WM_MOVE
, sent
|optional
},
1004 { WM_SIZE
, sent
|optional
},
1005 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1006 { WM_GETTEXT
, sent
|optional
},
1007 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1008 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1009 { WM_NCCALCSIZE
, sent
},
1010 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win8+ sends this. */
1011 { WM_NCPAINT
, sent
},
1012 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1013 { WM_ERASEBKGND
, sent
},
1014 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1015 { WM_MOVE
, sent
|defwinproc
},
1016 { WM_SIZE
, sent
|defwinproc
},
1017 { WM_NCCALCSIZE
, sent
|optional
},
1018 { WM_NCPAINT
, sent
|optional
},
1019 { WM_ERASEBKGND
, sent
|optional
},
1020 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1021 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1022 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1023 { HCBT_SETFOCUS
, hook
},
1024 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1025 { WM_SETFOCUS
, sent
},
1026 /* Note this WM_ACTIVATE message even if the window is already active */
1027 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
1028 { WM_SYNCPAINT
, sent
|optional
},
1030 { WM_GETMINMAXINFO
, sent
|optional
},
1033 /* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to an active minimized window */
1034 static const struct message WmShowNoActivateActiveMinimizedOverlappedSeq
[] =
1036 { HCBT_MINMAX
, hook
},
1037 { WM_QUERYOPEN
, sent
},
1038 { WM_GETTEXT
, sent
|optional
},
1039 { WM_NCACTIVATE
, sent
},
1040 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1041 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1042 { WM_NCCALCSIZE
, sent
|optional
},
1043 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1044 { WM_MOVE
, sent
|optional
},
1045 { WM_SIZE
, sent
|optional
},
1046 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
1047 { WM_GETTEXT
, sent
|optional
},
1048 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1049 { WM_GETMINMAXINFO
, sent
|defwinproc
},
1050 { WM_NCCALCSIZE
, sent
},
1051 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win8+ sends this. */
1052 { WM_NCPAINT
, sent
},
1053 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1054 { WM_ERASEBKGND
, sent
},
1055 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1056 { WM_MOVE
, sent
|defwinproc
},
1057 { WM_SIZE
, sent
|defwinproc
},
1058 { WM_NCCALCSIZE
, sent
|optional
},
1059 { WM_NCPAINT
, sent
|optional
},
1060 { WM_ERASEBKGND
, sent
|optional
},
1061 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1062 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1063 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1064 /* Following optional messages are present on XP */
1065 { HCBT_SETFOCUS
, hook
|optional
},
1066 { WM_SETFOCUS
, sent
|optional
},
1067 /* Note this WM_ACTIVATE message even if the window is already active and with flag SW_SHOWNOACTIVATE */
1068 { WM_ACTIVATE
, sent
|wparam
|lparam
|optional
, WA_ACTIVE
, 0 },
1069 { WM_SYNCPAINT
, sent
|optional
},
1071 { WM_GETMINMAXINFO
, sent
|optional
},
1074 /* CreateWindow (for a child popup window, not initially visible) */
1075 static const struct message WmCreateChildPopupSeq
[] = {
1076 { HCBT_CREATEWND
, hook
},
1077 { WM_NCCREATE
, sent
},
1078 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1079 { WM_CREATE
, sent
},
1080 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1081 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1085 /* CreateWindow (for a popup window, not initially visible,
1086 * which sets WS_VISIBLE in WM_CREATE handler)
1088 static const struct message WmCreateInvisiblePopupSeq
[] = {
1089 { HCBT_CREATEWND
, hook
},
1090 { WM_NCCREATE
, sent
},
1091 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1092 { WM_CREATE
, sent
},
1093 { WM_STYLECHANGING
, sent
},
1094 { WM_STYLECHANGED
, sent
},
1095 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1096 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1100 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
1101 * for a popup window with WS_VISIBLE style set
1103 static const struct message WmShowVisiblePopupSeq_2
[] = {
1104 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1107 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1108 * for a popup window with WS_VISIBLE style set
1110 static const struct message WmShowVisiblePopupSeq_3
[] = {
1111 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1112 { HCBT_ACTIVATE
, hook
},
1113 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1114 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1115 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1116 { WM_NCACTIVATE
, sent
},
1117 { WM_ACTIVATE
, sent
|wparam
, 1 },
1118 { HCBT_SETFOCUS
, hook
},
1119 { WM_KILLFOCUS
, sent
|parent
},
1120 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1121 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1122 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1123 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1124 { WM_SETFOCUS
, sent
|defwinproc
},
1125 { WM_GETTEXT
, sent
|optional
},
1126 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_SHOWWINDOW
},
1129 /* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location)
1131 static const struct message WmShowPopupExtremeLocationSeq
[] = {
1132 { HCBT_CREATEWND
, hook
},
1133 { WM_NCCREATE
, sent
},
1134 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1135 { WM_CREATE
, sent
},
1136 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1137 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1139 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1140 { WM_WINDOWPOSCHANGING
, sent
},
1141 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1142 { HCBT_ACTIVATE
, hook
},
1143 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1144 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1145 { WM_QUERYNEWPALETTE
, sent
|optional
},
1147 /* occasionally received on test machines */
1148 { WM_NCPAINT
, sent
|optional
},
1149 { WM_ERASEBKGND
, sent
|optional
},
1150 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1152 { WM_ACTIVATEAPP
, sent
},
1153 { WM_NCACTIVATE
, sent
},
1154 { WM_ACTIVATE
, sent
},
1155 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1156 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1157 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1158 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1159 { HCBT_SETFOCUS
, hook
},
1160 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1161 { WM_SETFOCUS
, sent
|defwinproc
},
1162 { WM_NCPAINT
, sent
|wparam
|optional
, 1 }, /* Not always sent on Win8+ */
1163 { WM_ERASEBKGND
, sent
|optional
}, /* Not always sent on Win8+ */
1164 { WM_WINDOWPOSCHANGED
, sent
},
1165 /* occasionally received on test machines */
1166 { WM_NCPAINT
, sent
|optional
},
1167 { WM_ERASEBKGND
, sent
|optional
},
1170 /* CreateWindow (for a popup window with WS_VISIBLE style set)
1172 static const struct message WmShowPopupFirstDrawSeq_1
[] = {
1173 { HCBT_CREATEWND
, hook
},
1174 { WM_NCCREATE
, sent
},
1175 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1176 { WM_CREATE
, sent
},
1177 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1178 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1180 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1181 { WM_WINDOWPOSCHANGING
, sent
},
1182 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1183 { HCBT_ACTIVATE
, hook
},
1184 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1185 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1186 { WM_QUERYNEWPALETTE
, sent
|optional
},
1187 { WM_ACTIVATEAPP
, sent
},
1188 { WM_NCACTIVATE
, sent
},
1189 { WM_ACTIVATE
, sent
},
1190 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1191 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1192 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1193 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1194 { HCBT_SETFOCUS
, hook
},
1195 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1196 { WM_SETFOCUS
, sent
|defwinproc
},
1197 { WM_NCPAINT
, sent
|wparam
, 1 },
1198 { WM_ERASEBKGND
, sent
},
1199 { WM_WINDOWPOSCHANGED
, sent
},
1201 /* occasionally received on test machines */
1202 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1203 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1206 /* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED))
1208 static const struct message WmShowPopupFirstDrawSeq_2
[] = {
1209 { HCBT_CREATEWND
, hook
},
1210 { WM_NCCREATE
, sent
},
1211 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1212 { WM_CREATE
, sent
},
1213 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1214 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1216 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1217 { WM_GETMINMAXINFO
, sent
},
1218 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_STATECHANGED
|SWP_SHOWWINDOW
|SWP_FRAMECHANGED
},
1219 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
1220 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1221 { HCBT_ACTIVATE
, hook
},
1222 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1223 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1224 { WM_NCPAINT
, sent
|optional
|wparam
, 1 },
1225 { WM_ERASEBKGND
, sent
|optional
},
1226 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1227 { WM_QUERYNEWPALETTE
, sent
|optional
},
1228 { WM_ACTIVATEAPP
, sent
},
1229 { WM_NCACTIVATE
, sent
},
1230 { WM_ACTIVATE
, sent
},
1231 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1232 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1233 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1234 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1235 { HCBT_SETFOCUS
, hook
},
1236 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1237 { WM_SETFOCUS
, sent
|defwinproc
},
1238 { WM_NCPAINT
, sent
|wparam
, 1 },
1239 { WM_ERASEBKGND
, sent
},
1240 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1241 { WM_MOVE
, sent
|defwinproc
},
1242 { WM_SIZE
, sent
|defwinproc
, 0 },
1243 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1245 /* occasionally received on test machines */
1246 { WM_NCPAINT
, sent
|beginpaint
|optional
},
1247 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
1250 static const struct message WmFirstDrawSetWindowPosSeq1
[] = {
1251 { HCBT_CREATEWND
, hook
},
1252 { WM_NCCREATE
, sent
},
1253 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1254 { WM_CREATE
, sent
},
1255 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1256 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1258 { WM_WINDOWPOSCHANGING
, sent
},
1259 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1260 { HCBT_ACTIVATE
, hook
},
1261 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1262 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1263 { WM_QUERYNEWPALETTE
, sent
|optional
},
1264 { WM_ACTIVATEAPP
, sent
},
1265 { WM_NCACTIVATE
, sent
},
1266 { WM_ACTIVATE
, sent
},
1267 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1268 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1269 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1270 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1271 { HCBT_SETFOCUS
, hook
},
1272 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1273 { WM_SETFOCUS
, sent
|defwinproc
},
1274 { WM_NCPAINT
, sent
|wparam
, 1 },
1275 { WM_ERASEBKGND
, sent
},
1276 { WM_WINDOWPOSCHANGED
, sent
},
1277 { WM_MOVE
, sent
|defwinproc
},
1278 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1281 static const struct message WmFirstDrawSetWindowPosSeq2
[] = {
1282 { HCBT_CREATEWND
, hook
},
1283 { WM_NCCREATE
, sent
},
1284 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1285 { WM_CREATE
, sent
},
1286 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1287 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1289 { WM_WINDOWPOSCHANGING
, sent
},
1290 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not always sent. */
1291 { HCBT_ACTIVATE
, hook
},
1292 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1293 { WM_QUERYNEWPALETTE
, sent
|optional
},
1294 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1295 { WM_ACTIVATEAPP
, sent
},
1296 { WM_NCACTIVATE
, sent
},
1297 { WM_ACTIVATE
, sent
},
1298 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1299 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1300 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1301 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1302 { HCBT_SETFOCUS
, hook
},
1303 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1304 { WM_SETFOCUS
, sent
|defwinproc
},
1305 { WM_WINDOWPOSCHANGED
, sent
},
1306 { WM_MOVE
, sent
|defwinproc
},
1307 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1310 static const struct message WmFirstDrawSetWindowPosSeq3
[] = {
1311 { HCBT_CREATEWND
, hook
},
1312 { WM_NCCREATE
, sent
},
1313 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1314 { WM_CREATE
, sent
},
1315 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1316 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1318 { EVENT_OBJECT_SHOW
, winevent_hook
|wine_only
},
1319 { HCBT_ACTIVATE
, hook
|wine_only
},
1320 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
1321 { WM_QUERYNEWPALETTE
, sent
|wine_only
},
1322 { WM_ACTIVATEAPP
, sent
|wine_only
},
1323 { WM_NCACTIVATE
, sent
|wine_only
},
1324 { WM_ACTIVATE
, sent
|wine_only
},
1325 { HCBT_SETFOCUS
, hook
|wine_only
},
1326 { EVENT_OBJECT_FOCUS
, winevent_hook
|lparam
|wparam
|wine_only
, OBJID_CLIENT
, 0 },
1327 { WM_SETFOCUS
, sent
|defwinproc
|wine_only
},
1328 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|lparam
|wparam
|wine_only
, 0, 0 },
1331 static const struct message WmFirstDrawSetWindowPosSeq4
[] = {
1332 { HCBT_CREATEWND
, hook
},
1333 { WM_NCCREATE
, sent
},
1334 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1335 { WM_CREATE
, sent
},
1336 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1337 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1339 { WM_WINDOWPOSCHANGING
, sent
},
1340 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1341 { HCBT_ACTIVATE
, hook
},
1342 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1343 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1344 { WM_QUERYNEWPALETTE
, sent
|optional
},
1345 { WM_ACTIVATEAPP
, sent
},
1346 { WM_NCACTIVATE
, sent
},
1347 { WM_ACTIVATE
, sent
},
1348 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1349 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1350 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1351 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1352 { HCBT_SETFOCUS
, hook
},
1353 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1354 { WM_SETFOCUS
, sent
|defwinproc
},
1355 { WM_NCPAINT
, sent
|wparam
, 1 },
1356 { WM_ERASEBKGND
, sent
},
1357 { WM_WINDOWPOSCHANGED
, sent
},
1360 static const struct message WmFirstDrawSetWindowPosSeq5
[] = {
1361 { HCBT_CREATEWND
, hook
},
1362 { WM_NCCREATE
, sent
},
1363 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1364 { WM_CREATE
, sent
},
1365 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1366 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1368 { WM_WINDOWPOSCHANGING
, sent
},
1369 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1370 { HCBT_ACTIVATE
, hook
},
1371 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1372 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1373 { WM_QUERYNEWPALETTE
, sent
|optional
},
1374 { WM_ACTIVATEAPP
, sent
},
1375 { WM_NCACTIVATE
, sent
},
1376 { WM_ACTIVATE
, sent
},
1377 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1378 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
1379 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1380 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Not sent on Win10. */
1381 { HCBT_SETFOCUS
, hook
},
1382 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1383 { WM_SETFOCUS
, sent
|defwinproc
},
1384 { WM_WINDOWPOSCHANGED
, sent
},
1387 static const struct message WmFirstDrawSetWindowPosSeq6
[] = {
1388 { HCBT_CREATEWND
, hook
},
1389 { WM_NCCREATE
, sent
},
1390 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1391 { WM_CREATE
, sent
},
1392 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1393 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1395 { EVENT_OBJECT_SHOW
, winevent_hook
|wine_only
},
1396 { HCBT_ACTIVATE
, hook
|wine_only
},
1397 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
1398 { WM_QUERYNEWPALETTE
, sent
|wine_only
},
1399 { WM_ACTIVATEAPP
, sent
|wine_only
},
1400 { WM_NCACTIVATE
, sent
|wine_only
},
1401 { WM_ACTIVATE
, sent
|wine_only
},
1402 { HCBT_SETFOCUS
, hook
|wine_only
},
1403 { EVENT_OBJECT_FOCUS
, winevent_hook
|lparam
|wparam
|wine_only
, OBJID_CLIENT
, 0 },
1404 { WM_SETFOCUS
, sent
|defwinproc
|wine_only
},
1407 static const struct message WmFirstDrawChildSeq1
[] = {
1408 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1409 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1412 static const struct message WmFirstDrawChildSeq2
[] = {
1413 { WM_NCPAINT
, sent
|wparam
, 1 },
1414 { WM_ERASEBKGND
, sent
},
1415 /* occasionally received on test machines */
1416 { WM_NCPAINT
, sent
|optional
},
1417 { WM_ERASEBKGND
, sent
|optional
},
1418 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1419 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
1422 /* CreateWindow (for child window, not initially visible) */
1423 static const struct message WmCreateChildSeq
[] = {
1424 { HCBT_CREATEWND
, hook
},
1425 { WM_NCCREATE
, sent
},
1426 /* child is inserted into parent's child list after WM_NCCREATE returns */
1427 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1428 { WM_CREATE
, sent
},
1429 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1430 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1432 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1435 /* CreateWindow (for maximized child window, not initially visible) */
1436 static const struct message WmCreateMaximizedChildSeq
[] = {
1437 { HCBT_CREATEWND
, hook
},
1438 { WM_NCCREATE
, sent
},
1439 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1440 { WM_CREATE
, sent
},
1441 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1442 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1444 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1445 { WM_GETMINMAXINFO
, sent
},
1446 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
1447 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1448 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1449 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1450 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1451 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1454 /* CreateWindow (for a child window, initially visible) */
1455 static const struct message WmCreateVisibleChildSeq
[] = {
1456 { HCBT_CREATEWND
, hook
},
1457 { WM_NCCREATE
, sent
},
1458 /* child is inserted into parent's child list after WM_NCCREATE returns */
1459 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1460 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1461 { WM_CREATE
, sent
},
1462 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1463 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1465 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_CREATE
},
1466 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1467 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1468 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1469 { WM_ERASEBKGND
, sent
|parent
|optional
},
1470 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1471 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* WinXP */
1472 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1475 /* ShowWindow(SW_SHOW) for a not visible child window */
1476 static const struct message WmShowChildSeq
[] = {
1477 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1478 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1479 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1480 { WM_ERASEBKGND
, sent
|parent
|optional
},
1481 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1484 /* ShowWindow(SW_HIDE) for a visible child window */
1485 static const struct message WmHideChildSeq
[] = {
1486 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1487 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1488 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1489 { WM_ERASEBKGND
, sent
|parent
|optional
},
1490 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1493 /* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/
1494 static const struct message WmHideChildSeq2
[] = {
1495 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1496 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1497 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1498 { WM_ERASEBKGND
, sent
|parent
|optional
},
1499 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1502 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1503 * for a not visible child window
1505 static const struct message WmShowChildSeq_2
[] = {
1506 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1507 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1508 { WM_CHILDACTIVATE
, sent
},
1509 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1512 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
1513 * for a not visible child window
1515 static const struct message WmShowChildSeq_3
[] = {
1516 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1517 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1518 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1521 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
1522 * for a visible child window with a caption
1524 static const struct message WmShowChildSeq_4
[] = {
1525 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1526 { WM_CHILDACTIVATE
, sent
},
1529 /* ShowWindow(SW_MINIMIZE) for child with invisible parent */
1530 static const struct message WmShowChildInvisibleParentSeq_1
[] = {
1531 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1532 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1533 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1534 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1535 { WM_CHILDACTIVATE
, sent
|optional
},
1536 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
1537 { WM_MOVE
, sent
|defwinproc
},
1538 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1539 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1540 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1541 { WM_GETTEXT
, sent
|optional
},
1544 /* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */
1545 static const struct message WmShowChildInvisibleParentSeq_1r
[] = {
1546 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
1549 /* ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1550 static const struct message WmShowChildInvisibleParentSeq_2
[] = {
1551 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1552 { WM_GETMINMAXINFO
, sent
},
1553 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
1554 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1555 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1556 { WM_CHILDACTIVATE
, sent
},
1557 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
1558 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
1559 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1562 /* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */
1563 static const struct message WmShowChildInvisibleParentSeq_2r
[] = {
1564 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
1567 /* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1568 static const struct message WmShowChildInvisibleParentSeq_3
[] = {
1569 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1570 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1571 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1572 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1573 { WM_CHILDACTIVATE
, sent
},
1574 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1575 { WM_MOVE
, sent
|defwinproc
},
1576 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1577 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1578 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1579 { WM_GETTEXT
, sent
|optional
},
1582 /* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */
1583 static const struct message WmShowChildInvisibleParentSeq_3r
[] = {
1584 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
1587 /* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1588 static const struct message WmShowChildInvisibleParentSeq_4
[] = {
1589 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1590 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1591 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1592 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1593 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
1594 { WM_MOVE
, sent
|defwinproc
},
1595 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
1596 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1597 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
1598 /* FIXME: Wine creates an icon/title window while Windows doesn't */
1599 { WM_GETTEXT
, sent
|optional
},
1602 /* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */
1603 static const struct message WmShowChildInvisibleParentSeq_4r
[] = {
1604 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
1607 /* ShowWindow(SW_SHOW) for child with invisible parent */
1608 static const struct message WmShowChildInvisibleParentSeq_5
[] = {
1609 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1612 /* ShowWindow(SW_HIDE) for child with invisible parent */
1613 static const struct message WmHideChildInvisibleParentSeq
[] = {
1614 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1617 /* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */
1618 static const struct message WmShowChildInvisibleParentSeq_6
[] = {
1619 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1620 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1621 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1624 /* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */
1625 static const struct message WmHideChildInvisibleParentSeq_2
[] = {
1626 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1627 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1628 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1631 /* DestroyWindow for a visible child window */
1632 static const struct message WmDestroyChildSeq
[] = {
1633 { HCBT_DESTROYWND
, hook
},
1634 { 0x0090, sent
|optional
},
1635 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1636 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1637 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1638 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1639 { WM_ERASEBKGND
, sent
|parent
|optional
},
1640 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1641 { HCBT_SETFOCUS
, hook
}, /* set focus to a parent */
1642 { WM_KILLFOCUS
, sent
},
1643 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1644 { WM_IME_SETCONTEXT
, sent
|wparam
|parent
|optional
, 1 },
1645 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1646 { WM_SETFOCUS
, sent
|parent
},
1647 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1648 { WM_DESTROY
, sent
},
1649 { WM_DESTROY
, sent
|optional
}, /* some other (IME?) window */
1650 { WM_NCDESTROY
, sent
|optional
}, /* some other (IME?) window */
1651 { WM_NCDESTROY
, sent
},
1654 /* visible child window destroyed by thread exit */
1655 static const struct message WmExitThreadSeq
[] = {
1656 { WM_NCDESTROY
, sent
}, /* actually in grandchild */
1657 { WM_PAINT
, sent
|parent
},
1658 { WM_ERASEBKGND
, sent
|parent
|beginpaint
},
1661 /* DestroyWindow for a visible child window with invisible parent */
1662 static const struct message WmDestroyInvisibleChildSeq
[] = {
1663 { HCBT_DESTROYWND
, hook
},
1664 { 0x0090, sent
|optional
},
1665 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_DESTROY
},
1666 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
1667 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1668 { WM_DESTROY
, sent
},
1669 { WM_NCDESTROY
, sent
},
1672 /* Resizing child window with MoveWindow (32) */
1673 static const struct message WmResizingChildWithMoveWindowSeq
[] = {
1674 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
1675 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1676 { WM_ERASEBKGND
, sent
|parent
|optional
},
1677 { WM_ERASEBKGND
, sent
|optional
},
1678 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
},
1679 { WM_MOVE
, sent
|defwinproc
},
1680 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1681 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1684 /* Creation of a custom dialog (32) */
1685 static const struct message WmCreateCustomDialogSeq
[] = {
1686 { HCBT_CREATEWND
, hook
},
1687 { WM_GETMINMAXINFO
, sent
},
1688 { WM_NCCREATE
, sent
},
1689 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
1690 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1691 { WM_CREATE
, sent
},
1692 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1693 { WM_NOTIFYFORMAT
, sent
|optional
},
1694 { WM_QUERYUISTATE
, sent
|optional
},
1695 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1696 { WM_GETMINMAXINFO
, sent
|optional
},
1697 { WM_NCCALCSIZE
, sent
|optional
},
1698 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1699 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1700 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1701 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1702 { HCBT_ACTIVATE
, hook
},
1703 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1706 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1708 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1710 { WM_NCACTIVATE
, sent
},
1711 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1712 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1713 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1714 { EVENT_OBJECT_DEFACTIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
1715 { WM_ACTIVATE
, sent
|wparam
, 1 },
1716 { WM_GETTEXT
, sent
|optional
},
1717 { WM_KILLFOCUS
, sent
|parent
},
1718 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1719 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1720 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1721 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1722 { WM_SETFOCUS
, sent
},
1723 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1724 { WM_NCPAINT
, sent
|wparam
, 1 },
1725 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1726 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1727 { WM_ERASEBKGND
, sent
},
1728 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1729 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1730 { WM_GETTEXT
, sent
|optional
},
1731 { WM_GETTEXT
, sent
|optional
},
1732 { WM_NCCALCSIZE
, sent
|optional
},
1733 { WM_NCPAINT
, sent
|optional
},
1734 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1735 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1736 { WM_ERASEBKGND
, sent
|optional
},
1737 { WM_CTLCOLORDLG
, sent
|optional
|defwinproc
},
1738 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1739 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
1743 /* Calling EndDialog for a custom dialog (32) */
1744 static const struct message WmEndCustomDialogSeq
[] = {
1745 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1746 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1747 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1748 { WM_GETTEXT
, sent
|optional
},
1749 { HCBT_ACTIVATE
, hook
},
1750 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1751 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1752 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1753 { WM_ACTIVATE
, sent
|wparam
, 0 },
1754 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
1755 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1756 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1757 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1758 { WM_GETTEXT
, sent
|optional
|defwinproc
},
1759 { HCBT_SETFOCUS
, hook
},
1760 { WM_KILLFOCUS
, sent
},
1761 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
1762 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1763 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 1 },
1764 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1765 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1768 /* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */
1769 static const struct message WmShowCustomDialogSeq
[] = {
1770 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
1771 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
1772 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1773 { HCBT_ACTIVATE
, hook
},
1774 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1776 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1778 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
1779 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 },
1780 { WM_NCACTIVATE
, sent
},
1781 { WM_ACTIVATE
, sent
|wparam
, 1 },
1782 { WM_GETTEXT
, sent
|optional
},
1784 { WM_KILLFOCUS
, sent
|parent
},
1785 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1786 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
1787 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
1788 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1789 { WM_SETFOCUS
, sent
},
1790 { WM_GETDLGCODE
, sent
|defwinproc
|wparam
, 0 },
1791 { WM_NCPAINT
, sent
|wparam
, 1 },
1792 { WM_ERASEBKGND
, sent
},
1793 { WM_CTLCOLORDLG
, sent
|defwinproc
},
1794 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1797 /* Creation and destruction of a modal dialog (32) */
1798 static const struct message WmModalDialogSeq
[] = {
1799 { WM_CANCELMODE
, sent
|parent
},
1800 { HCBT_SETFOCUS
, hook
},
1801 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1802 { WM_KILLFOCUS
, sent
|parent
},
1803 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1804 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1805 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
1806 { HCBT_CREATEWND
, hook
},
1807 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1808 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1809 { WM_SETFONT
, sent
},
1810 { WM_INITDIALOG
, sent
},
1811 { WM_CHANGEUISTATE
, sent
|optional
},
1812 { WM_UPDATEUISTATE
, sent
|optional
},
1813 { WM_SHOWWINDOW
, sent
},
1814 { HCBT_ACTIVATE
, hook
},
1815 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1816 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
1817 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
1818 { WM_NCACTIVATE
, sent
},
1819 { WM_GETTEXT
, sent
|optional
},
1820 { WM_ACTIVATE
, sent
|wparam
, 1 },
1821 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1822 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
1823 { WM_NCPAINT
, sent
|optional
},
1824 { WM_GETTEXT
, sent
|optional
},
1825 { WM_ERASEBKGND
, sent
|optional
},
1826 { WM_CTLCOLORDLG
, sent
|optional
},
1827 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1828 { WM_GETTEXT
, sent
|optional
},
1829 { WM_NCCALCSIZE
, sent
|optional
},
1830 { WM_NCPAINT
, sent
|optional
},
1831 { WM_GETTEXT
, sent
|optional
},
1832 { WM_ERASEBKGND
, sent
|optional
},
1833 { WM_CTLCOLORDLG
, sent
|optional
},
1834 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
1835 { WM_PAINT
, sent
|optional
},
1836 { WM_CTLCOLORBTN
, sent
|optional
},
1837 { WM_GETTITLEBARINFOEX
, sent
|optional
},
1838 { WM_ENTERIDLE
, sent
|parent
|optional
},
1839 { WM_ENTERIDLE
, sent
|parent
|optional
},
1840 { WM_ENTERIDLE
, sent
|parent
|optional
},
1841 { WM_ENTERIDLE
, sent
|parent
|optional
},
1842 { WM_ENTERIDLE
, sent
|parent
|optional
},
1843 { WM_ENTERIDLE
, sent
|parent
|optional
},
1844 { WM_ENTERIDLE
, sent
|parent
|optional
},
1845 { WM_ENTERIDLE
, sent
|parent
|optional
},
1846 { WM_ENTERIDLE
, sent
|parent
|optional
},
1847 { WM_ENTERIDLE
, sent
|parent
|optional
},
1848 { WM_ENTERIDLE
, sent
|parent
|optional
},
1849 { WM_ENTERIDLE
, sent
|parent
|optional
},
1850 { WM_ENTERIDLE
, sent
|parent
|optional
},
1851 { WM_ENTERIDLE
, sent
|parent
|optional
},
1852 { WM_ENTERIDLE
, sent
|parent
|optional
},
1853 { WM_ENTERIDLE
, sent
|parent
|optional
},
1854 { WM_ENTERIDLE
, sent
|parent
|optional
},
1855 { WM_ENTERIDLE
, sent
|parent
|optional
},
1856 { WM_ENTERIDLE
, sent
|parent
|optional
},
1857 { WM_ENTERIDLE
, sent
|parent
|optional
},
1859 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1860 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
1861 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1862 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1863 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1864 { WM_GETTEXT
, sent
|optional
},
1865 { HCBT_ACTIVATE
, hook
},
1866 { WM_NCACTIVATE
, sent
|wparam
, 0 },
1867 { WM_GETTEXT
, sent
|optional
},
1868 { WM_ACTIVATE
, sent
|wparam
, 0 },
1869 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1870 { WM_WINDOWPOSCHANGING
, sent
|optional
},
1871 { WM_WINDOWPOSCHANGED
, sent
|optional
},
1872 { HCBT_SETFOCUS
, hook
},
1873 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|defwinproc
|optional
, 1 },
1874 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1875 { WM_SETFOCUS
, sent
|parent
|defwinproc
},
1876 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1877 { HCBT_DESTROYWND
, hook
},
1878 { 0x0090, sent
|optional
},
1879 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1880 { WM_DESTROY
, sent
},
1881 { WM_NCDESTROY
, sent
},
1884 static const struct message WmModalDialogSeq_2
[] = {
1885 { WM_CANCELMODE
, sent
},
1886 { HCBT_SETFOCUS
, hook
},
1887 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
1888 { WM_KILLFOCUS
, sent
},
1889 { WM_IME_SETCONTEXT
, sent
|parent
|wparam
|optional
, 0 },
1890 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1891 { WM_ENABLE
, sent
|wparam
, 0 },
1892 { HCBT_CREATEWND
, hook
},
1893 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
1894 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1895 { WM_SETFONT
, sent
},
1896 { WM_INITDIALOG
, sent
},
1897 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1898 { WM_CHANGEUISTATE
, sent
|optional
},
1899 { WM_UPDATEUISTATE
, sent
|optional
},
1900 { WM_ENABLE
, sent
|wparam
, 1 },
1901 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
1902 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
1903 { WM_CHANGEUISTATE
, sent
|optional
},
1904 { WM_UPDATEUISTATE
, sent
|optional
},
1905 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1906 { HCBT_DESTROYWND
, hook
},
1907 { 0x0090, sent
|optional
},
1908 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1909 { WM_DESTROY
, sent
},
1910 { WM_NCDESTROY
, sent
},
1913 /* SetMenu for NonVisible windows with size change*/
1914 static const struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
1915 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1916 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1917 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1918 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
1919 { WM_MOVE
, sent
|defwinproc
},
1920 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1921 { WM_NCCALCSIZE
,sent
|wparam
|optional
, 1 }, /* XP */
1922 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1923 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1924 { WM_GETTEXT
, sent
|optional
},
1925 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1928 /* SetMenu for NonVisible windows with no size change */
1929 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
1930 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1931 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1932 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1933 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1936 /* SetMenu for Visible windows with size change */
1937 static const struct message WmSetMenuVisibleSizeChangeSeq
[] = {
1938 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1939 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1940 { 0x0093, sent
|defwinproc
|optional
},
1941 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
1942 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1943 { 0x0093, sent
|defwinproc
|optional
},
1944 { 0x0093, sent
|defwinproc
|optional
},
1945 { 0x0091, sent
|defwinproc
|optional
},
1946 { 0x0092, sent
|defwinproc
|optional
},
1947 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1948 { WM_ERASEBKGND
, sent
|optional
},
1949 { WM_ACTIVATE
, sent
|optional
},
1950 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1951 { WM_MOVE
, sent
|defwinproc
},
1952 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
1953 { 0x0093, sent
|optional
},
1954 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
1955 { 0x0093, sent
|defwinproc
|optional
},
1956 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1957 { 0x0093, sent
|defwinproc
|optional
},
1958 { 0x0093, sent
|defwinproc
|optional
},
1959 { 0x0091, sent
|defwinproc
|optional
},
1960 { 0x0092, sent
|defwinproc
|optional
},
1961 { WM_ERASEBKGND
, sent
|optional
},
1962 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1963 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
1966 /* SetMenu for Visible windows with no size change */
1967 static const struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
1968 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1969 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1970 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1971 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1972 { WM_ERASEBKGND
, sent
|optional
},
1973 { WM_ACTIVATE
, sent
|optional
},
1974 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1975 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1978 /* DrawMenuBar for a visible window */
1979 static const struct message WmDrawMenuBarSeq
[] =
1981 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
1982 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
1983 { 0x0093, sent
|defwinproc
|optional
},
1984 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
1985 { 0x0093, sent
|defwinproc
|optional
},
1986 { 0x0093, sent
|defwinproc
|optional
},
1987 { 0x0091, sent
|defwinproc
|optional
},
1988 { 0x0092, sent
|defwinproc
|optional
},
1989 { WM_GETTEXT
, sent
|defwinproc
|optional
},
1990 { WM_ERASEBKGND
, sent
|optional
},
1991 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
1992 { 0x0093, sent
|optional
},
1993 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
1997 static const struct message WmSetRedrawFalseSeq
[] =
1999 { WM_SETREDRAW
, sent
|wparam
, 0 },
2003 static const struct message WmSetRedrawTrueSeq
[] =
2005 { WM_SETREDRAW
, sent
|wparam
, 1 },
2009 static const struct message WmEnableWindowSeq_1
[] =
2011 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
2012 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2013 { HCBT_SETFOCUS
, hook
|optional
},
2014 { WM_KILLFOCUS
, sent
|optional
},
2015 { WM_ENABLE
, sent
|wparam
|lparam
, FALSE
, 0 },
2019 static const struct message WmEnableWindowSeq_2
[] =
2021 { WM_CANCELMODE
, sent
|wparam
|lparam
, 0, 0 },
2022 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
2026 static const struct message WmEnableWindowSeq_3
[] =
2028 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2029 { WM_ENABLE
, sent
|wparam
|lparam
, TRUE
, 0 },
2033 static const struct message WmEnableWindowSeq_4
[] =
2035 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win10. */
2039 static const struct message WmGetScrollRangeSeq
[] =
2041 { SBM_GETRANGE
, sent
},
2044 static const struct message WmGetScrollInfoSeq
[] =
2046 { SBM_GETSCROLLINFO
, sent
},
2049 static const struct message WmSetScrollRangeSeq
[] =
2051 /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
2052 sends SBM_SETSCROLLINFO.
2054 { SBM_SETSCROLLINFO
, sent
},
2057 /* SetScrollRange for a window without a non-client area */
2058 static const struct message WmSetScrollRangeHSeq_empty
[] =
2060 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_HSCROLL
, 0 },
2063 static const struct message WmSetScrollRangeVSeq_empty
[] =
2065 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_VSCROLL
, 0 },
2068 static const struct message WmSetScrollRangeHVSeq
[] =
2070 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
2071 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2072 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2073 { WM_ERASEBKGND
, sent
|optional
},
2074 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2075 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2076 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2079 /* SetScrollRange for a window with a non-client area */
2080 static const struct message WmSetScrollRangeHV_NC_Seq
[] =
2082 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
},
2083 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
2084 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2085 { WM_NCPAINT
, sent
|optional
},
2086 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2087 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2088 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2089 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2090 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2091 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2092 { WM_STYLECHANGING
, sent
|defwinproc
|optional
},
2093 { WM_STYLECHANGED
, sent
|defwinproc
|optional
},
2094 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2095 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2096 { WM_ERASEBKGND
, sent
|optional
},
2097 { WM_CTLCOLORDLG
, sent
|defwinproc
|optional
}, /* sent to a parent of the dialog */
2098 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOCLIENTSIZE
},
2099 { WM_SIZE
, sent
|defwinproc
|optional
},
2100 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2101 { EVENT_OBJECT_VALUECHANGE
, winevent_hook
|lparam
|optional
, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
2102 { WM_GETTEXT
, sent
|optional
},
2103 { WM_GETTEXT
, sent
|optional
},
2104 { WM_GETTEXT
, sent
|optional
},
2105 { WM_GETTEXT
, sent
|optional
},
2108 /* test if we receive the right sequence of messages */
2109 /* after calling ShowWindow( SW_SHOWNA) */
2110 static const struct message WmSHOWNAChildInvisParInvis
[] = {
2111 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2114 static const struct message WmSHOWNAChildVisParInvis
[] = {
2115 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2118 static const struct message WmSHOWNAChildVisParVis
[] = {
2119 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2120 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
2123 static const struct message WmSHOWNAChildInvisParVis
[] = {
2124 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2125 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2126 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2127 { WM_ERASEBKGND
, sent
|optional
},
2128 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOACTIVATE
|SWP_NOCLIENTMOVE
},
2131 static const struct message WmSHOWNATopVisible
[] = {
2132 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2133 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
2134 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2135 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2136 { WM_ERASEBKGND
, sent
|optional
},
2137 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2140 static const struct message WmSHOWNATopInvisible
[] = {
2141 { WM_NOTIFYFORMAT
, sent
|optional
},
2142 { WM_QUERYUISTATE
, sent
|optional
},
2143 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2144 { WM_GETMINMAXINFO
, sent
|optional
},
2145 { WM_NCCALCSIZE
, sent
|optional
},
2146 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2147 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2148 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
2149 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2150 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2151 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2152 { WM_ERASEBKGND
, sent
|optional
},
2153 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
2154 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2155 { WM_NCPAINT
, sent
|wparam
|optional
, 1 },
2156 { WM_ERASEBKGND
, sent
|optional
},
2157 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
2158 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
2163 static const struct message WmTrackPopupMenuMinimizeWindow
[] = {
2164 { HCBT_CREATEWND
, hook
},
2165 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2166 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2167 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2168 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2169 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2170 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2171 { 0x0093, sent
|optional
},
2172 { 0x0094, sent
|optional
},
2173 { 0x0094, sent
|optional
},
2174 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2175 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2176 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2177 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2178 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2179 { HCBT_MINMAX
, hook
},
2180 { HCBT_SETFOCUS
, hook
},
2181 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2182 { WM_KILLFOCUS
, sent
|wparam
, 0 },
2183 { WM_GETTEXT
, sent
|optional
},
2184 { WM_WINDOWPOSCHANGING
, sent
},
2185 { WM_GETMINMAXINFO
, sent
|defwinproc
},
2186 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2187 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2188 { WM_WINDOWPOSCHANGED
, sent
},
2189 { WM_MOVE
, sent
|defwinproc
},
2190 { WM_SIZE
, sent
|defwinproc
},
2191 { WM_GETTEXT
, sent
|optional
},
2192 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
2193 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2194 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
2195 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2196 { WM_CANCELMODE
, sent
},
2197 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2198 { WM_CAPTURECHANGED
, sent
|defwinproc
},
2199 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2200 { HCBT_DESTROYWND
, hook
},
2201 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2202 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2203 { WM_UNINITMENUPOPUP
, sent
|defwinproc
|lparam
, 0, 0 },
2204 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
2205 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2206 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 1, 0 },
2207 { WM_NCACTIVATE
, sent
},
2208 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2209 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2210 { WM_ACTIVATE
, sent
},
2211 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
2215 static const struct message WmTrackPopupMenu
[] = {
2216 { HCBT_CREATEWND
, hook
},
2217 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2218 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2219 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2220 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2221 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2222 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2223 { 0x0093, sent
|optional
},
2224 { 0x0094, sent
|optional
},
2225 { 0x0094, sent
|optional
},
2226 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2227 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2228 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2229 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2230 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2231 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2232 { WM_CAPTURECHANGED
, sent
},
2233 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2234 { HCBT_DESTROYWND
, hook
},
2235 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2236 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2237 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2238 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2239 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2240 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2244 static const struct message WmTrackPopupMenuEsc
[] = {
2248 static const struct message WmTrackPopupMenuCapture
[] = {
2249 { HCBT_CREATEWND
, hook
},
2250 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2251 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2252 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2253 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2254 { WM_CAPTURECHANGED
, sent
},
2255 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2256 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2257 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2258 { 0x0093, sent
|optional
},
2259 { 0x0094, sent
|optional
},
2260 { 0x0094, sent
|optional
},
2261 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2262 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2263 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2264 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2265 { WM_ENTERIDLE
, sent
|wparam
, 2 },
2266 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2267 { WM_CAPTURECHANGED
, sent
},
2268 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2269 { HCBT_DESTROYWND
, hook
},
2270 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2271 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2272 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2273 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2274 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2275 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2279 static const struct message WmTrackPopupMenuEmpty
[] = {
2280 { HCBT_CREATEWND
, hook
},
2281 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2282 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2283 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2284 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2285 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2286 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2287 { 0x0093, sent
|optional
},
2288 { 0x0094, sent
|optional
},
2289 { 0x0094, sent
|optional
},
2290 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2291 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2292 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2293 { WM_CAPTURECHANGED
, sent
},
2294 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2295 { HCBT_DESTROYWND
, hook
},
2296 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2297 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2301 static const struct message WmTrackPopupMenuAbort
[] = {
2302 { HCBT_CREATEWND
, hook
},
2303 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2304 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, TRUE
, 0 },
2305 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2306 { WM_INITMENU
, sent
|lparam
, 0, 0 },
2307 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2308 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
2309 { 0x0093, sent
|optional
},
2310 { 0x0094, sent
|optional
},
2311 { 0x0094, sent
|optional
},
2312 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2313 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2314 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
2315 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2316 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2317 { WM_CAPTURECHANGED
, sent
},
2318 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
2319 { HCBT_DESTROYWND
, hook
},
2320 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2321 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2322 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
2323 { WM_MENUSELECT
, sent
|wparam
|lparam
, 0xffff0000, 0 },
2324 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
2325 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 1, 0 },
2329 static BOOL after_end_dialog
, test_def_id
, paint_loop_done
;
2330 static int sequence_cnt
, sequence_size
;
2331 static struct recvd_message
* sequence
;
2332 static int log_all_parent_messages
;
2333 static CRITICAL_SECTION sequence_cs
;
2335 /* user32 functions */
2336 static void (WINAPI
*pNotifyWinEvent
)(DWORD
, HWND
, LONG
, LONG
);
2337 static HWINEVENTHOOK (WINAPI
*pSetWinEventHook
)(DWORD
, DWORD
, HMODULE
, WINEVENTPROC
, DWORD
, DWORD
, DWORD
);
2338 static BOOL (WINAPI
*pTrackMouseEvent
)(TRACKMOUSEEVENT
*);
2339 static BOOL (WINAPI
*pUnhookWinEvent
)(HWINEVENTHOOK
);
2340 static BOOL (WINAPI
*pUpdateLayeredWindow
)(HWND
,HDC
,POINT
*,SIZE
*,HDC
,POINT
*,COLORREF
,BLENDFUNCTION
*,DWORD
);
2341 static UINT_PTR (WINAPI
*pSetSystemTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
);
2342 static UINT_PTR (WINAPI
*pKillSystemTimer
)(HWND
, UINT_PTR
);
2343 static UINT_PTR (WINAPI
*pSetCoalescableTimer
)(HWND
, UINT_PTR
, UINT
, TIMERPROC
, ULONG
);
2344 /* kernel32 functions */
2345 static BOOL (WINAPI
*pGetCPInfoExA
)(UINT
, DWORD
, LPCPINFOEXA
);
2347 static void init_procs(void)
2349 HMODULE user32
= GetModuleHandleA("user32.dll");
2350 HMODULE kernel32
= GetModuleHandleA("kernel32.dll");
2352 #define GET_PROC(dll, func) \
2353 p ## func = (void*)GetProcAddress(dll, #func); \
2355 trace("GetProcAddress(%s) failed\n", #func); \
2358 GET_PROC(user32
, NotifyWinEvent
)
2359 GET_PROC(user32
, SetWinEventHook
)
2360 GET_PROC(user32
, TrackMouseEvent
)
2361 GET_PROC(user32
, UnhookWinEvent
)
2362 GET_PROC(user32
, UpdateLayeredWindow
)
2363 GET_PROC(user32
, SetSystemTimer
)
2364 GET_PROC(user32
, KillSystemTimer
)
2365 GET_PROC(user32
, SetCoalescableTimer
)
2367 GET_PROC(kernel32
, GetCPInfoExA
)
2372 static const char *get_winpos_flags(UINT flags
)
2374 static char buffer
[300];
2377 #define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0)
2378 DUMP( SWP_SHOWWINDOW
);
2379 DUMP( SWP_HIDEWINDOW
);
2380 DUMP( SWP_NOACTIVATE
);
2381 DUMP( SWP_FRAMECHANGED
);
2382 DUMP( SWP_NOCOPYBITS
);
2383 DUMP( SWP_NOOWNERZORDER
);
2384 DUMP( SWP_NOSENDCHANGING
);
2385 DUMP( SWP_DEFERERASE
);
2386 DUMP( SWP_ASYNCWINDOWPOS
);
2387 DUMP( SWP_NOZORDER
);
2388 DUMP( SWP_NOREDRAW
);
2391 DUMP( SWP_NOCLIENTSIZE
);
2392 DUMP( SWP_NOCLIENTMOVE
);
2393 if (flags
) sprintf(buffer
+ strlen(buffer
),"|0x%04x", flags
);
2398 static BOOL
ignore_message( UINT message
)
2400 /* these are always ignored */
2401 return (message
>= 0xc000 ||
2402 message
== WM_GETICON
||
2403 message
== WM_GETOBJECT
||
2404 message
== WM_TIMECHANGE
||
2405 message
== WM_DISPLAYCHANGE
||
2406 message
== WM_DEVICECHANGE
||
2407 message
== WM_DWMNCRENDERINGCHANGED
||
2408 message
== WM_WININICHANGE
);
2411 static unsigned hash_Ly_W(const WCHAR
*str
)
2416 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2421 static unsigned hash_Ly(const char *str
)
2426 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
2431 #define add_message(msg) add_message_(__LINE__,msg);
2432 static void add_message_(int line
, const struct recvd_message
*msg
)
2434 struct recvd_message
*seq
;
2436 EnterCriticalSection( &sequence_cs
);
2440 sequence
= malloc( sequence_size
* sizeof(*sequence
) );
2442 if (sequence_cnt
== sequence_size
)
2445 sequence
= realloc( sequence
, sequence_size
* sizeof(*sequence
) );
2448 seq
= &sequence
[sequence_cnt
++];
2449 seq
->hwnd
= msg
->hwnd
;
2450 seq
->message
= msg
->message
;
2451 seq
->flags
= msg
->flags
;
2452 seq
->wParam
= msg
->wParam
;
2453 seq
->lParam
= msg
->lParam
;
2455 seq
->descr
= msg
->descr
;
2457 LeaveCriticalSection( &sequence_cs
);
2461 if (msg
->flags
& hook
)
2463 static const char * const CBT_code_name
[10] =
2471 "HCBT_CLICKSKIPPED",
2476 const char *code_name
= (msg
->message
<= HCBT_SETFOCUS
) ? CBT_code_name
[msg
->message
] : "Unknown";
2478 sprintf( seq
->output
, "%s: hook %d (%s) wp %08Ix lp %08Ix",
2479 msg
->descr
, msg
->message
, code_name
, msg
->wParam
, msg
->lParam
);
2481 else if (msg
->flags
& winevent_hook
)
2483 sprintf( seq
->output
, "%s: winevent %p %08x %08Ix %08Ix",
2484 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2488 switch (msg
->message
)
2490 case WM_WINDOWPOSCHANGING
:
2491 case WM_WINDOWPOSCHANGED
:
2493 WINDOWPOS
*winpos
= (WINDOWPOS
*)msg
->lParam
;
2495 sprintf( seq
->output
, "%s: %p WM_WINDOWPOS%s wp %08Ix lp %08Ix after %p x %d y %d cx %d cy %d flags %s",
2496 msg
->descr
, msg
->hwnd
,
2497 (msg
->message
== WM_WINDOWPOSCHANGING
) ? "CHANGING" : "CHANGED",
2498 msg
->wParam
, msg
->lParam
, winpos
->hwndInsertAfter
,
2499 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
2500 get_winpos_flags(winpos
->flags
) );
2502 /* Log only documented flags, win2k uses 0x1000 and 0x2000
2503 * in the high word for internal purposes
2505 seq
->wParam
= winpos
->flags
& 0xffff;
2506 /* We are not interested in the flags that don't match under XP and Win9x */
2507 seq
->wParam
&= ~SWP_NOZORDER
;
2508 seq
->lParam
= (!!winpos
->cx
) | ((!!winpos
->cy
) << 1)
2509 | ((!!winpos
->x
) << 2) | ((!!winpos
->y
) << 3);
2516 NCCALCSIZE_PARAMS
*p
= (NCCALCSIZE_PARAMS
*)msg
->lParam
;
2517 WINDOWPOS
*winpos
= p
->lppos
;
2519 sprintf(seq
->output
, "%s: %p WM_NCCALCSIZE: winpos->cx %u, winpos->cy %u",
2520 msg
->descr
, msg
->hwnd
, winpos
->cx
, winpos
->cy
);
2521 seq
->lParam
= (!!winpos
->cx
) | ((!!winpos
->cy
) << 1)
2522 | ((!!winpos
->x
) << 2) | ((!!winpos
->y
) << 3);
2526 RECT
*rect
= (RECT
*)msg
->lParam
;
2528 sprintf(seq
->output
, "%s: %p WM_NCCALCSIZE: %s",
2529 msg
->descr
, msg
->hwnd
, wine_dbgstr_rect(rect
));
2535 DRAW_ITEM_STRUCT di
;
2536 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)msg
->lParam
;
2538 sprintf( seq
->output
, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x",
2539 msg
->descr
, msg
->hwnd
, dis
->CtlType
, dis
->CtlID
,
2540 dis
->itemID
, dis
->itemAction
, dis
->itemState
);
2543 di
.u
.item
.type
= dis
->CtlType
;
2544 di
.u
.item
.ctl_id
= dis
->CtlID
;
2545 if (dis
->CtlType
== ODT_LISTBOX
||
2546 dis
->CtlType
== ODT_COMBOBOX
||
2547 dis
->CtlType
== ODT_MENU
)
2548 di
.u
.item
.item_id
= dis
->itemID
;
2549 di
.u
.item
.action
= dis
->itemAction
;
2550 di
.u
.item
.state
= dis
->itemState
;
2552 seq
->lParam
= di
.u
.lp
;
2556 case WM_MEASUREITEM
:
2558 MEASURE_ITEM_STRUCT mi
;
2559 MEASUREITEMSTRUCT
*mis
= (MEASUREITEMSTRUCT
*)msg
->lParam
;
2560 BOOL is_unicode_data
= TRUE
;
2562 sprintf( seq
->output
, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#Ix",
2563 msg
->descr
, msg
->hwnd
, mis
->CtlType
, mis
->CtlID
,
2564 mis
->itemID
, mis
->itemData
);
2566 if (mis
->CtlType
== ODT_LISTBOX
)
2568 HWND ctrl
= GetDlgItem(msg
->hwnd
, mis
->CtlID
);
2569 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2573 mi
.u
.item
.CtlType
= mis
->CtlType
;
2574 mi
.u
.item
.CtlID
= mis
->CtlID
;
2575 mi
.u
.item
.itemID
= mis
->itemID
;
2576 mi
.u
.item
.wParam
= msg
->wParam
;
2577 seq
->wParam
= mi
.u
.wp
;
2578 if (is_unicode_data
)
2579 seq
->lParam
= mis
->itemData
? hash_Ly_W((const WCHAR
*)mis
->itemData
) : 0;
2581 seq
->lParam
= mis
->itemData
? hash_Ly((const char *)mis
->itemData
) : 0;
2585 case WM_COMPAREITEM
:
2587 COMPAREITEMSTRUCT
*cis
= (COMPAREITEMSTRUCT
*)msg
->lParam
;
2588 HWND ctrl
= GetDlgItem(msg
->hwnd
, cis
->CtlID
);
2589 BOOL is_unicode_data
= TRUE
;
2591 ok(msg
->wParam
== cis
->CtlID
, "expected %#x, got %#Ix\n", cis
->CtlID
, msg
->wParam
);
2592 ok(cis
->hwndItem
== ctrl
, "expected %p, got %p\n", ctrl
, cis
->hwndItem
);
2593 ok((int)cis
->itemID1
>= 0, "expected >= 0, got %d\n", cis
->itemID1
);
2594 ok((int)cis
->itemID2
== -1, "expected -1, got %d\n", cis
->itemID2
);
2596 sprintf( seq
->output
, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#Ix, itemID2 %#x, itemData2 %#Ix",
2597 msg
->descr
, msg
->hwnd
, cis
->CtlType
, cis
->CtlID
,
2598 cis
->itemID1
, cis
->itemData1
, cis
->itemID2
, cis
->itemData2
);
2600 if (cis
->CtlType
== ODT_LISTBOX
)
2601 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
2603 if (is_unicode_data
)
2605 seq
->wParam
= cis
->itemData1
? hash_Ly_W((const WCHAR
*)cis
->itemData1
) : 0;
2606 seq
->lParam
= cis
->itemData2
? hash_Ly_W((const WCHAR
*)cis
->itemData2
) : 0;
2610 seq
->wParam
= cis
->itemData1
? hash_Ly((const char *)cis
->itemData1
) : 0;
2611 seq
->lParam
= cis
->itemData2
? hash_Ly((const char *)cis
->itemData2
) : 0;
2617 if (msg
->message
>= 0xc000) return; /* ignore registered messages */
2618 sprintf( seq
->output
, "%s: %p %04x wp %08Ix lp %08Ix",
2619 msg
->descr
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
2621 if (msg
->flags
& (sent
|posted
|parent
|defwinproc
|beginpaint
))
2622 sprintf( seq
->output
+ strlen(seq
->output
), " (flags %x)", msg
->flags
);
2627 /* try to make sure pending X events have been processed before continuing */
2628 static void flush_events(void)
2632 int min_timeout
= 100;
2633 DWORD time
= GetTickCount() + diff
;
2637 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
2638 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2639 diff
= time
- GetTickCount();
2643 static void flush_sequence(void)
2645 EnterCriticalSection( &sequence_cs
);
2648 sequence_cnt
= sequence_size
= 0;
2649 LeaveCriticalSection( &sequence_cs
);
2652 static const char* message_type_name(int flags
) {
2653 if (flags
& hook
) return "hook";
2654 if (flags
& kbd_hook
) return "kbd_hook";
2655 if (flags
& winevent_hook
) return "winevent_hook";
2659 static BOOL
can_skip_message(const struct message
*expected
)
2661 if (expected
->flags
& optional
) return TRUE
;
2663 if ((expected
->flags
& winevent_hook
) && !hEvent_hook
) return TRUE
;
2664 if ((expected
->flags
& kbd_hook
) && !hKBD_hook
) return TRUE
;
2665 if ((expected
->flags
& hook
) && !hCBT_hook
) return TRUE
;
2667 if ((expected
->flags
& msg_todo
) && !strcmp(winetest_platform
, "wine")) return TRUE
;
2669 if ((expected
->flags
& wine_only
) && strcmp(winetest_platform
, "wine")) return TRUE
;
2674 static BOOL
messages_equal(const struct message
*expected
, const struct recvd_message
*actual
,
2675 BOOL expect_equal
, const char* file
, int line
)
2677 int todo
= (expected
->flags
& msg_todo
) != 0;
2678 int msg_wine_only
= (expected
->flags
& wine_only
) != 0;
2679 const int message_type_flags
= hook
|winevent_hook
|kbd_hook
;
2680 static int todo_reported
;
2682 if (!todo
&& can_skip_message(expected
))
2683 expect_equal
= FALSE
;
2685 if (msg_wine_only
&& strcmp(winetest_platform
, "wine"))
2687 /* Ignore Wine-only message records on Windows. */
2691 if (!expected
->message
|| !actual
->message
) {
2692 if (expect_equal
&& (!todo
|| !todo_reported
++))
2693 todo_wine_if(todo
|| msg_wine_only
)
2694 ok_( file
, line
) (msg_wine_only
, "the msg sequence is not complete: expected %s %04x - actual %s %04x\n",
2695 message_type_name(expected
->flags
), expected
->message
, message_type_name(actual
->flags
), actual
->message
);
2699 if (expected
->message
!= actual
->message
||
2700 (expected
->flags
& message_type_flags
) != (actual
->flags
& message_type_flags
))
2702 if (expect_equal
&& (!todo
|| !todo_reported
++))
2703 todo_wine_if(todo
|| msg_wine_only
)
2704 ok_( file
, line
) (msg_wine_only
, "the %s 0x%04x was expected, but got %s 0x%04x instead\n",
2705 message_type_name(expected
->flags
), expected
->message
, message_type_name(actual
->flags
), actual
->message
);
2709 if (expected
->flags
& optional
)
2711 /* If a message can be sent in 2 different ways at the same time, we may need to treat
2712 * them as unequal so that the optional message can be properly skipped. */
2713 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) {
2714 /* don't match messages if their defwinproc status differs */
2720 todo_wine_if(todo
|| msg_wine_only
)
2721 ok_( file
, line
) (!msg_wine_only
, "got %s 0x%04x as expected\n",
2722 message_type_name(expected
->flags
), expected
->message
);
2727 static BOOL
sequence_contains_message(const struct message
*expected
, const struct recvd_message
*actual
)
2729 while (expected
->message
)
2731 if (messages_equal(expected
, actual
, FALSE
, __FILE__
, __LINE__
))
2738 static void dump_sequence(const struct message
*expected
, const char *context
, const char *file
, int line
)
2740 const struct recvd_message
*actual
= sequence
;
2741 unsigned int count
= 0;
2743 trace_(file
, line
)("Failed sequence %s:\n", context
);
2744 while (expected
->message
&& actual
->message
)
2746 if (actual
->output
[0])
2748 trace_(file
, line
)( " %u: expected: %s %04x - actual: %s\n",
2749 count
, message_type_name(expected
->flags
), expected
->message
, actual
->output
);
2752 if (messages_equal(expected
, actual
, FALSE
, file
, line
))
2758 else if (can_skip_message(expected
) || sequence_contains_message(expected
, actual
))
2769 /* optional trailing messages */
2770 while (can_skip_message(expected
))
2772 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2777 if (expected
->message
)
2779 trace_(file
, line
)( " %u: expected: msg %04x - actual: nothing\n", count
, expected
->message
);
2783 while (actual
->message
&& actual
->output
[0])
2785 trace_(file
, line
)( " %u: expected: nothing - actual: %s\n", count
, actual
->output
);
2791 #define ok_sequence( exp, contx, todo) \
2792 ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
2795 static void ok_sequence_(const struct message
*expected_list
, const char *context
, BOOL todo
,
2796 const char *file
, int line
)
2798 static const struct recvd_message end_of_sequence
;
2799 const struct message
*expected
= expected_list
;
2800 const struct recvd_message
*actual
;
2801 int failcount
= 0, dump
= 0;
2802 unsigned int count
= 0;
2803 BOOL is_wine
= !strcmp(winetest_platform
, "wine");
2805 add_message(&end_of_sequence
);
2809 winetest_push_context("%s: %u", context
, count
);
2811 while (expected
->message
&& actual
->message
)
2813 if (messages_equal(expected
, actual
, !todo
, file
, line
))
2815 if (expected
->flags
& wparam
)
2817 if (((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) && todo
)
2822 ok_( file
, line
) (FALSE
,
2823 "in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2824 expected
->message
, expected
->wParam
, actual
->wParam
);
2826 if (is_wine
) goto done
;
2830 ok_( file
, line
)( ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) == 0,
2831 "in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
2832 expected
->message
, expected
->wParam
, actual
->wParam
);
2833 if ((expected
->wParam
^ actual
->wParam
) & ~expected
->wp_mask
) dump
++;
2837 if (expected
->flags
& lparam
)
2839 if (((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) && todo
)
2844 ok_( file
, line
) (FALSE
,
2845 "in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2846 expected
->message
, expected
->lParam
, actual
->lParam
);
2848 if (is_wine
) goto done
;
2852 ok_( file
, line
)(((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) == 0,
2853 "in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
2854 expected
->message
, expected
->lParam
, actual
->lParam
);
2855 if ((expected
->lParam
^ actual
->lParam
) & ~expected
->lp_mask
) dump
++;
2858 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
) && todo
)
2863 ok_( file
, line
) (FALSE
,
2864 "the msg 0x%04x should %shave been sent by DefWindowProc\n",
2865 expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2867 if (is_wine
) goto done
;
2871 ok_( file
, line
) ((expected
->flags
& defwinproc
) == (actual
->flags
& defwinproc
),
2872 "the msg 0x%04x should %shave been sent by DefWindowProc\n",
2873 expected
->message
, (expected
->flags
& defwinproc
) ? "" : "NOT ");
2874 if ((expected
->flags
& defwinproc
) != (actual
->flags
& defwinproc
)) dump
++;
2877 ok_( file
, line
) ((expected
->flags
& beginpaint
) == (actual
->flags
& beginpaint
),
2878 "the msg 0x%04x should %shave been sent by BeginPaint\n",
2879 expected
->message
, (expected
->flags
& beginpaint
) ? "" : "NOT ");
2880 if ((expected
->flags
& beginpaint
) != (actual
->flags
& beginpaint
)) dump
++;
2882 ok_( file
, line
) ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
2883 "the msg 0x%04x should have been %s\n",
2884 expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
2885 if ((expected
->flags
& (sent
|posted
)) != (actual
->flags
& (sent
|posted
))) dump
++;
2887 ok_( file
, line
) ((expected
->flags
& parent
) == (actual
->flags
& parent
),
2888 "the msg 0x%04x was expected in %s\n",
2889 expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
2890 if ((expected
->flags
& parent
) != (actual
->flags
& parent
)) dump
++;
2897 * silently drop hook messages if there is no support for them
2899 else if (can_skip_message(expected
))
2906 todo_wine
messages_equal(expected
, actual
, TRUE
, file
, line
);
2911 else if (sequence_contains_message(expected
, actual
))
2923 winetest_pop_context();
2924 winetest_push_context("%s: %u", context
, count
);
2927 /* skip all optional trailing messages */
2928 while (can_skip_message(expected
))
2930 messages_equal(expected
, actual
, TRUE
, file
, line
); /* check for message todo's */
2937 if (expected
->message
|| actual
->message
) {
2940 messages_equal(expected
, actual
, TRUE
, file
, line
);
2943 if (is_wine
&& !failcount
) /* succeeded yet marked todo */
2946 ok_( file
, line
)( TRUE
, "marked \"todo_wine\" but succeeds\n");
2951 if (expected
->message
|| actual
->message
)
2954 messages_equal(expected
, actual
, TRUE
, file
, line
);
2959 winetest_pop_context();
2960 if (dump
&& (!is_wine
|| winetest_debug
> 1)) dump_sequence(expected_list
, context
, file
, line
);
2964 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
2966 /******************************** MDI test **********************************/
2968 /* CreateWindow for MDI frame window, initially visible */
2969 static const struct message WmCreateMDIframeSeq
[] = {
2970 { HCBT_CREATEWND
, hook
},
2971 { WM_GETMINMAXINFO
, sent
},
2972 { WM_NCCREATE
, sent
},
2973 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
2974 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
2975 { WM_CREATE
, sent
},
2976 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
2977 { WM_NOTIFYFORMAT
, sent
|optional
},
2978 { WM_QUERYUISTATE
, sent
|optional
},
2979 { WM_WINDOWPOSCHANGING
, sent
|optional
},
2980 { WM_GETMINMAXINFO
, sent
|optional
},
2981 { WM_NCCALCSIZE
, sent
|optional
},
2982 { WM_WINDOWPOSCHANGED
, sent
|optional
},
2983 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
2984 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
2985 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
2986 { HCBT_ACTIVATE
, hook
},
2987 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
2988 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
2989 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* XP */
2990 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 1 }, /* Win9x doesn't send it */
2991 { WM_NCACTIVATE
, sent
},
2992 { WM_GETTEXT
, sent
|defwinproc
|optional
},
2993 { WM_ACTIVATE
, sent
|wparam
, 1 },
2994 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* Win9x */
2995 { HCBT_SETFOCUS
, hook
},
2996 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
2997 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
2998 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
2999 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
3000 /* Win9x adds SWP_NOZORDER below */
3001 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3002 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3003 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
3004 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3008 /* DestroyWindow for MDI frame window, initially visible */
3009 static const struct message WmDestroyMDIframeSeq
[] = {
3010 { HCBT_DESTROYWND
, hook
},
3011 { 0x0090, sent
|optional
},
3012 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3013 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3014 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
3015 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3016 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 }, /* XP */
3017 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 }, /* Win9x */
3018 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 }, /* Win9x */
3019 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
3020 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3021 { WM_DESTROY
, sent
},
3022 { WM_NCDESTROY
, sent
},
3025 /* CreateWindow for MDI client window, initially visible */
3026 static const struct message WmCreateMDIclientSeq
[] = {
3027 { HCBT_CREATEWND
, hook
},
3028 { WM_NCCREATE
, sent
},
3029 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3030 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
3031 { WM_CREATE
, sent
},
3032 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
3033 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3034 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3036 { WM_PARENTNOTIFY
, sent
|wparam
, WM_CREATE
}, /* in MDI frame */
3037 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3038 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3039 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3040 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3043 /* ShowWindow(SW_SHOW) for MDI client window */
3044 static const struct message WmShowMDIclientSeq
[] = {
3045 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3046 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3047 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3048 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3051 /* ShowWindow(SW_HIDE) for MDI client window */
3052 static const struct message WmHideMDIclientSeq
[] = {
3053 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3054 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3055 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win2000 */
3056 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
3057 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3060 /* DestroyWindow for MDI client window, initially visible */
3061 static const struct message WmDestroyMDIclientSeq
[] = {
3062 { HCBT_DESTROYWND
, hook
},
3063 { 0x0090, sent
|optional
},
3064 { WM_PARENTNOTIFY
, sent
|wparam
, WM_DESTROY
}, /* in MDI frame */
3065 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3066 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3067 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3068 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3069 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3070 { WM_DESTROY
, sent
},
3071 { WM_NCDESTROY
, sent
},
3074 /* CreateWindow for MDI child window, initially visible */
3075 static const struct message WmCreateMDIchildVisibleSeq
[] = {
3076 { HCBT_CREATEWND
, hook
},
3077 { WM_NCCREATE
, sent
},
3078 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3079 { WM_CREATE
, sent
},
3080 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3081 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3083 /* Win2k sends wparam set to
3084 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3085 * while Win9x doesn't bother to set child window id according to
3086 * CLIENTCREATESTRUCT.idFirstChild
3088 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3089 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3090 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3091 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3092 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3093 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3094 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3095 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3096 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3098 /* Win9x: message sequence terminates here. */
3100 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3101 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3102 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3103 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3104 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3105 { WM_SETFOCUS
, sent
}, /* in MDI client */
3106 { HCBT_SETFOCUS
, hook
},
3107 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3108 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3109 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3110 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3111 { WM_SETFOCUS
, sent
|defwinproc
},
3112 { WM_MDIACTIVATE
, sent
|defwinproc
},
3115 /* WM_CHILDACTIVATE sent to disabled window */
3116 static const struct message WmChildActivateDisabledWindowSeq
[] = {
3117 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3120 /* WM_CHILDACTIVATE sent to enabled window */
3121 static const struct message WmChildActivateWindowSeq
[] = {
3122 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3123 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 },
3124 { WM_MDIACTIVATE
, sent
|defwinproc
},
3125 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3126 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
3127 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3128 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3129 { HCBT_SETFOCUS
, hook
},
3130 { WM_KILLFOCUS
, sent
|defwinproc
},
3131 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3132 { WM_SETFOCUS
, sent
},
3133 { HCBT_SETFOCUS
, hook
},
3134 { WM_KILLFOCUS
, sent
},
3135 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3136 { WM_SETFOCUS
, sent
|defwinproc
},
3137 { WM_MDIACTIVATE
, sent
|defwinproc
},
3140 /* CreateWindow for MDI child window with invisible parent */
3141 static const struct message WmCreateMDIchildInvisibleParentSeq
[] = {
3142 { HCBT_CREATEWND
, hook
},
3143 { WM_GETMINMAXINFO
, sent
},
3144 { WM_NCCREATE
, sent
},
3145 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3146 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
3147 { WM_CREATE
, sent
},
3148 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3149 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3151 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3152 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3153 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3154 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3155 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3156 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3158 /* Win9x: message sequence terminates here. */
3160 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3161 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3162 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3163 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3164 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3165 { WM_SETFOCUS
, sent
}, /* in MDI client */
3166 { HCBT_SETFOCUS
, hook
},
3167 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3168 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3169 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3170 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3171 { WM_SETFOCUS
, sent
|defwinproc
},
3172 { WM_MDIACTIVATE
, sent
|defwinproc
},
3175 /* DestroyWindow for MDI child window, initially visible */
3176 static const struct message WmDestroyMDIchildVisibleSeq
[] = {
3177 { HCBT_DESTROYWND
, hook
},
3178 /* Win2k sends wparam set to
3179 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3180 * while Win9x doesn't bother to set child window id according to
3181 * CLIENTCREATESTRUCT.idFirstChild
3183 { 0x0090, sent
|optional
},
3184 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3185 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3186 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3187 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3188 { WM_ERASEBKGND
, sent
|parent
|optional
},
3189 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3191 /* { WM_DESTROY, sent }
3192 * Win9x: message sequence terminates here.
3195 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3196 { WM_KILLFOCUS
, sent
},
3197 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3198 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3199 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3200 { WM_SETFOCUS
, sent
}, /* in MDI client */
3202 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3203 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3204 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3205 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3206 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3207 { WM_SETFOCUS
, sent
}, /* in MDI client */
3209 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3211 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3212 { WM_KILLFOCUS
, sent
},
3213 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3214 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3215 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3216 { WM_SETFOCUS
, sent
}, /* in MDI client */
3218 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3219 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3220 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3221 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3222 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3223 { WM_SETFOCUS
, sent
}, /* in MDI client */
3225 { WM_DESTROY
, sent
},
3227 { HCBT_SETFOCUS
, hook
}, /* set focus to MDI client */
3228 { WM_KILLFOCUS
, sent
},
3229 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3230 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3231 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3232 { WM_SETFOCUS
, sent
}, /* in MDI client */
3234 { HCBT_SETFOCUS
, hook
}, /* MDI client sets focus back to MDI child */
3235 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3236 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3237 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3238 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3239 { WM_SETFOCUS
, sent
}, /* in MDI client */
3241 { WM_NCDESTROY
, sent
},
3244 /* CreateWindow for MDI child window, initially invisible */
3245 static const struct message WmCreateMDIchildInvisibleSeq
[] = {
3246 { HCBT_CREATEWND
, hook
},
3247 { WM_NCCREATE
, sent
},
3248 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3249 { WM_CREATE
, sent
},
3250 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3251 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3253 /* Win2k sends wparam set to
3254 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3255 * while Win9x doesn't bother to set child window id according to
3256 * CLIENTCREATESTRUCT.idFirstChild
3258 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3261 /* DestroyWindow for MDI child window, initially invisible */
3262 static const struct message WmDestroyMDIchildInvisibleSeq
[] = {
3263 { HCBT_DESTROYWND
, hook
},
3264 /* Win2k sends wparam set to
3265 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3266 * while Win9x doesn't bother to set child window id according to
3267 * CLIENTCREATESTRUCT.idFirstChild
3269 { 0x0090, sent
|optional
},
3270 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3271 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3272 { WM_DESTROY
, sent
},
3273 { WM_NCDESTROY
, sent
},
3276 /* CreateWindow for the 1st MDI child window, initially visible and maximized */
3277 static const struct message WmCreateMDIchildVisibleMaxSeq1
[] = {
3278 { HCBT_CREATEWND
, hook
},
3279 { WM_NCCREATE
, sent
},
3280 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3281 { WM_CREATE
, sent
},
3282 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3283 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3285 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3286 { WM_GETMINMAXINFO
, sent
},
3287 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3288 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3289 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3290 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3292 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3293 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3294 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3295 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3296 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3297 /* Win2k sends wparam set to
3298 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3299 * while Win9x doesn't bother to set child window id according to
3300 * CLIENTCREATESTRUCT.idFirstChild
3302 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3303 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3304 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3305 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3306 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3307 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3308 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3309 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3310 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_FRAMECHANGED
},
3312 /* Win9x: message sequence terminates here. */
3314 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3315 { HCBT_SETFOCUS
, hook
|optional
}, /* in MDI client */
3316 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3317 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 }, /* in MDI client */
3318 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3319 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3320 { HCBT_SETFOCUS
, hook
|optional
},
3321 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3322 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3323 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3324 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3325 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3326 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3328 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3329 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3330 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3331 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3334 /* CreateWindow for the 2nd MDI child window, initially visible and maximized */
3335 static const struct message WmCreateMDIchildVisibleMaxSeq2
[] = {
3336 /* restore the 1st MDI child */
3337 { WM_SETREDRAW
, sent
|wparam
, 0 },
3338 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3339 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3340 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3341 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3342 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3343 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3345 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3346 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3347 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3348 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3349 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3350 { WM_SETREDRAW
, sent
|wparam
, 1 }, /* in the 1st MDI child */
3351 /* create the 2nd MDI child */
3352 { HCBT_CREATEWND
, hook
},
3353 { WM_NCCREATE
, sent
},
3354 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3355 { WM_CREATE
, sent
},
3356 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3357 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3359 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3360 { WM_GETMINMAXINFO
, sent
},
3361 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3362 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3363 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
3364 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3365 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3367 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3368 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3369 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3370 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3371 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3372 /* Win2k sends wparam set to
3373 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3374 * while Win9x doesn't bother to set child window id according to
3375 * CLIENTCREATESTRUCT.idFirstChild
3377 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3378 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3379 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3380 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3381 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3382 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3383 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3384 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3386 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3387 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3389 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3391 /* Win9x: message sequence terminates here. */
3393 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3394 { HCBT_SETFOCUS
, hook
},
3395 { WM_KILLFOCUS
, sent
|defwinproc
|optional
}, /* in the 1st MDI child */
3396 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 }, /* in the 1st MDI child */
3397 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3398 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3399 { WM_SETFOCUS
, sent
}, /* in MDI client */
3400 { HCBT_SETFOCUS
, hook
},
3401 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3402 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3403 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3404 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3405 { WM_SETFOCUS
, sent
|defwinproc
},
3407 { WM_MDIACTIVATE
, sent
|defwinproc
},
3409 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3410 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3411 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3412 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3415 /* WM_MDICREATE MDI child window, initially visible and maximized */
3416 static const struct message WmCreateMDIchildVisibleMaxSeq3
[] = {
3417 { WM_MDICREATE
, sent
},
3418 { HCBT_CREATEWND
, hook
},
3419 { WM_NCCREATE
, sent
},
3420 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3421 { WM_CREATE
, sent
},
3422 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3423 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3425 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3426 { WM_GETMINMAXINFO
, sent
},
3427 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3428 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3429 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3430 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3433 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3434 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3435 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3436 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3437 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3439 /* Win2k sends wparam set to
3440 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3441 * while Win9x doesn't bother to set child window id according to
3442 * CLIENTCREATESTRUCT.idFirstChild
3444 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3445 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3446 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3448 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3450 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3451 { WM_MDIREFRESHMENU
, sent
/*|wparam|lparam, 0, 0*/ },
3452 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
3454 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3455 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3457 /* Win9x: message sequence terminates here. */
3459 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3460 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3461 { HCBT_SETFOCUS
, hook
}, /* in MDI client */
3462 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3463 { WM_IME_NOTIFY
, sent
|wparam
|optional
, 2 },
3464 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
3465 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3466 { HCBT_SETFOCUS
, hook
|optional
},
3467 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3468 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3469 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3470 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3471 { WM_SETFOCUS
, sent
|defwinproc
},
3473 { WM_MDIACTIVATE
, sent
|defwinproc
},
3476 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3477 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3478 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3479 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3482 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3483 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3484 { 0x0093, sent
|defwinproc
|optional
},
3485 { 0x0093, sent
|defwinproc
|optional
},
3486 { 0x0093, sent
|defwinproc
|optional
},
3487 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3488 { WM_MOVE
, sent
|defwinproc
},
3489 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3492 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3493 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3494 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3495 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3498 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3499 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3500 { 0x0093, sent
|optional
},
3501 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3502 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3504 { 0x0093, sent
|optional
},
3505 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3506 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client, not sent on Win7. */
3507 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3508 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP sends it to MDI frame */
3509 { 0x0093, sent
|defwinproc
|optional
},
3510 { 0x0093, sent
|defwinproc
|optional
},
3511 { 0x0093, sent
|defwinproc
|optional
},
3512 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3513 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3517 /* CreateWindow for the 1st MDI child window, initially invisible and maximized */
3518 static const struct message WmCreateMDIchildInvisibleMaxSeq4
[] = {
3519 { HCBT_CREATEWND
, hook
},
3520 { WM_GETMINMAXINFO
, sent
},
3521 { WM_NCCREATE
, sent
},
3522 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
3523 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not sent on Win8+. */
3524 { WM_CREATE
, sent
},
3525 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3526 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3527 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3528 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI frame */
3529 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOZORDER
}, /* MDI frame */
3531 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3532 { WM_GETMINMAXINFO
, sent
},
3533 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_STATECHANGED
},
3534 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3535 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3536 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3537 { WM_MOVE
, sent
|defwinproc
},
3538 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3540 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3541 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3542 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3543 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3544 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* MDI child */
3545 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3546 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3547 /* Win2k sends wparam set to
3548 * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
3549 * while Win9x doesn't bother to set child window id according to
3550 * CLIENTCREATESTRUCT.idFirstChild
3552 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_CREATE*/ }, /* in MDI client */
3555 /* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */
3556 static const struct message WmDestroyMDIchildVisibleMaxSeq2
[] = {
3557 { WM_SYSCOMMAND
, sent
|wparam
, SC_CLOSE
},
3558 { HCBT_SYSCOMMAND
, hook
},
3559 { WM_CLOSE
, sent
|defwinproc
},
3560 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3562 /* bring the 1st MDI child to top */
3563 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 1st MDI child */
3564 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
}, /* in the 2nd MDI child */
3566 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
3568 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 }, /* in the 1st MDI child */
3569 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 0 }, /* in the 1st MDI child */
3570 { WM_MDIACTIVATE
, sent
|defwinproc
}, /* in the 1st MDI child */
3572 /* maximize the 1st MDI child */
3573 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3574 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3575 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3576 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3577 { WM_CHILDACTIVATE
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
3578 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3579 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3581 /* restore the 2nd MDI child */
3582 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 0 },
3583 { HCBT_MINMAX
, hook
|lparam
, 0, SW_NORMALNA
},
3584 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3585 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
3587 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3589 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3590 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3592 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3594 { WM_SETREDRAW
, sent
|defwinproc
|wparam
, 1 },
3596 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3597 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3598 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3599 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3600 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3602 /* bring the 1st MDI child to top */
3603 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3604 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
, 1 },
3605 { HCBT_SETFOCUS
, hook
},
3606 { WM_KILLFOCUS
, sent
|defwinproc
},
3607 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
3608 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3609 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3610 { WM_SETFOCUS
, sent
}, /* in MDI client */
3611 { HCBT_SETFOCUS
, hook
},
3612 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3613 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3614 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3615 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3616 { WM_SETFOCUS
, sent
|defwinproc
},
3617 { WM_MDIACTIVATE
, sent
|defwinproc
},
3618 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3620 /* apparently ShowWindow(SW_SHOW) on an MDI client */
3621 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
3622 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3623 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3624 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3625 { WM_MDIREFRESHMENU
, sent
},
3627 { HCBT_DESTROYWND
, hook
},
3628 /* Win2k sends wparam set to
3629 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3630 * while Win9x doesn't bother to set child window id according to
3631 * CLIENTCREATESTRUCT.idFirstChild
3633 { 0x0090, sent
|defwinproc
|optional
},
3634 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3635 { WM_SHOWWINDOW
, sent
|defwinproc
|wparam
, 0 },
3636 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3637 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3638 { WM_ERASEBKGND
, sent
|parent
|optional
},
3639 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3641 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3642 { WM_DESTROY
, sent
|defwinproc
},
3643 { WM_NCDESTROY
, sent
|defwinproc
},
3646 /* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */
3647 static const struct message WmDestroyMDIchildVisibleMaxSeq1
[] = {
3648 { WM_MDIDESTROY
, sent
}, /* in MDI client */
3649 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3650 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3651 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3652 { WM_ERASEBKGND
, sent
|parent
|optional
},
3653 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3655 { HCBT_SETFOCUS
, hook
},
3656 { WM_KILLFOCUS
, sent
},
3657 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3658 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3659 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3660 { WM_SETFOCUS
, sent
}, /* in MDI client */
3661 { HCBT_SETFOCUS
, hook
},
3662 { WM_KILLFOCUS
, sent
}, /* in MDI client */
3663 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3664 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3665 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3666 { WM_SETFOCUS
, sent
},
3669 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3670 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3671 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3672 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3675 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3676 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3677 { 0x0093, sent
|defwinproc
|optional
},
3678 { 0x0093, sent
|defwinproc
|optional
},
3679 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3680 { WM_MOVE
, sent
|defwinproc
},
3681 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3684 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3685 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3686 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3687 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3690 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3691 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3692 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3693 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3696 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3697 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3698 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3699 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3702 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3703 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3704 { 0x0093, sent
|defwinproc
|optional
},
3705 { 0x0093, sent
|defwinproc
|optional
},
3706 { 0x0093, sent
|defwinproc
|optional
},
3707 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3708 { WM_MOVE
, sent
|defwinproc
},
3709 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3712 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3713 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3714 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3715 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3718 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3719 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3720 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3721 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3722 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3723 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI client */
3725 { 0x0093, sent
|defwinproc
|optional
},
3726 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 }, /* XP sends it to MDI frame */
3727 { 0x0093, sent
|defwinproc
|optional
},
3728 { 0x0093, sent
|defwinproc
|optional
},
3729 { 0x0093, sent
|defwinproc
|optional
},
3730 { 0x0093, sent
|optional
},
3732 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3733 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3734 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI client */
3735 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame */
3736 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3737 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3740 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3741 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3742 { 0x0093, sent
|defwinproc
|optional
},
3743 { 0x0093, sent
|defwinproc
|optional
},
3744 { 0x0093, sent
|defwinproc
|optional
},
3745 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3746 { 0x0093, sent
|optional
}, /* Win8+ sends an extra. */
3747 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3748 { 0x0093, sent
|optional
},
3750 { WM_NCACTIVATE
, sent
|wparam
, 0 },
3751 { WM_MDIACTIVATE
, sent
},
3753 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNORMAL
},
3754 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_STATECHANGED
},
3755 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3757 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3759 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3760 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3761 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3764 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3765 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3766 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3767 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3770 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3771 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3772 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3773 { WM_MOVE
, sent
|defwinproc
},
3774 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3777 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3778 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3779 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
},
3780 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3781 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI child */
3782 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 }, /* XP */
3783 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI client */
3784 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* MDI frame */
3785 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP sends a duplicate */
3787 { HCBT_SETFOCUS
, hook
},
3788 { WM_KILLFOCUS
, sent
},
3789 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
3790 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3791 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3792 { WM_SETFOCUS
, sent
}, /* in MDI client */
3794 { WM_MDIREFRESHMENU
, sent
}, /* in MDI client */
3796 { HCBT_DESTROYWND
, hook
},
3797 /* Win2k sends wparam set to
3798 * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
3799 * while Win9x doesn't bother to set child window id according to
3800 * CLIENTCREATESTRUCT.idFirstChild
3802 { 0x0090, sent
|optional
},
3803 { WM_PARENTNOTIFY
, sent
/*|wparam, WM_DESTROY*/ }, /* in MDI client */
3805 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
3806 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3807 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
3808 { WM_ERASEBKGND
, sent
|parent
|optional
},
3809 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3811 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
3812 { WM_DESTROY
, sent
},
3813 { WM_NCDESTROY
, sent
},
3816 /* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */
3817 static const struct message WmMaximizeMDIchildInvisibleSeq
[] = {
3818 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3819 { WM_GETMINMAXINFO
, sent
},
3820 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3821 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3822 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3823 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3825 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
|defwinproc
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3826 { WM_NCACTIVATE
, sent
|wparam
|optional
|defwinproc
, 1 },
3827 { HCBT_SETFOCUS
, hook
|optional
},
3828 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3829 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3830 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3831 { HCBT_SETFOCUS
, hook
|optional
},
3832 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3833 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3834 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3835 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3836 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
3837 { WM_MDIACTIVATE
, sent
|optional
|defwinproc
},
3838 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3839 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3841 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3842 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3843 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3844 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3845 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3848 /* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */
3849 static const struct message WmMaximizeMDIchildInvisibleSeq2
[] = {
3850 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3851 { WM_GETMINMAXINFO
, sent
},
3852 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
3853 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3854 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3855 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
3856 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3858 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3859 { WM_NCACTIVATE
, sent
|wparam
|defwinproc
|optional
, 1 },
3860 { HCBT_SETFOCUS
, hook
|optional
},
3861 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 }, /* in MDI client */
3862 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3863 { WM_SETFOCUS
, sent
|optional
}, /* in MDI client */
3864 { HCBT_SETFOCUS
, hook
|optional
},
3865 { WM_KILLFOCUS
, sent
|optional
}, /* in MDI client */
3866 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 }, /* in MDI client */
3867 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
3868 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3869 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
3870 { WM_MDIACTIVATE
, sent
|defwinproc
|optional
},
3871 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_STATECHANGED
/* w1064v1809 */ },
3872 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child, not sent on Win8+. */
3873 { WM_SIZE
, sent
|defwinproc
|optional
},
3874 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* w1064v1809. */
3877 /* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
3878 static const struct message WmMaximizeMDIchildInvisibleParentSeq
[] = {
3879 { WM_MDIMAXIMIZE
, sent
}, /* in MDI client */
3880 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3881 { WM_GETMINMAXINFO
, sent
},
3882 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3883 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3884 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3885 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* XP doesn't send it */
3886 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3887 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOREDRAW
|SWP_STATECHANGED
},
3888 { WM_MOVE
, sent
|defwinproc
},
3889 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3891 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3892 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3893 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3894 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3895 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3896 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3898 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3899 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3900 { 0x0093, sent
|defwinproc
|optional
},
3901 { 0x0094, sent
|defwinproc
|optional
},
3902 { 0x0094, sent
|defwinproc
|optional
},
3903 { 0x0094, sent
|defwinproc
|optional
},
3904 { 0x0094, sent
|defwinproc
|optional
},
3905 { 0x0093, sent
|defwinproc
|optional
},
3906 { 0x0093, sent
|defwinproc
|optional
},
3907 { 0x0091, sent
|defwinproc
|optional
},
3908 { 0x0092, sent
|defwinproc
|optional
},
3909 { 0x0092, sent
|defwinproc
|optional
},
3910 { 0x0092, sent
|defwinproc
|optional
},
3911 { 0x0092, sent
|defwinproc
|optional
},
3912 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3913 { WM_MOVE
, sent
|defwinproc
},
3914 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3915 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame win2000 */
3917 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOACTIVATE
},
3918 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3919 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3920 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
3922 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
},
3923 { WM_GETMINMAXINFO
, sent
|defwinproc
},
3924 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
3925 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTMOVE
},
3926 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3927 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child win2000 */
3928 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
3929 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3930 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3931 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI client XP */
3933 { 0x0093, sent
|optional
},
3934 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
3935 { 0x0093, sent
|defwinproc
|optional
},
3936 { 0x0093, sent
|defwinproc
|optional
},
3937 { 0x0093, sent
|defwinproc
|optional
},
3938 { 0x0091, sent
|defwinproc
|optional
},
3939 { 0x0092, sent
|defwinproc
|optional
},
3940 { 0x0092, sent
|defwinproc
|optional
},
3941 { 0x0092, sent
|defwinproc
|optional
},
3942 { 0x0092, sent
|defwinproc
|optional
},
3943 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3944 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI frame XP */
3945 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* MDI child XP */
3948 /* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */
3949 static const struct message WmMaximizeMDIchildVisibleSeq
[] = {
3950 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MAXIMIZE
},
3951 { WM_GETMINMAXINFO
, sent
},
3952 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3953 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3954 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3955 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3956 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_MAXIMIZED
},
3958 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3959 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3960 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3961 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3962 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3965 /* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */
3966 static const struct message WmRestoreMDIchildVisibleSeq
[] = {
3967 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3968 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
3969 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3970 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3971 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
3972 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3974 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
3975 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3976 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
3977 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
3978 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3981 /* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */
3982 static const struct message WmRestoreMDIchildVisibleSeq_2
[] = {
3983 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
3984 { WM_QUERYOPEN
, sent
|wparam
|lparam
, 0, 0 },
3985 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3986 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
3987 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
3988 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
3989 { WM_MOVE
, sent
|defwinproc
},
3990 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
3991 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3992 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
3993 { HCBT_SETFOCUS
, hook
},
3994 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
3995 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
3996 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
3997 { WM_SETFOCUS
, sent
},
4000 /* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */
4001 static const struct message WmMinimizeMDIchildVisibleSeq
[] = {
4002 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
4003 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
4004 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
4005 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
4006 { WM_MOVE
, sent
|defwinproc
},
4007 { WM_SIZE
, sent
|defwinproc
|wparam
|lparam
, SIZE_MINIMIZED
, 0 },
4008 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
4009 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
4010 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
4013 /* ShowWindow(SW_RESTORE) for a not visible MDI child window */
4014 static const struct message WmRestoreMDIchildInvisibleSeq
[] = {
4015 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
4016 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
4017 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
4018 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
4019 { WM_CHILDACTIVATE
, sent
|wparam
|lparam
, 0, 0 },
4020 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOMOVE
|SWP_NOCLIENTMOVE
|SWP_STATECHANGED
},
4021 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
4023 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
4024 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
4025 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
4026 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI frame */
4027 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 }, /* MDI child */
4031 static HWND mdi_client
;
4032 static WNDPROC old_mdi_client_proc
;
4034 static LRESULT WINAPI
mdi_client_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4036 struct recvd_message msg
;
4038 /* do not log painting messages */
4039 if (message
!= WM_PAINT
&&
4040 message
!= WM_NCPAINT
&&
4041 message
!= WM_SYNCPAINT
&&
4042 message
!= WM_ERASEBKGND
&&
4043 message
!= WM_NCHITTEST
&&
4044 message
!= WM_GETTEXT
&&
4045 message
!= WM_MDIGETACTIVE
&&
4046 !ignore_message( message
))
4049 msg
.message
= message
;
4050 msg
.flags
= sent
|wparam
|lparam
;
4051 msg
.wParam
= wParam
;
4052 msg
.lParam
= lParam
;
4053 msg
.descr
= "mdi client";
4057 return CallWindowProcA(old_mdi_client_proc
, hwnd
, message
, wParam
, lParam
);
4060 static LRESULT WINAPI
mdi_child_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4062 static LONG defwndproc_counter
= 0;
4064 struct recvd_message msg
;
4066 /* do not log painting messages */
4067 if (message
!= WM_PAINT
&&
4068 message
!= WM_NCPAINT
&&
4069 message
!= WM_SYNCPAINT
&&
4070 message
!= WM_ERASEBKGND
&&
4071 message
!= WM_NCHITTEST
&&
4072 message
!= WM_GETTEXT
&&
4073 !ignore_message( message
))
4077 case WM_MDIACTIVATE
:
4079 HWND active
, client
= GetParent(hwnd
);
4081 active
= (HWND
)SendMessageA(client
, WM_MDIGETACTIVE
, 0, 0);
4083 if (hwnd
== (HWND
)lParam
) /* if we are being activated */
4084 ok (active
== (HWND
)lParam
, "new active %p != active %p\n", (HWND
)lParam
, active
);
4086 ok (active
== (HWND
)wParam
, "old active %p != active %p\n", (HWND
)wParam
, active
);
4092 msg
.message
= message
;
4093 msg
.flags
= sent
|wparam
|lparam
;
4094 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4095 msg
.wParam
= wParam
;
4096 msg
.lParam
= lParam
;
4097 msg
.descr
= "mdi child";
4101 defwndproc_counter
++;
4102 ret
= DefMDIChildProcA(hwnd
, message
, wParam
, lParam
);
4103 defwndproc_counter
--;
4108 static LRESULT WINAPI
mdi_frame_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4110 static LONG defwndproc_counter
= 0;
4112 struct recvd_message msg
;
4114 /* do not log painting messages */
4115 if (message
!= WM_PAINT
&&
4116 message
!= WM_NCPAINT
&&
4117 message
!= WM_SYNCPAINT
&&
4118 message
!= WM_ERASEBKGND
&&
4119 message
!= WM_NCHITTEST
&&
4120 message
!= WM_GETTEXT
&&
4121 !ignore_message( message
))
4124 msg
.message
= message
;
4125 msg
.flags
= sent
|wparam
|lparam
;
4126 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
4127 msg
.wParam
= wParam
;
4128 msg
.lParam
= lParam
;
4129 msg
.descr
= "mdi frame";
4133 defwndproc_counter
++;
4134 ret
= DefFrameProcA(hwnd
, mdi_client
, message
, wParam
, lParam
);
4135 defwndproc_counter
--;
4140 static void mdi_register_classes(void)
4146 cls
.lpfnWndProc
= mdi_frame_wnd_proc
;
4149 cls
.hInstance
= GetModuleHandleA(0);
4151 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
4152 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
4153 cls
.lpszMenuName
= NULL
;
4154 cls
.lpszClassName
= "MDI_frame_class";
4155 register_class(&cls
);
4157 cls
.lpfnWndProc
= mdi_child_wnd_proc
;
4158 cls
.lpszClassName
= "MDI_child_class";
4159 register_class(&cls
);
4161 ret
= GetClassInfoA(0, "MDIClient", &cls
);
4162 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
4163 old_mdi_client_proc
= cls
.lpfnWndProc
;
4164 cls
.hInstance
= GetModuleHandleA(0);
4165 cls
.lpfnWndProc
= mdi_client_hook_proc
;
4166 cls
.lpszClassName
= "MDI_client_class";
4167 register_class(&cls
);
4170 static void test_mdi_messages(void)
4172 MDICREATESTRUCTA mdi_cs
;
4173 CLIENTCREATESTRUCT client_cs
;
4174 HWND mdi_frame
, mdi_child
, mdi_child2
, active_child
;
4177 HMENU hMenu
= CreateMenu();
4180 mdi_register_classes();
4184 if (winetest_debug
> 1) trace("creating MDI frame window\n");
4185 mdi_frame
= CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
4186 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
4187 WS_MAXIMIZEBOX
| WS_VISIBLE
,
4188 100, 100, CW_USEDEFAULT
, CW_USEDEFAULT
,
4189 GetDesktopWindow(), hMenu
,
4190 GetModuleHandleA(0), NULL
);
4191 ok(!!mdi_frame
, "Failed to create window, error %lu.\n", GetLastError());
4192 ok_sequence(WmCreateMDIframeSeq
, "Create MDI frame window", FALSE
);
4194 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4195 ok(GetFocus() == mdi_frame
, "wrong focus window %p\n", GetFocus());
4197 if (winetest_debug
> 1) trace("creating MDI client window\n");
4198 GetClientRect(mdi_frame
, &rc
);
4199 client_cs
.hWindowMenu
= 0;
4200 client_cs
.idFirstChild
= MDI_FIRST_CHILD_ID
;
4201 mdi_client
= CreateWindowExA(0, "MDI_client_class",
4203 WS_CHILD
| WS_VISIBLE
| MDIS_ALLCHILDSTYLES
,
4204 rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
4205 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4206 ok(!!mdi_client
, "Failed to create window, error %lu.\n", GetLastError());
4207 SetWindowLongA(mdi_client
, 0, 0xdeadbeef);
4209 ok_sequence(WmCreateMDIclientSeq
, "Create visible MDI client window", FALSE
);
4210 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4211 ok(GetFocus() == mdi_frame
, "input focus should be on MDI frame not on %p\n", GetFocus());
4213 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4214 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4215 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4220 if (winetest_debug
> 1) trace("creating invisible MDI child window\n");
4221 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4223 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4224 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4225 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4228 ShowWindow(mdi_child
, SW_SHOWNORMAL
);
4229 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE
);
4231 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4232 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4234 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4235 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4237 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4238 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4239 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4241 ShowWindow(mdi_child
, SW_HIDE
);
4242 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE) MDI child window", FALSE
);
4245 ShowWindow(mdi_child
, SW_SHOW
);
4246 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW) MDI child window", FALSE
);
4248 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4249 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4251 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4252 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4254 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4255 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4256 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4258 DestroyWindow(mdi_child
);
4261 if (winetest_debug
> 1) trace("creating visible MDI child window\n");
4262 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4263 WS_CHILD
| WS_VISIBLE
,
4264 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4265 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4266 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4267 ok_sequence(WmCreateMDIchildVisibleSeq
, "Create visible MDI child window", FALSE
);
4269 ok(GetWindowLongA(mdi_child
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4270 ok(IsWindowVisible(mdi_child
), "MDI child should be visible\n");
4272 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4273 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4275 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4276 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4277 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4280 DestroyWindow(mdi_child
);
4281 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4283 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4284 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4286 /* Win2k: MDI client still returns a just destroyed child as active
4287 * Win9x: MDI client returns 0
4289 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4290 ok(active_child
== mdi_child
|| /* win2k */
4291 !active_child
, /* win9x */
4292 "wrong active MDI child %p\n", active_child
);
4293 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4297 if (winetest_debug
> 1) trace("creating invisible MDI child window\n");
4298 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4300 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4301 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4302 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4303 ok_sequence(WmCreateMDIchildInvisibleSeq
, "Create invisible MDI child window", FALSE
);
4305 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should not be visible\n");
4306 ok(!IsWindowVisible(mdi_child2
), "MDI child should not be visible\n");
4308 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4309 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4311 /* Win2k: MDI client still returns a just destroyed child as active
4312 * Win9x: MDI client returns mdi_child2
4314 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4315 ok(active_child
== mdi_child
|| /* win2k */
4316 active_child
== mdi_child2
, /* win9x */
4317 "wrong active MDI child %p\n", active_child
);
4318 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4321 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4322 ok_sequence(WmMaximizeMDIchildInvisibleSeq
, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE
);
4324 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4325 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4327 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4328 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4329 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4332 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4333 ok(GetFocus() == mdi_child2
|| /* win2k */
4334 GetFocus() == 0, /* win9x */
4335 "wrong focus window %p\n", GetFocus());
4340 ShowWindow(mdi_child2
, SW_HIDE
);
4341 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4343 ShowWindow(mdi_child2
, SW_RESTORE
);
4344 ok_sequence(WmRestoreMDIchildInvisibleSeq
, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE
);
4347 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4348 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4350 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4351 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4352 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4358 ShowWindow(mdi_child2
, SW_HIDE
);
4359 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4361 ShowWindow(mdi_child2
, SW_SHOW
);
4362 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):MDI child", FALSE
);
4364 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4365 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4367 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4368 ok_sequence(WmMaximizeMDIchildVisibleSeq
, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE
);
4370 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4371 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4373 ShowWindow(mdi_child2
, SW_RESTORE
);
4374 ok_sequence(WmRestoreMDIchildVisibleSeq
, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE
);
4376 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4377 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4379 ShowWindow(mdi_child2
, SW_MINIMIZE
);
4380 ok_sequence(WmMinimizeMDIchildVisibleSeq
, "ShowWindow(SW_MINIMIZE):MDI child", FALSE
);
4382 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4383 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4385 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4386 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4387 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4390 ShowWindow(mdi_child2
, SW_RESTORE
);
4391 ok_sequence(WmRestoreMDIchildVisibleSeq_2
, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE
);
4393 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4394 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4396 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4397 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4398 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4404 ShowWindow(mdi_child2
, SW_HIDE
);
4405 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):MDI child", FALSE
);
4407 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4408 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4410 DestroyWindow(mdi_child2
);
4411 ok_sequence(WmDestroyMDIchildInvisibleSeq
, "Destroy invisible MDI child window", FALSE
);
4413 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4414 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4416 if (winetest_debug
> 1) trace("Testing WM_CHILDACTIVATE\n");
4418 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4419 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_DISABLED
,
4420 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4421 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4423 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4424 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
,
4425 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4426 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4428 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4429 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4430 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4433 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4434 ok_sequence(WmChildActivateDisabledWindowSeq
, "WM_CHILDACTIVATE sent to disabled window", FALSE
);
4436 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4437 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4438 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4441 EnableWindow(mdi_child
, TRUE
);
4443 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4444 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4445 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4448 SendMessageW(mdi_child
, WM_CHILDACTIVATE
, 0, 0);
4449 ok_sequence(WmChildActivateWindowSeq
, "WM_CHILDACTIVATE sent to enabled window", FALSE
);
4451 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4452 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4453 ok(!zoomed
, "wrong zoomed state %d\n", zoomed
);
4456 DestroyWindow(mdi_child
);
4457 DestroyWindow(mdi_child2
);
4460 /* test for maximized MDI children */
4461 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 1\n");
4462 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4463 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4464 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4465 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4466 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4467 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window", TRUE
);
4468 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4470 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4471 ok(GetFocus() == mdi_child
|| /* win2k */
4472 GetFocus() == 0, /* win9x */
4473 "wrong focus window %p\n", GetFocus());
4475 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4476 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4477 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4480 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 2\n");
4481 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4482 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4483 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4484 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4485 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4486 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4487 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4488 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4490 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4491 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4493 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4494 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4495 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4498 if (winetest_debug
> 1) trace("destroying maximized visible MDI child window 2\n");
4499 DestroyWindow(mdi_child2
);
4500 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4502 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4504 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4505 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4507 /* Win2k: MDI client still returns a just destroyed child as active
4508 * Win9x: MDI client returns 0
4510 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4511 ok(active_child
== mdi_child2
|| /* win2k */
4512 !active_child
, /* win9x */
4513 "wrong active MDI child %p\n", active_child
);
4516 ShowWindow(mdi_child
, SW_MAXIMIZE
);
4517 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4520 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4521 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4523 if (winetest_debug
> 1) trace("re-creating maximized visible MDI child window 2\n");
4524 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4525 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4526 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4527 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4528 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4529 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child 2 window", TRUE
);
4530 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized\n");
4531 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized\n");
4533 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4534 ok(GetFocus() == mdi_child2
, "wrong focus window %p\n", GetFocus());
4536 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4537 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4538 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4541 SendMessageA(mdi_child2
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
4542 ok_sequence(WmDestroyMDIchildVisibleMaxSeq2
, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE
);
4543 ok(!IsWindow(mdi_child2
), "MDI child 2 should be destroyed\n");
4545 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized\n");
4546 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4547 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4549 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4550 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4551 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4554 DestroyWindow(mdi_child
);
4555 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible MDI child window", TRUE
);
4557 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4558 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
4560 /* Win2k: MDI client still returns a just destroyed child as active
4561 * Win9x: MDI client returns 0
4563 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4564 ok(active_child
== mdi_child
|| /* win2k */
4565 !active_child
, /* win9x */
4566 "wrong active MDI child %p\n", active_child
);
4569 if (winetest_debug
> 1) trace("creating maximized invisible MDI child window\n");
4570 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4571 WS_CHILD
| WS_MAXIMIZE
| WS_CAPTION
| WS_THICKFRAME
,
4572 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4573 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4574 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4575 ok_sequence(WmCreateMDIchildInvisibleMaxSeq4
, "Create maximized invisible MDI child window", FALSE
);
4576 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4577 ok(!(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
), "MDI child should be not visible\n");
4578 ok(!IsWindowVisible(mdi_child2
), "MDI child should be not visible\n");
4580 /* Win2k: MDI client still returns a just destroyed child as active
4581 * Win9x: MDI client returns 0
4583 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4584 ok(active_child
== mdi_child
|| /* win2k */
4585 !active_child
|| active_child
== mdi_child2
, /* win9x */
4586 "wrong active MDI child %p\n", active_child
);
4589 if (winetest_debug
> 1) trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n");
4590 ShowWindow(mdi_child2
, SW_MAXIMIZE
);
4591 ok_sequence(WmMaximizeMDIchildInvisibleSeq2
, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE
);
4592 ok(IsZoomed(mdi_child2
), "MDI child should be maximized\n");
4593 ok(GetWindowLongA(mdi_child2
, GWL_STYLE
) & WS_VISIBLE
, "MDI child should be visible\n");
4594 ok(IsWindowVisible(mdi_child2
), "MDI child should be visible\n");
4596 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4597 ok(active_child
== mdi_child2
, "wrong active MDI child %p\n", active_child
);
4598 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4601 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4604 /* end of test for maximized MDI children */
4607 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 1(Switch test)\n");
4608 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4609 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4610 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4611 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4612 ok(!!mdi_child
, "Failed to create window, error %lu.\n", GetLastError());
4613 ok_sequence(WmCreateMDIchildVisibleMaxSeq1
, "Create maximized visible 1st MDI child window(Switch test)", TRUE
);
4614 ok(IsZoomed(mdi_child
), "1st MDI child should be maximized(Switch test)\n");
4616 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4617 ok(GetFocus() == mdi_child
|| /* win2k */
4618 GetFocus() == 0, /* win9x */
4619 "wrong focus window %p(Switch test)\n", GetFocus());
4621 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4622 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4623 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4626 if (winetest_debug
> 1) trace("creating maximized visible MDI child window 2(Switch test)\n");
4627 mdi_child2
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4628 WS_CHILD
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
,
4629 0, 0, CW_USEDEFAULT
, CW_USEDEFAULT
,
4630 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4631 ok(!!mdi_child2
, "Failed to create window, error %lu.\n", GetLastError());
4632 ok_sequence(WmCreateMDIchildVisibleMaxSeq2
, "Create maximized visible 2nd MDI child window (Switch test)", TRUE
);
4634 ok(IsZoomed(mdi_child2
), "2nd MDI child should be maximized(Switch test)\n");
4635 ok(!IsZoomed(mdi_child
), "1st MDI child should NOT be maximized(Switch test)\n");
4637 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p(Switch test)\n", GetActiveWindow());
4638 ok(GetFocus() == mdi_child2
, "wrong focus window %p(Switch test)\n", GetFocus());
4640 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4641 ok(active_child
== mdi_child2
, "wrong active MDI child %p(Switch test)\n", active_child
);
4642 ok(zoomed
, "wrong zoomed state %d(Switch test)\n", zoomed
);
4645 if (winetest_debug
> 1) trace("Switch child window.\n");
4646 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child
, 0);
4647 ok_sequence(WmSwitchChild
, "Child did not switch correctly", TRUE
);
4648 if (winetest_debug
> 1) trace("end of test for switch maximized MDI children\n");
4651 /* Prepare for switching test of not maximized MDI children */
4652 ShowWindow( mdi_child
, SW_NORMAL
);
4653 ok(!IsZoomed(mdi_child
), "wrong zoomed state for %p(Switch test)\n", mdi_child
);
4654 ok(!IsZoomed(mdi_child2
), "wrong zoomed state for %p(Switch test)\n", mdi_child2
);
4655 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, 0);
4656 ok(active_child
== mdi_child
, "wrong active MDI child %p(Switch test)\n", active_child
);
4659 SendMessageA(mdi_client
, WM_MDIACTIVATE
, (WPARAM
)mdi_child2
, 0);
4660 ok_sequence(WmSwitchNotMaximizedChild
, "Not maximized child did not switch correctly", FALSE
);
4661 if (winetest_debug
> 1) trace("end of test for switch not maximized MDI children\n");
4664 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4667 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child2
, 0);
4672 /* end of tests for switch maximized/not maximized MDI children */
4674 mdi_cs
.szClass
= "MDI_child_Class";
4675 mdi_cs
.szTitle
= "MDI child";
4676 mdi_cs
.hOwner
= GetModuleHandleA(0);
4679 mdi_cs
.cx
= CW_USEDEFAULT
;
4680 mdi_cs
.cy
= CW_USEDEFAULT
;
4681 mdi_cs
.style
= WS_CHILD
| WS_SYSMENU
| WS_VISIBLE
| WS_MAXIMIZEBOX
| WS_MAXIMIZE
;
4683 mdi_child
= (HWND
)SendMessageA(mdi_client
, WM_MDICREATE
, 0, (LPARAM
)&mdi_cs
);
4684 ok(mdi_child
!= 0, "MDI child creation failed\n");
4685 ok_sequence(WmCreateMDIchildVisibleMaxSeq3
, "WM_MDICREATE for maximized visible MDI child window", TRUE
);
4687 ok(GetMenuItemID(hMenu
, GetMenuItemCount(hMenu
) - 1) == SC_CLOSE
, "SC_CLOSE menu item not found\n");
4689 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4690 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4692 ok(IsZoomed(mdi_child
), "MDI child should be maximized\n");
4693 ok(GetActiveWindow() == mdi_frame
, "wrong active window %p\n", GetActiveWindow());
4694 ok(GetFocus() == mdi_child
, "wrong focus window %p\n", GetFocus());
4696 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4697 ok(active_child
== mdi_child
, "wrong active MDI child %p\n", active_child
);
4698 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4701 SendMessageA(mdi_client
, WM_MDIDESTROY
, (WPARAM
)mdi_child
, 0);
4702 ok_sequence(WmDestroyMDIchildVisibleMaxSeq1
, "Destroy visible maximized MDI child window", TRUE
);
4704 ok(!IsWindow(mdi_child
), "MDI child should be destroyed\n");
4705 active_child
= (HWND
)SendMessageA(mdi_client
, WM_MDIGETACTIVE
, 0, (LPARAM
)&zoomed
);
4706 ok(!active_child
, "wrong active MDI child %p\n", active_child
);
4711 val
= GetWindowLongA(mdi_client
, 0);
4712 ok(val
== 0xdeadbeef || broken(val
== 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%lx\n", val
);
4713 DestroyWindow(mdi_client
);
4714 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4716 /* test maximization of MDI child with invisible parent */
4717 client_cs
.hWindowMenu
= 0;
4718 mdi_client
= CreateWindowA("MDI_client_class",
4720 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
| WS_VISIBLE
,
4722 mdi_frame
, 0, GetModuleHandleA(0), &client_cs
);
4723 ok_sequence(WmCreateMDIclientSeq
, "Create MDI client window", FALSE
);
4725 ShowWindow(mdi_client
, SW_HIDE
);
4726 ok_sequence(WmHideMDIclientSeq
, "Hide MDI client window", FALSE
);
4728 mdi_child
= CreateWindowExA(WS_EX_MDICHILD
, "MDI_child_class", "MDI child",
4729 WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
,
4731 mdi_client
, 0, GetModuleHandleA(0), NULL
);
4732 ok_sequence(WmCreateMDIchildInvisibleParentSeq
, "Create MDI child window with invisible parent", FALSE
);
4734 SendMessageA(mdi_client
, WM_MDIMAXIMIZE
, (WPARAM
) mdi_child
, 0);
4735 ok_sequence(WmMaximizeMDIchildInvisibleParentSeq
, "Maximize MDI child window with invisible parent", TRUE
);
4736 zoomed
= IsZoomed(mdi_child
);
4737 ok(zoomed
, "wrong zoomed state %d\n", zoomed
);
4739 ShowWindow(mdi_client
, SW_SHOW
);
4740 ok_sequence(WmShowMDIclientSeq
, "Show MDI client window", FALSE
);
4742 DestroyWindow(mdi_child
);
4743 ok_sequence(WmDestroyMDIchildVisibleSeq
, "Destroy visible maximized MDI child window", TRUE
);
4745 /* end of test for maximization of MDI child with invisible parent */
4747 DestroyWindow(mdi_client
);
4748 ok_sequence(WmDestroyMDIclientSeq
, "Destroy MDI client window", FALSE
);
4750 DestroyWindow(mdi_frame
);
4751 ok_sequence(WmDestroyMDIframeSeq
, "Destroy MDI frame window", FALSE
);
4753 /************************* End of MDI test **********************************/
4755 static void test_WM_SETREDRAW(HWND hwnd
)
4757 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4762 SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
4763 ok_sequence(WmSetRedrawFalseSeq
, "SetRedraw:FALSE", FALSE
);
4765 ok(!(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should NOT be set\n");
4766 ok(!IsWindowVisible(hwnd
), "IsWindowVisible() should return FALSE\n");
4769 SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
4770 ok_sequence(WmSetRedrawTrueSeq
, "SetRedraw:TRUE", FALSE
);
4772 ok(GetWindowLongA(hwnd
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
4773 ok(IsWindowVisible(hwnd
), "IsWindowVisible() should return TRUE\n");
4775 /* restore original WS_VISIBLE state */
4776 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
4782 static INT_PTR CALLBACK
TestModalDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4784 struct recvd_message msg
;
4786 if (ignore_message( message
)) return 0;
4792 case WM_NCMOUSEMOVE
:
4793 case WM_NCMOUSELEAVE
:
4801 msg
.message
= message
;
4802 msg
.flags
= sent
|wparam
|lparam
;
4803 msg
.wParam
= wParam
;
4804 msg
.lParam
= lParam
;
4805 msg
.descr
= "dialog";
4808 if (message
== WM_INITDIALOG
) SetTimer( hwnd
, 1, 100, NULL
);
4809 if (message
== WM_TIMER
) EndDialog( hwnd
, 0 );
4813 static INT_PTR CALLBACK
TestModalDlgProc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
4815 struct recvd_message msg
;
4817 if (ignore_message( message
)) return 0;
4823 case WM_NCMOUSEMOVE
:
4824 case WM_NCMOUSELEAVE
:
4832 msg
.message
= message
;
4833 msg
.flags
= sent
|wparam
|lparam
;
4834 msg
.wParam
= wParam
;
4835 msg
.lParam
= lParam
;
4836 msg
.descr
= "dialog";
4839 if (message
== WM_INITDIALOG
) EndDialog( hwnd
, 0 );
4843 static void test_hv_scroll_1(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4845 DWORD style
, exstyle
;
4849 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4850 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4851 /* do not be confused by WS_DLGFRAME set */
4852 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4854 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
4855 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
4857 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4858 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4859 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4860 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE
);
4862 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE
);
4864 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4865 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
4866 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
4868 /* a subsequent call should do nothing */
4869 ret
= SetScrollRange(hwnd
, ctl
, min
, max
, FALSE
);
4870 ok( ret
, "SetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4871 ok_sequence(WmEmptySeq
, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4875 ret
= GetScrollRange(hwnd
, ctl
, &xmin
, &xmax
);
4876 ok( ret
, "GetScrollRange(%d) error %ld\n", ctl
, GetLastError());
4877 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4878 ok(xmin
== min
, "unexpected min scroll value %d\n", xmin
);
4879 ok(xmax
== max
, "unexpected max scroll value %d\n", xmax
);
4882 static void test_hv_scroll_2(HWND hwnd
, INT ctl
, DWORD clear
, DWORD set
, INT min
, INT max
)
4884 DWORD style
, exstyle
;
4888 exstyle
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
4889 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4890 /* do not be confused by WS_DLGFRAME set */
4891 if ((style
& WS_CAPTION
) == WS_CAPTION
) style
&= ~WS_CAPTION
;
4893 if (clear
) ok(style
& clear
, "style %08lx should be set\n", clear
);
4894 if (set
) ok(!(style
& set
), "style %08lx should not be set\n", set
);
4896 si
.cbSize
= sizeof(si
);
4897 si
.fMask
= SIF_RANGE
;
4900 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4901 if ((style
& (WS_DLGFRAME
| WS_BORDER
| WS_THICKFRAME
)) || (exstyle
& WS_EX_DLGMODALFRAME
))
4902 ok_sequence(WmSetScrollRangeHV_NC_Seq
, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE
);
4904 ok_sequence(WmSetScrollRangeHVSeq
, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE
);
4906 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4907 if (set
) ok(style
& set
, "style %08lx should be set\n", set
);
4908 if (clear
) ok(!(style
& clear
), "style %08lx should not be set\n", clear
);
4910 /* a subsequent call should do nothing */
4911 SetScrollInfo(hwnd
, ctl
, &si
, TRUE
);
4912 if (style
& WS_HSCROLL
)
4913 ok_sequence(WmSetScrollRangeHSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4914 else if (style
& WS_VSCROLL
)
4915 ok_sequence(WmSetScrollRangeVSeq_empty
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4917 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4919 si
.fMask
= SIF_PAGE
;
4921 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4922 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4926 SetScrollInfo(hwnd
, ctl
, &si
, FALSE
);
4927 ok_sequence(WmEmptySeq
, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4929 si
.fMask
= SIF_RANGE
;
4930 si
.nMin
= 0xdeadbeef;
4931 si
.nMax
= 0xdeadbeef;
4932 ret
= GetScrollInfo(hwnd
, ctl
, &si
);
4933 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
4934 ok_sequence(WmEmptySeq
, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE
);
4935 ok(si
.nMin
== min
, "unexpected min scroll value %d\n", si
.nMin
);
4936 ok(si
.nMax
== max
, "unexpected max scroll value %d\n", si
.nMax
);
4939 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
4940 static void test_scroll_messages(HWND hwnd
)
4951 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4952 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
4953 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4954 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4955 /* values of min and max are undefined */
4958 ret
= SetScrollRange(hwnd
, SB_CTL
, 10, 150, FALSE
);
4959 ok( ret
, "SetScrollRange error %ld\n", GetLastError());
4960 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4961 trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4966 ret
= GetScrollRange(hwnd
, SB_CTL
, &min
, &max
);
4967 ok( ret
, "GetScrollRange error %ld\n", GetLastError());
4968 if (sequence
->message
!= WmGetScrollRangeSeq
[0].message
)
4969 trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4970 /* values of min and max are undefined */
4973 si
.cbSize
= sizeof(si
);
4974 si
.fMask
= SIF_RANGE
;
4977 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4978 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4979 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4982 si
.fMask
= SIF_PAGE
;
4984 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4985 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4986 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4991 SetScrollInfo(hwnd
, SB_CTL
, &si
, FALSE
);
4992 if (sequence
->message
!= WmSetScrollRangeSeq
[0].message
)
4993 trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
4996 si
.fMask
= SIF_RANGE
;
4997 si
.nMin
= 0xdeadbeef;
4998 si
.nMax
= 0xdeadbeef;
4999 ret
= GetScrollInfo(hwnd
, SB_CTL
, &si
);
5000 ok( ret
, "GetScrollInfo error %ld\n", GetLastError());
5001 if (sequence
->message
!= WmGetScrollInfoSeq
[0].message
)
5002 trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence
->message
);
5003 /* values of min and max are undefined */
5006 /* set WS_HSCROLL */
5007 test_hv_scroll_1(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
5008 /* clear WS_HSCROLL */
5009 test_hv_scroll_1(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
5011 /* set WS_HSCROLL */
5012 test_hv_scroll_2(hwnd
, SB_HORZ
, 0, WS_HSCROLL
, 10, 150);
5013 /* clear WS_HSCROLL */
5014 test_hv_scroll_2(hwnd
, SB_HORZ
, WS_HSCROLL
, 0, 0, 0);
5016 /* set WS_VSCROLL */
5017 test_hv_scroll_1(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
5018 /* clear WS_VSCROLL */
5019 test_hv_scroll_1(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
5021 /* set WS_VSCROLL */
5022 test_hv_scroll_2(hwnd
, SB_VERT
, 0, WS_VSCROLL
, 10, 150);
5023 /* clear WS_VSCROLL */
5024 test_hv_scroll_2(hwnd
, SB_VERT
, WS_VSCROLL
, 0, 0, 0);
5027 static void test_showwindow(void)
5029 HWND hwnd
, hwnd2
, hchild
;
5032 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5033 100, 100, 200, 200, 0, 0, 0, NULL
);
5034 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5035 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5036 0, 0, 10, 10, hwnd
, 0, 0, NULL
);
5037 ok (hchild
!= 0, "Failed to create child\n");
5040 /* ShowWindow( SW_SHOWNA) for invisible top level window */
5041 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n");
5042 ok( ShowWindow(hwnd
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5043 ok_sequence(WmSHOWNATopInvisible
, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE
);
5045 /* ShowWindow( SW_SHOWNA) for now visible top level window */
5046 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n");
5047 ok( ShowWindow(hwnd
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5048 ok_sequence(WmSHOWNATopVisible
, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE
);
5049 /* back to invisible */
5050 ShowWindow(hchild
, SW_HIDE
);
5051 ShowWindow(hwnd
, SW_HIDE
);
5053 /* ShowWindow(SW_SHOWNA) with child and parent invisible */
5054 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
5055 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5056 ok_sequence(WmSHOWNAChildInvisParInvis
, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE
);
5057 /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */
5058 ok( ShowWindow(hchild
, SW_SHOW
) != FALSE
, "ShowWindow: window was invisible\n" );
5060 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
5061 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5062 ok_sequence(WmSHOWNAChildVisParInvis
, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE
);
5063 /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
5064 ShowWindow( hwnd
, SW_SHOW
);
5066 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n");
5067 ok( ShowWindow(hchild
, SW_SHOWNA
) != FALSE
, "ShowWindow: window was invisible\n" );
5068 ok_sequence(WmSHOWNAChildVisParVis
, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE
);
5070 /* ShowWindow(SW_SHOWNA) with child invisible and parent visible */
5071 ShowWindow( hchild
, SW_HIDE
);
5073 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n");
5074 ok( ShowWindow(hchild
, SW_SHOWNA
) == FALSE
, "ShowWindow: window was visible\n" );
5075 ok_sequence(WmSHOWNAChildInvisParVis
, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE
);
5078 ok(GetCapture() == hchild
, "wrong capture window %p\n", GetCapture());
5079 DestroyWindow(hchild
);
5080 ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
5082 DestroyWindow(hwnd
);
5087 * 1. Create invisible maximized popup window.
5088 * 2. Move and resize it.
5089 * 3. Show it maximized.
5091 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5092 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
5093 100, 100, 200, 200, 0, 0, 0, NULL
);
5094 ok (hwnd
!= 0, "Failed to create popup window\n");
5095 ok(IsZoomed(hwnd
), "window should be maximized\n");
5096 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5098 GetWindowRect(hwnd
, &rc
);
5099 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
5100 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
5101 "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc
));
5102 /* Reset window's size & position */
5103 SetWindowPos(hwnd
, 0, 10, 10, 200, 200, SWP_NOZORDER
| SWP_NOACTIVATE
);
5104 ok(IsZoomed(hwnd
), "window should be maximized\n");
5107 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5108 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5109 ok(IsZoomed(hwnd
), "window should be maximized\n");
5110 ok_sequence(WmShowMaxPopupResizedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE
);
5112 GetWindowRect(hwnd
, &rc
);
5113 ok( rc
.right
-rc
.left
== GetSystemMetrics(SM_CXSCREEN
) &&
5114 rc
.bottom
-rc
.top
== GetSystemMetrics(SM_CYSCREEN
),
5115 "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc
));
5116 DestroyWindow(hwnd
);
5120 * 1. Create invisible maximized popup window.
5121 * 2. Show it maximized.
5123 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
5124 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
,
5125 100, 100, 200, 200, 0, 0, 0, NULL
);
5126 ok (hwnd
!= 0, "Failed to create popup window\n");
5127 ok(IsZoomed(hwnd
), "window should be maximized\n");
5128 ok_sequence(WmCreateInvisibleMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5130 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n");
5131 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5132 ok(IsZoomed(hwnd
), "window should be maximized\n");
5133 ok_sequence(WmShowMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE
);
5134 DestroyWindow(hwnd
);
5138 * 1. Create visible maximized popup window.
5140 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
5141 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_MAXIMIZE
| WS_VISIBLE
,
5142 100, 100, 200, 200, 0, 0, 0, NULL
);
5143 ok (hwnd
!= 0, "Failed to create popup window\n");
5144 ok(IsZoomed(hwnd
), "window should be maximized\n");
5145 ok_sequence(WmCreateMaxPopupSeq
, "CreateWindow(WS_MAXIMIZED):popup", FALSE
);
5146 DestroyWindow(hwnd
);
5150 * 1. Create visible popup window.
5153 if (winetest_debug
> 1) trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
5154 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP
| WS_VISIBLE
,
5155 100, 100, 200, 200, 0, 0, 0, NULL
);
5156 ok (hwnd
!= 0, "Failed to create popup window\n");
5157 ok(!IsZoomed(hwnd
), "window should NOT be maximized\n");
5158 ok_sequence(WmCreatePopupSeq
, "CreateWindow(WS_VISIBLE):popup", FALSE
);
5160 if (winetest_debug
> 1) trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
5161 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5162 ok(IsZoomed(hwnd
), "window should be maximized\n");
5163 ok_sequence(WmShowVisMaxPopupSeq
, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE
);
5164 DestroyWindow(hwnd
);
5168 * 1. Restoring a minimized window.
5170 hwnd
= CreateWindowA("TestWindowClass", "window1", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5171 ok(hwnd
!= NULL
, "Failed to create window\n");
5173 hwnd2
= CreateWindowA("static", "window2", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5174 ok(hwnd2
!= NULL
, "Failed to create window\n");
5176 ShowWindow(hwnd
, SW_MINIMIZE
);
5177 SetActiveWindow(hwnd2
);
5178 ok(GetActiveWindow() == hwnd2
, "Unexpected active window\n");
5181 ShowWindow(hwnd
, SW_RESTORE
);
5183 ok_sequence(WmShowRestoreMinimizedOverlappedSeq
,
5184 "ShowWindow(hwnd, SW_RESTORE): minimized overlapped", TRUE
);
5186 ShowWindow(hwnd
, SW_MINIMIZE
);
5187 SetActiveWindow(hwnd2
);
5188 ok(GetActiveWindow() == hwnd2
, "Unexpected active window\n");
5191 ShowWindow(hwnd
, SW_SHOWNOACTIVATE
);
5193 ok_sequence(WmShowNoActivateMinimizedOverlappedSeq
,
5194 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): minimized overlapped", TRUE
);
5196 DestroyWindow(hwnd2
);
5197 DestroyWindow(hwnd
);
5201 * 1. Restoring a minimized but active window.
5203 hwnd
= CreateWindowA("TestWindowClass", "parent", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, 0, 0, 0, 0);
5204 ok(hwnd
!= NULL
, "Failed to create window\n");
5206 ShowWindow(hwnd
, SW_MINIMIZE
);
5207 SetActiveWindow(hwnd
);
5208 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
5211 ShowWindow(hwnd
, SW_RESTORE
);
5213 ok_sequence(WmShowRestoreActiveMinimizedOverlappedSeq
,
5214 "ShowWindow(hwnd, SW_RESTORE): active minimized overlapped", TRUE
);
5216 ShowWindow(hwnd
, SW_MINIMIZE
);
5217 SetActiveWindow(hwnd
);
5218 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
5221 ShowWindow(hwnd
, SW_SHOWNOACTIVATE
);
5223 ok_sequence(WmShowNoActivateActiveMinimizedOverlappedSeq
,
5224 "ShowWindow(hwnd, SW_SHOWNOACTIVATE): active minimized overlapped", TRUE
);
5226 DestroyWindow(hwnd
);
5230 static void test_sys_menu(void)
5236 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5237 100, 100, 200, 200, 0, 0, 0, NULL
);
5238 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5242 /* test existing window without CS_NOCLOSE style */
5243 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5244 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5246 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5247 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5248 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
5250 EnableMenuItem(hmenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
5251 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
5253 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5254 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5255 ok((state
& (MF_DISABLED
| MF_GRAYED
)) == MF_GRAYED
, "wrong SC_CLOSE state %x\n", state
);
5257 EnableMenuItem(hmenu
, SC_CLOSE
, 0);
5258 ok_sequence(WmEmptySeq
, "WmEnableMenuItem", FALSE
);
5260 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5261 ok(state
!= 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5262 ok(!(state
& (MF_DISABLED
| MF_GRAYED
)), "wrong SC_CLOSE state %x\n", state
);
5264 /* test whether removing WS_SYSMENU destroys a system menu */
5265 SetWindowLongW(hwnd
, GWL_STYLE
, WS_POPUP
);
5266 SetWindowPos(hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5268 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5269 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5271 DestroyWindow(hwnd
);
5273 /* test new window with CS_NOCLOSE style */
5274 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
5275 100, 100, 200, 200, 0, 0, 0, NULL
);
5276 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5278 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5279 ok(hmenu
!= 0, "GetSystemMenu error %ld\n", GetLastError());
5281 state
= GetMenuState(hmenu
, SC_CLOSE
, MF_BYCOMMAND
);
5282 ok(state
== 0xffffffff, "wrong SC_CLOSE state %x\n", state
);
5284 DestroyWindow(hwnd
);
5286 /* test new window without WS_SYSMENU style */
5287 hwnd
= CreateWindowExA(0, "NoCloseWindowClass", NULL
, WS_OVERLAPPEDWINDOW
& ~WS_SYSMENU
,
5288 100, 100, 200, 200, 0, 0, 0, NULL
);
5289 ok(hwnd
!= 0, "Failed to create overlapped window\n");
5291 hmenu
= GetSystemMenu(hwnd
, FALSE
);
5292 ok(!hmenu
, "GetSystemMenu error %ld\n", GetLastError());
5294 DestroyWindow(hwnd
);
5297 /* For shown WS_OVERLAPPEDWINDOW */
5298 static const struct message WmSetIcon_1
[] = {
5299 { WM_SETICON
, sent
},
5300 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
5301 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5302 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP sends a duplicate */
5306 /* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */
5307 static const struct message WmSetIcon_2
[] = {
5308 { WM_SETICON
, sent
},
5312 /* Sending undocumented 0x3B message with wparam = 0x8000000b */
5313 static const struct message WmInitEndSession
[] = {
5315 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
5319 /* Sending undocumented 0x3B message with wparam = 0x0000000b */
5320 static const struct message WmInitEndSession_2
[] = {
5322 { WM_QUERYENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
5326 /* Sending undocumented 0x3B message with wparam = 0x80000008 */
5327 static const struct message WmInitEndSession_3
[] = {
5329 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, ENDSESSION_LOGOFF
},
5333 /* Sending undocumented 0x3B message with wparam = 0x00000008 */
5334 static const struct message WmInitEndSession_4
[] = {
5336 { WM_ENDSESSION
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
5340 /* Sending undocumented 0x3B message with wparam = 0x80000001 */
5341 static const struct message WmInitEndSession_5
[] = {
5343 { WM_ENDSESSION
, sent
|defwinproc
/*|wparam*/|lparam
, 1, ENDSESSION_LOGOFF
},
5347 static const struct message WmOptionalPaint
[] = {
5348 { WM_PAINT
, sent
|optional
},
5349 { WM_NCPAINT
, sent
|beginpaint
|optional
},
5350 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
5351 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
5355 static const struct message WmZOrder
[] = {
5356 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0, 0 },
5357 { WM_GETMINMAXINFO
, sent
|defwinproc
|wparam
, 0, 0 },
5358 { HCBT_ACTIVATE
, hook
},
5359 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
5360 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
5361 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 3, 0 },
5362 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0 },
5363 { WM_GETTEXT
, sent
|optional
},
5364 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
5365 { WM_ACTIVATEAPP
, sent
|wparam
, 1, 0 },
5366 { WM_NCACTIVATE
, sent
|lparam
, 1, 0 },
5367 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5368 { WM_GETTEXT
, sent
|defwinproc
|optional
},
5369 { WM_ACTIVATE
, sent
|wparam
|lparam
, 1, 0 },
5370 { HCBT_SETFOCUS
, hook
},
5371 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
5372 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
5373 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
5374 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
5375 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
5376 { WM_GETTEXT
, sent
|optional
},
5377 { WM_NCCALCSIZE
, sent
|optional
},
5378 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
5382 static void CALLBACK
apc_test_proc(ULONG_PTR param
)
5387 static void test_MsgWaitForMultipleObjects(HWND hwnd
)
5392 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5393 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5395 PostMessageA(hwnd
, WM_USER
, 0, 0);
5397 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5398 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5400 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5401 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5403 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5404 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5406 PostMessageA(hwnd
, WM_USER
, 0, 0);
5408 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5409 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5411 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5412 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5414 /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */
5415 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5416 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5418 PostMessageA(hwnd
, WM_USER
, 0, 0);
5420 /* new incoming message causes it to become signaled again */
5421 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5422 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5424 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5425 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5426 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5427 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5429 /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
5430 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5431 ok(PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
), "PeekMessage should succeed\n");
5432 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5434 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_INPUTAVAILABLE
);
5435 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5437 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5438 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5440 /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
5441 ret
= QueueUserAPC( apc_test_proc
, GetCurrentThread(), 0 );
5442 ok(ret
, "QueueUserAPC failed %lu\n", GetLastError());
5444 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, 0 );
5445 ok(ret
== WAIT_TIMEOUT
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5447 /* but even with MWMO_ALERTABLE window events are preferred */
5448 PostMessageA( hwnd
, WM_USER
, 0, 0 );
5450 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5451 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5453 ok(PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5454 ok(msg
.message
== WM_USER
, "got %04x instead of WM_USER\n", msg
.message
);
5456 /* the APC call is still queued */
5457 ret
= MsgWaitForMultipleObjectsEx( 0, NULL
, 0, QS_POSTMESSAGE
, MWMO_ALERTABLE
);
5458 ok(ret
== WAIT_IO_COMPLETION
, "MsgWaitForMultipleObjectsEx returned %lx\n", ret
);
5461 static void test_WM_DEVICECHANGE(HWND hwnd
)
5466 static const WPARAM wparams
[] = {0,
5467 DBT_DEVNODES_CHANGED
,
5468 DBT_QUERYCHANGECONFIG
,
5470 DBT_CONFIGCHANGECANCELED
,
5473 DBT_CONFIGMGPRIVATE
, /* 0x7fff */
5474 DBT_DEVICEARRIVAL
, /* 0x8000 */
5475 DBT_DEVICEQUERYREMOVE
,
5476 DBT_DEVICEQUERYREMOVEFAILED
,
5477 DBT_DEVICEREMOVEPENDING
,
5478 DBT_DEVICEREMOVECOMPLETE
,
5479 DBT_DEVICETYPESPECIFIC
,
5482 for (i
= 0; i
< ARRAY_SIZE(wparams
); i
++)
5484 SetLastError(0xdeadbeef);
5485 ret
= PostMessageA(hwnd
, WM_DEVICECHANGE
, wparams
[i
], 0);
5486 if (wparams
[i
] & 0x8000)
5488 ok(ret
== FALSE
, "PostMessage returned %ld\n", ret
);
5489 ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY
, "PostMessage error %08lx\n", GetLastError());
5493 ret
= MsgWaitForMultipleObjects(0, NULL
, FALSE
, 0, QS_POSTMESSAGE
);
5494 ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %lx\n", ret
);
5495 memset(&msg
, 0, sizeof(msg
));
5496 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n");
5497 ok(msg
.message
== WM_DEVICECHANGE
, "got %04x instead of WM_DEVICECHANGE\n", msg
.message
);
5502 static DWORD CALLBACK
hide_window_thread( LPVOID arg
)
5506 /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
5507 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5512 static DWORD CALLBACK
show_window_thread( LPVOID arg
)
5516 /* function will not return if ShowWindow(SW_SHOW) calls SendMessage() */
5517 ok( ShowWindow( hwnd
, SW_SHOW
), "ShowWindow(SW_SHOW) expected TRUE\n" ); /* actually it's 24... */
5522 /* Helper function to easier test SetWindowPos messages */
5523 #define test_msg_setpos( expected_list, flags, todo ) \
5524 test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)
5525 static void test_msg_setpos_(const struct message
*expected_list
, UINT flags
, BOOL todo
, const char *file
, int line
)
5531 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5532 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5533 ok (hwnd
!= 0, "Failed to create popup window\n");
5534 SetWindowPos(hwnd
, NULL
, 0, 0, 100, 100, flags
);
5535 ok_sequence_(expected_list
, "SetWindowPos:show_popup_first_show_window", todo
, file
, line
);
5536 DestroyWindow(hwnd
);
5539 /* test if we receive the right sequence of messages */
5540 static void test_messages(void)
5544 HWND hwnd
, hparent
, hchild
;
5545 HWND hchild2
, hbutton
;
5554 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5555 100, 100, 200, 200, 0, 0, 0, NULL
);
5556 ok (hwnd
!= 0, "Failed to create overlapped window\n");
5557 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5559 /* test ShowWindow(SW_HIDE) on a newly created invisible window */
5560 ok( ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow: window was visible\n" );
5561 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE
);
5563 /* test WM_SETREDRAW on a not visible top level window */
5564 test_WM_SETREDRAW(hwnd
);
5566 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5568 ok_sequence(WmSWP_ShowOverlappedSeq
, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE
);
5569 ok(IsWindowVisible(hwnd
), "window should be visible at this point\n");
5571 ok(GetActiveWindow() == hwnd
, "window should be active\n");
5572 ok(GetFocus() == hwnd
, "window should have input focus\n");
5573 ShowWindow(hwnd
, SW_HIDE
);
5575 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5577 /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
5578 ok(ShowWindow(hwnd
, SW_HIDE
) == FALSE
, "ShowWindow(SW_HIDE) expected FALSE\n");
5580 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5582 /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
5583 hthread
= CreateThread( NULL
, 0, hide_window_thread
, hwnd
, 0, &tid
);
5584 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
5585 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
5586 CloseHandle(hthread
);
5588 ok_sequence(WmEmptySeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5590 ShowWindow(hwnd
, SW_SHOW
);
5592 ok_sequence(WmShowOverlappedSeq
, "ShowWindow(SW_SHOW):overlapped", TRUE
);
5594 /* test ShowWindow(SW_SHOW) on a visible window - multi-threaded */
5595 hthread
= CreateThread( NULL
, 0, show_window_thread
, hwnd
, 0, &tid
);
5596 ok( hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError() );
5597 ok( WaitForSingleObject( hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
5598 CloseHandle( hthread
);
5600 ok_sequence( WmEmptySeq
, "ShowWindow(SW_SHOW):overlapped", FALSE
);
5602 ShowWindow(hwnd
, SW_HIDE
);
5604 ok_sequence(WmHideOverlappedSeq
, "ShowWindow(SW_HIDE):overlapped", FALSE
);
5606 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5608 ok_sequence(WmShowMaxOverlappedSeq
, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE
);
5611 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MAXIMIZE
)
5613 ShowWindow(hwnd
, SW_RESTORE
);
5615 ok_sequence(WmShowRestoreMaxOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", TRUE
);
5619 ShowWindow(hwnd
, SW_MINIMIZE
);
5621 ok_sequence(WmShowMinOverlappedSeq
, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE
);
5624 if (GetWindowLongW( hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
5626 ShowWindow(hwnd
, SW_RESTORE
);
5628 ok_sequence(WmShowRestoreMinOverlappedSeq
, "ShowWindow(SW_RESTORE):overlapped", FALSE
);
5632 ShowWindow(hwnd
, SW_SHOW
);
5634 ok_sequence(WmOptionalPaint
, "ShowWindow(SW_SHOW):overlapped already visible", FALSE
);
5636 SetWindowPos(hwnd
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5637 ok_sequence(WmSWP_HideOverlappedSeq
, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE
);
5638 ok(!IsWindowVisible(hwnd
), "window should not be visible at this point\n");
5639 ok(GetActiveWindow() == hwnd
, "window should still be active\n");
5641 /* test WM_SETREDRAW on a visible top level window */
5642 ShowWindow(hwnd
, SW_SHOW
);
5644 test_WM_SETREDRAW(hwnd
);
5646 if (winetest_debug
> 1) trace("testing scroll APIs on a visible top level window %p\n", hwnd
);
5647 test_scroll_messages(hwnd
);
5649 /* test resizing and moving */
5650 SetWindowPos( hwnd
, 0, 0, 0, 300, 300, SWP_NOMOVE
|SWP_NOACTIVATE
);
5651 ok_sequence(WmSWP_ResizeSeq
, "SetWindowPos:Resize", FALSE
);
5654 SetWindowPos( hwnd
, 0, 200, 200, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
5655 ok_sequence(WmSWP_MoveSeq
, "SetWindowPos:Move", FALSE
);
5658 SetWindowPos( hwnd
, 0, 200, 200, 250, 250, SWP_NOZORDER
|SWP_NOACTIVATE
);
5659 ok_sequence(WmSWP_ResizeNoZOrder
, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE
);
5663 /* popups don't get WM_GETMINMAXINFO */
5664 SetWindowLongW( hwnd
, GWL_STYLE
, WS_VISIBLE
|WS_POPUP
);
5665 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOZORDER
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_FRAMECHANGED
);
5667 SetWindowPos( hwnd
, 0, 0, 0, 200, 200, SWP_NOMOVE
|SWP_NOACTIVATE
);
5668 ok_sequence(WmSWP_ResizePopupSeq
, "SetWindowPos:ResizePopup", FALSE
);
5670 DestroyWindow(hwnd
);
5671 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped", FALSE
);
5673 /* Test if windows are correctly drawn when first shown */
5675 /* Visible, redraw */
5678 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5679 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5680 ok (hwnd
!= 0, "Failed to create popup window\n");
5681 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5682 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_visible", FALSE
);
5683 DestroyWindow(hwnd
);
5685 /* Invisible, show, message */
5688 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5689 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5690 ok (hwnd
!= 0, "Failed to create popup window\n");
5691 ShowWindow(hwnd
, SW_SHOW
);
5692 SendMessageW(hwnd
, WM_PAINT
, 0, 0);
5693 ok_sequence(WmShowPopupFirstDrawSeq_1
, "RedrawWindow:show_popup_first_draw_show", FALSE
);
5694 DestroyWindow(hwnd
);
5696 /* Invisible, show maximized, redraw */
5699 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
,
5700 10, 10, 100, 100, NULL
, 0, 0, NULL
);
5701 ok (hwnd
!= 0, "Failed to create popup window\n");
5702 ShowWindow(hwnd
, SW_SHOWMAXIMIZED
);
5703 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
5704 ok_sequence(WmShowPopupFirstDrawSeq_2
, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE
);
5705 DestroyWindow(hwnd
);
5707 /* Test SetWindowPos */
5708 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
, FALSE
);
5709 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, 0, FALSE
);
5710 test_msg_setpos(WmFirstDrawSetWindowPosSeq6
,
5711 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOCLIENTSIZE
| SWP_NOCLIENTMOVE
| SWP_NOZORDER
, FALSE
);
5713 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOSIZE
, FALSE
);
5714 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOMOVE
, FALSE
);
5715 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTSIZE
, FALSE
);
5716 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCLIENTMOVE
, FALSE
);
5717 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOZORDER
, FALSE
);
5719 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
, FALSE
);
5720 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTMOVE
, FALSE
);
5721 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOCLIENTSIZE
, FALSE
);
5722 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOMOVE
, FALSE
);
5723 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOSIZE
, FALSE
);
5724 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_DEFERERASE
| SWP_NOZORDER
, FALSE
);
5726 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
, FALSE
);
5727 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTMOVE
, FALSE
);
5728 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOCLIENTSIZE
, FALSE
);
5729 test_msg_setpos(WmFirstDrawSetWindowPosSeq4
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOMOVE
, FALSE
);
5730 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOSIZE
, FALSE
);
5731 test_msg_setpos(WmFirstDrawSetWindowPosSeq1
, SWP_SHOWWINDOW
| SWP_NOCOPYBITS
| SWP_NOZORDER
, FALSE
);
5733 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
, FALSE
);
5734 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTMOVE
, FALSE
);
5735 test_msg_setpos(WmFirstDrawSetWindowPosSeq3
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOCLIENTSIZE
, FALSE
);
5736 test_msg_setpos(WmFirstDrawSetWindowPosSeq5
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOMOVE
, FALSE
);
5737 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOSIZE
, FALSE
);
5738 test_msg_setpos(WmFirstDrawSetWindowPosSeq2
, SWP_SHOWWINDOW
| SWP_NOREDRAW
| SWP_NOZORDER
, FALSE
);
5740 /* Test SetWindowPos with child windows */
5742 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5743 100, 100, 200, 200, 0, 0, 0, NULL
);
5744 ok (hparent
!= 0, "Failed to create parent window\n");
5746 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5747 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5748 ok (hchild
!= 0, "Failed to create child window\n");
5750 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5751 ok_sequence(WmFirstDrawChildSeq1
, /* Expect no messages for the child */
5752 "SetWindowPos:show_popup_first_show_window_child1", FALSE
);
5753 DestroyWindow(hchild
);
5754 DestroyWindow(hparent
);
5757 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
,
5758 100, 100, 200, 200, 0, 0, 0, NULL
);
5759 ok (hparent
!= 0, "Failed to create parent window\n");
5761 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
5762 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5763 ok (hchild
!= 0, "Failed to create child window\n");
5765 SetWindowPos(hparent
, NULL
, 0, 0, 100, 100, SWP_SHOWWINDOW
);
5766 ok_sequence(WmFirstDrawChildSeq2
, /* Expect child to be redrawn */
5767 "SetWindowPos:show_popup_first_show_window_child2", FALSE
);
5768 DestroyWindow(hchild
);
5769 DestroyWindow(hparent
);
5771 /* Test message sequence for extreme position and size */
5774 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5775 -10, -10, 10000, 10000, NULL
, 0, 0, NULL
);
5776 ok (hwnd
!= 0, "Failed to create popup window\n");
5777 ok_sequence(WmShowPopupExtremeLocationSeq
, "RedrawWindow:show_popup_extreme_location", FALSE
);
5778 DestroyWindow(hwnd
);
5781 /* Test child windows */
5783 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
5784 100, 100, 200, 200, 0, 0, 0, NULL
);
5785 ok (hparent
!= 0, "Failed to create parent window\n");
5788 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_MAXIMIZE
,
5789 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5790 ok (hchild
!= 0, "Failed to create child window\n");
5791 ok_sequence(WmCreateMaximizedChildSeq
, "CreateWindow:maximized child", FALSE
);
5792 DestroyWindow(hchild
);
5795 /* visible child window with a caption */
5796 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
5797 WS_CHILD
| WS_VISIBLE
| WS_CAPTION
,
5798 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5799 ok (hchild
!= 0, "Failed to create child window\n");
5800 ok_sequence(WmCreateVisibleChildSeq
, "CreateWindow:visible child", FALSE
);
5802 if (winetest_debug
> 1) trace("testing scroll APIs on a visible child window %p\n", hchild
);
5803 test_scroll_messages(hchild
);
5805 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5806 ok_sequence(WmShowChildSeq_4
, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE
);
5808 DestroyWindow(hchild
);
5811 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
5812 0, 0, 10, 10, hparent
, 0, 0, NULL
);
5813 ok (hchild
!= 0, "Failed to create child window\n");
5814 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
5816 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD
,
5817 100, 100, 50, 50, hparent
, 0, 0, NULL
);
5818 ok (hchild2
!= 0, "Failed to create child2 window\n");
5821 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD
,
5822 0, 100, 50, 50, hchild
, 0, 0, NULL
);
5823 ok (hbutton
!= 0, "Failed to create button window\n");
5825 /* test WM_SETREDRAW on a not visible child window */
5826 test_WM_SETREDRAW(hchild
);
5828 ShowWindow(hchild
, SW_SHOW
);
5829 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5831 /* check parent messages too */
5832 log_all_parent_messages
++;
5833 ShowWindow(hchild
, SW_HIDE
);
5834 ok_sequence(WmHideChildSeq2
, "ShowWindow(SW_HIDE):child", FALSE
);
5835 log_all_parent_messages
--;
5837 ShowWindow(hchild
, SW_SHOW
);
5838 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5840 ShowWindow(hchild
, SW_HIDE
);
5841 ok_sequence(WmHideChildSeq
, "ShowWindow(SW_HIDE):child", FALSE
);
5843 ShowWindow(hchild
, SW_SHOW
);
5844 ok_sequence(WmShowChildSeq
, "ShowWindow(SW_SHOW):child", FALSE
);
5846 /* test WM_SETREDRAW on a visible child window */
5847 test_WM_SETREDRAW(hchild
);
5849 log_all_parent_messages
++;
5850 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
5851 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child", FALSE
);
5852 log_all_parent_messages
--;
5854 ShowWindow(hchild
, SW_HIDE
);
5856 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5857 ok_sequence(WmShowChildSeq_2
, "SetWindowPos:show_child_2", FALSE
);
5859 ShowWindow(hchild
, SW_HIDE
);
5861 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
5862 ok_sequence(WmShowChildSeq_3
, "SetWindowPos:show_child_3", FALSE
);
5864 /* DestroyWindow sequence below expects that a child has focus */
5868 DestroyWindow(hchild
);
5869 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child", FALSE
);
5870 DestroyWindow(hchild2
);
5871 DestroyWindow(hbutton
);
5874 hchild
= CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD
| WS_POPUP
,
5875 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5876 ok (hchild
!= 0, "Failed to create child popup window\n");
5877 ok_sequence(WmCreateChildPopupSeq
, "CreateWindow:child_popup", FALSE
);
5878 DestroyWindow(hchild
);
5880 /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
5882 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
,
5883 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5884 ok (hchild
!= 0, "Failed to create popup window\n");
5885 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5886 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5887 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5889 ShowWindow(hchild
, SW_SHOW
);
5890 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5892 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5893 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5895 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
);
5896 ok_sequence(WmShowVisiblePopupSeq_3
, "SetWindowPos:show_visible_popup_3", FALSE
);
5897 DestroyWindow(hchild
);
5899 /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
5900 * changes nothing in message sequences.
5903 hchild
= CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP
| WS_VISIBLE
,
5904 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5905 ok (hchild
!= 0, "Failed to create popup window\n");
5906 ok_sequence(WmCreateInvisiblePopupSeq
, "CreateWindow:invisible_popup", FALSE
);
5907 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
5908 ok(IsWindowVisible(hchild
), "IsWindowVisible() should return TRUE\n");
5910 ShowWindow(hchild
, SW_SHOW
);
5911 ok_sequence(WmEmptySeq
, "ShowWindow:show_visible_popup", FALSE
);
5913 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
5914 ok_sequence(WmShowVisiblePopupSeq_2
, "SetWindowPos:show_visible_popup_2", FALSE
);
5915 DestroyWindow(hchild
);
5918 hwnd
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
, WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
5919 0, 0, 100, 100, hparent
, 0, 0, NULL
);
5920 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5921 ok_sequence(WmCreateCustomDialogSeq
, "CreateCustomDialog", TRUE
);
5924 if (winetest_debug
> 1) trace("testing scroll APIs on a visible dialog %p\n", hwnd
);
5925 test_scroll_messages(hwnd
);
5931 SendMessageA(hwnd
, WM_NULL
, 0, 0);
5934 after_end_dialog
= TRUE
;
5935 EndDialog( hwnd
, 0 );
5936 ok_sequence(WmEndCustomDialogSeq
, "EndCustomDialog", FALSE
);
5938 DestroyWindow(hwnd
);
5939 after_end_dialog
= FALSE
;
5940 test_def_id
= FALSE
;
5942 ok(GetCursorPos(&pos
), "GetCursorPos failed\n");
5943 ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
5945 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_POPUP
|WS_CHILD
,
5946 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
5947 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5949 if (winetest_debug
> 1) trace("call ShowWindow(%p, SW_SHOW)\n", hwnd
);
5950 ShowWindow(hwnd
, SW_SHOW
);
5951 ok_sequence(WmShowCustomDialogSeq
, "ShowCustomDialog", TRUE
);
5955 ret
= DrawMenuBar(hwnd
);
5956 ok(ret
, "DrawMenuBar failed: %ld\n", GetLastError());
5958 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
5959 ok(SetCursorPos(pos
.x
, pos
.y
), "SetCursorPos failed\n");
5961 DestroyWindow(hwnd
);
5963 hwnd
= CreateWindowExA(0, "TestDialogClass", NULL
, WS_CHILD
|WS_VISIBLE
,
5964 0, 0, 100, 100, hparent
, 0, GetModuleHandleA(0), NULL
);
5965 ok(hwnd
!= 0, "Failed to create custom dialog window\n");
5968 ret
= DrawMenuBar(hwnd
);
5969 ok(ret
, "DrawMenuBar failed: %ld\n", GetLastError());
5971 ok_sequence(WmEmptySeq
, "DrawMenuBar for a child window", FALSE
);
5973 DestroyWindow(hwnd
);
5976 DialogBoxA( 0, "TEST_DIALOG", hparent
, TestModalDlgProcA
);
5977 ok_sequence(WmModalDialogSeq
, "ModalDialog", TRUE
);
5979 DestroyWindow(hparent
);
5982 /* Message sequence for SetMenu */
5983 ok(!DrawMenuBar(hwnd
), "DrawMenuBar should return FALSE for a destroyed window\n");
5984 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "last error is %ld\n", GetLastError());
5985 ok_sequence(WmEmptySeq
, "DrawMenuBar for a window without a menu", FALSE
);
5987 hmenu
= CreateMenu();
5988 ok (hmenu
!= 0, "Failed to create menu\n");
5989 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
5990 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
5991 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
5992 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped", FALSE
);
5993 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5994 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange", FALSE
);
5995 ok (SetMenu(hwnd
, 0), "SetMenu\n");
5996 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange", FALSE
);
5997 ShowWindow(hwnd
, SW_SHOW
);
5998 UpdateWindow( hwnd
);
6001 ok (SetMenu(hwnd
, 0), "SetMenu\n");
6002 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange", FALSE
);
6003 ok (SetMenu(hwnd
, hmenu
), "SetMenu\n");
6004 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange", FALSE
);
6006 UpdateWindow( hwnd
);
6009 ok(DrawMenuBar(hwnd
), "DrawMenuBar\n");
6011 ok_sequence(WmDrawMenuBarSeq
, "DrawMenuBar", FALSE
);
6013 DestroyWindow(hwnd
);
6016 /* Message sequence for EnableWindow */
6017 hparent
= CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6018 100, 100, 200, 200, 0, 0, 0, NULL
);
6019 ok (hparent
!= 0, "Failed to create parent window\n");
6020 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
6021 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6022 ok (hchild
!= 0, "Failed to create child window\n");
6028 EnableWindow(hparent
, FALSE
);
6029 ok_sequence(WmEnableWindowSeq_1
, "EnableWindow(FALSE)", FALSE
);
6031 EnableWindow(hparent
, FALSE
);
6032 ok_sequence(WmEnableWindowSeq_2
, "EnableWindow(FALSE)", FALSE
);
6034 EnableWindow(hparent
, TRUE
);
6035 ok_sequence(WmEnableWindowSeq_3
, "EnableWindow(TRUE)", FALSE
);
6037 EnableWindow(hparent
, TRUE
);
6038 ok_sequence(WmEnableWindowSeq_4
, "EnableWindow(TRUE)", FALSE
);
6043 test_MsgWaitForMultipleObjects(hparent
);
6044 test_WM_DEVICECHANGE(hparent
);
6046 /* the following test causes an exception in user.exe under win9x */
6047 if (!PostMessageW( hparent
, WM_USER
, 0, 0 ))
6049 DestroyWindow(hparent
);
6053 PostMessageW( hparent
, WM_USER
+1, 0, 0 );
6054 /* PeekMessage(NULL) fails, but still removes the message */
6055 SetLastError(0xdeadbeef);
6056 ok( !PeekMessageW( NULL
, 0, 0, 0, PM_REMOVE
), "PeekMessage(NULL) should fail\n" );
6057 ok( GetLastError() == ERROR_NOACCESS
|| /* Win2k */
6058 GetLastError() == 0xdeadbeef, /* NT4 */
6059 "last error is %ld\n", GetLastError() );
6060 ok( PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should succeed\n" );
6061 ok( msg
.message
== WM_USER
+1, "got %x instead of WM_USER+1\n", msg
.message
);
6063 DestroyWindow(hchild
);
6064 DestroyWindow(hparent
);
6067 /* Message sequences for WM_SETICON */
6068 if (winetest_debug
> 1) trace("testing WM_SETICON\n");
6069 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
6070 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6072 ShowWindow(hwnd
, SW_SHOW
);
6076 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6077 ok_sequence(WmSetIcon_1
, "WM_SETICON for shown window with caption", FALSE
);
6079 ShowWindow(hwnd
, SW_HIDE
);
6082 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6083 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window with caption", FALSE
);
6084 DestroyWindow(hwnd
);
6087 hwnd
= CreateWindowExA(0, "TestPopupClass", NULL
, WS_POPUP
,
6088 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
6090 ShowWindow(hwnd
, SW_SHOW
);
6094 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6095 ok_sequence(WmSetIcon_2
, "WM_SETICON for shown window without caption", FALSE
);
6097 ShowWindow(hwnd
, SW_HIDE
);
6100 SendMessageA(hwnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)LoadIconA(0, (LPCSTR
)IDI_APPLICATION
));
6101 ok_sequence(WmSetIcon_2
, "WM_SETICON for hidden window without caption", FALSE
);
6104 res
= SendMessageA(hwnd
, 0x3B, 0x8000000b, 0);
6107 todo_wine
win_skip( "Message 0x3b not supported\n" );
6110 ok_sequence(WmInitEndSession
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE
);
6111 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %Id\n", res
);
6112 res
= SendMessageA(hwnd
, 0x3B, 0x0000000b, 0);
6113 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE
);
6114 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %Id\n", res
);
6115 res
= SendMessageA(hwnd
, 0x3B, 0x0000000f, 0);
6116 ok_sequence(WmInitEndSession_2
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE
);
6117 ok(res
== 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %Id\n", res
);
6120 res
= SendMessageA(hwnd
, 0x3B, 0x80000008, 0);
6121 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE
);
6122 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %Id\n", res
);
6123 res
= SendMessageA(hwnd
, 0x3B, 0x00000008, 0);
6124 ok_sequence(WmInitEndSession_4
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE
);
6125 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %Id\n", res
);
6127 res
= SendMessageA(hwnd
, 0x3B, 0x80000004, 0);
6128 ok_sequence(WmInitEndSession_3
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE
);
6129 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %Id\n", res
);
6131 res
= SendMessageA(hwnd
, 0x3B, 0x80000001, 0);
6132 ok_sequence(WmInitEndSession_5
, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE
);
6133 ok(res
== 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %Id\n", res
);
6136 DestroyWindow(hwnd
);
6140 static const struct message WmFrameChanged
[] = {
6141 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
, 0 },
6142 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0xf },
6143 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
6144 |SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0xf },
6145 { WM_GETTEXT
, sent
|optional
},
6146 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
6147 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
6151 static const struct message WmFrameChanged_move
[] = {
6152 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
, 0 },
6153 { WM_NCCALCSIZE
, sent
|wparam
|lparam
, 1, 0x3 },
6154 { WM_WINDOWPOSCHANGED
, sent
|wparam
|lparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOREDRAW
6155 |SWP_NOSIZE
|SWP_NOCLIENTSIZE
, 0x3 },
6156 { WM_MOVE
, sent
|defwinproc
, 0 },
6157 { WM_GETTEXT
, sent
|optional
},
6158 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
6159 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
6163 static void test_setwindowpos(void)
6170 const INT winX
= 100;
6171 const INT winY
= 100;
6172 const INT sysX
= GetSystemMetrics(SM_CXMINTRACK
);
6174 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
6175 X
, Y
, winX
, winY
, 0,
6178 GetWindowRect(hwnd
, &rc
);
6179 expect(sysX
+ X
, rc
.right
);
6180 expect(winY
+ Y
, rc
.bottom
);
6184 res
= SetWindowPos(hwnd
, HWND_TOPMOST
, 50, 50, winX
, winY
, 0);
6185 ok_sequence(WmZOrder
, "Z-Order", TRUE
);
6186 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id\n", res
);
6188 GetWindowRect(hwnd
, &rc
);
6189 expect(sysX
+ X
, rc
.right
);
6190 expect(winY
+ Y
, rc
.bottom
);
6192 res
= SetWindowPos( hwnd
, 0, 0, 0, 0, 0,
6193 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
6194 ok_sequence(WmFrameChanged
, "FrameChanged", FALSE
);
6195 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id.\n", res
);
6197 GetWindowRect(hwnd
, &rc
);
6198 expect(sysX
+ X
, rc
.right
);
6199 expect(winY
+ Y
, rc
.bottom
);
6201 res
= SetWindowPos( hwnd
, 0, 0, 0, 0, 0,
6202 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
6203 ok_sequence(WmFrameChanged_move
, "FrameChanged", FALSE
);
6204 ok(res
== TRUE
, "SetWindowPos expected TRUE, got %Id.\n", res
);
6206 GetWindowRect(hwnd
, &rc
);
6207 expect(sysX
, rc
.right
);
6208 expect(winY
, rc
.bottom
);
6210 DestroyWindow(hwnd
);
6213 static void invisible_parent_tests(void)
6215 HWND hparent
, hchild
;
6217 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
6218 100, 100, 200, 200, 0, 0, 0, NULL
);
6219 ok (hparent
!= 0, "Failed to create parent window\n");
6222 /* test showing child with hidden parent */
6224 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6225 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6226 ok (hchild
!= 0, "Failed to create child window\n");
6227 ok_sequence(WmCreateChildSeq
, "CreateWindow:child", FALSE
);
6229 ShowWindow( hchild
, SW_MINIMIZE
);
6230 ok_sequence(WmShowChildInvisibleParentSeq_1
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
6231 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6232 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6237 ShowWindow( hchild
, SW_MINIMIZE
);
6238 ok_sequence(WmShowChildInvisibleParentSeq_1r
, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE
);
6240 DestroyWindow(hchild
);
6241 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6242 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6245 ShowWindow( hchild
, SW_MAXIMIZE
);
6246 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
6247 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6248 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6253 ShowWindow( hchild
, SW_MAXIMIZE
);
6254 ok_sequence(WmShowChildInvisibleParentSeq_2r
, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE
);
6256 DestroyWindow(hchild
);
6257 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6258 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6261 ShowWindow( hchild
, SW_RESTORE
);
6262 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE
);
6263 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6264 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6266 DestroyWindow(hchild
);
6267 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6268 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6271 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
6272 ok_sequence(WmShowChildInvisibleParentSeq_3
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
6273 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6274 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6279 ShowWindow( hchild
, SW_SHOWMINIMIZED
);
6280 ok_sequence(WmShowChildInvisibleParentSeq_3r
, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE
);
6282 DestroyWindow(hchild
);
6283 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6284 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6287 /* same as ShowWindow( hchild, SW_MAXIMIZE ); */
6288 ShowWindow( hchild
, SW_SHOWMAXIMIZED
);
6289 ok_sequence(WmShowChildInvisibleParentSeq_2
, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE
);
6290 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6291 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6293 DestroyWindow(hchild
);
6294 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6295 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6298 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
6299 ok_sequence(WmShowChildInvisibleParentSeq_4
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
6300 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6301 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6306 ShowWindow( hchild
, SW_SHOWMINNOACTIVE
);
6307 ok_sequence(WmShowChildInvisibleParentSeq_4r
, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE
);
6309 DestroyWindow(hchild
);
6310 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6311 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6314 /* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */
6315 ShowWindow( hchild
, SW_FORCEMINIMIZE
);
6316 ok_sequence(WmEmptySeq
, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE
);
6318 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
6320 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6322 DestroyWindow(hchild
);
6323 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6324 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6327 ShowWindow( hchild
, SW_SHOWNA
);
6328 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
6329 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6330 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6335 ShowWindow( hchild
, SW_SHOWNA
);
6336 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE
);
6338 DestroyWindow(hchild
);
6339 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
,
6340 0, 0, 10, 10, hparent
, 0, 0, NULL
);
6343 ShowWindow( hchild
, SW_SHOW
);
6344 ok_sequence(WmShowChildInvisibleParentSeq_5
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
6345 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6346 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6351 ShowWindow( hchild
, SW_SHOW
);
6352 ok_sequence(WmEmptySeq
, "ShowWindow(SW_SHOW) child with invisible parent", FALSE
);
6354 ShowWindow( hchild
, SW_HIDE
);
6355 ok_sequence(WmHideChildInvisibleParentSeq
, "ShowWindow:hide child with invisible parent", FALSE
);
6356 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should be not set\n");
6357 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6359 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6360 ok_sequence(WmShowChildInvisibleParentSeq_6
, "SetWindowPos:show child with invisible parent", FALSE
);
6361 ok(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
6362 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6364 SetWindowPos(hchild
, 0,0,0,0,0, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6365 ok_sequence(WmHideChildInvisibleParentSeq_2
, "SetWindowPos:hide child with invisible parent", FALSE
);
6366 ok(!(GetWindowLongA(hchild
, GWL_STYLE
) & WS_VISIBLE
), "WS_VISIBLE should not be set\n");
6367 ok(!IsWindowVisible(hchild
), "IsWindowVisible() should return FALSE\n");
6369 SetWindowPos(hchild
, 0,0,0,0,0, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
6371 DestroyWindow(hchild
);
6372 ok_sequence(WmDestroyInvisibleChildSeq
, "DestroyInvisibleChildSeq", FALSE
);
6374 DestroyWindow(hparent
);
6378 /****************** button message test *************************/
6379 #define ID_BUTTON 0x000e
6381 static const struct message WmSetFocusButtonSeq
[] =
6383 { HCBT_SETFOCUS
, hook
},
6384 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6385 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6386 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6387 { WM_SETFOCUS
, sent
|wparam
, 0 },
6388 { WM_CTLCOLORBTN
, sent
|parent
},
6389 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6390 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6393 static const struct message WmKillFocusButtonSeq
[] =
6395 { HCBT_SETFOCUS
, hook
},
6396 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6397 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6398 { WM_CTLCOLORBTN
, sent
|parent
},
6399 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6400 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6401 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6402 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6404 { WM_CTLCOLORBTN
, sent
|parent
},
6407 static const struct message WmSetFocusStaticSeq
[] =
6409 { HCBT_SETFOCUS
, hook
},
6410 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6411 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6412 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6413 { WM_SETFOCUS
, sent
|wparam
, 0 },
6414 { WM_CTLCOLORSTATIC
, sent
|parent
},
6415 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6416 { WM_COMMAND
, sent
|wparam
|parent
|optional
, MAKEWPARAM(ID_BUTTON
, BN_CLICKED
) }, /* radio button */
6417 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6420 static const struct message WmKillFocusStaticSeq
[] =
6422 { HCBT_SETFOCUS
, hook
},
6423 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6424 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6425 { WM_CTLCOLORSTATIC
, sent
|parent
},
6426 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6427 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6428 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6429 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6431 { WM_CTLCOLORSTATIC
, sent
|parent
},
6434 static const struct message WmSetFocusOwnerdrawSeq
[] =
6436 { HCBT_SETFOCUS
, hook
},
6437 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
6438 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6439 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6440 { WM_SETFOCUS
, sent
|wparam
, 0 },
6441 { WM_CTLCOLORBTN
, sent
|parent
},
6442 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x001040e4 },
6443 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_SETFOCUS
) },
6444 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6447 static const struct message WmKillFocusOwnerdrawSeq
[] =
6449 { HCBT_SETFOCUS
, hook
},
6450 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6451 { WM_KILLFOCUS
, sent
|wparam
, 0 },
6452 { WM_CTLCOLORBTN
, sent
|parent
},
6453 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000040e4 },
6454 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_KILLFOCUS
) },
6455 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
6456 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
6457 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6459 { WM_CTLCOLORBTN
, sent
|parent
},
6460 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6463 static const struct message WmLButtonDownSeq
[] =
6465 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6466 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6467 { HCBT_SETFOCUS
, hook
},
6468 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6469 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6470 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6471 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6472 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6473 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6474 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6475 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6478 static const struct message WmLButtonDownStaticSeq
[] =
6480 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
6481 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6482 { HCBT_SETFOCUS
, hook
},
6483 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
6484 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
6485 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
6486 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
6487 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6488 { BM_SETSTATE
, sent
|wparam
|defwinproc
, TRUE
},
6489 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6490 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6493 static const struct message WmLButtonUpSeq
[] =
6495 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6496 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6497 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6498 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6499 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6500 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6503 static const struct message WmLButtonUpStaticSeq
[] =
6505 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6506 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6507 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6508 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6509 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6510 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6513 static const struct message WmLButtonUpAutoSeq
[] =
6515 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6516 { BM_SETSTATE
, sent
|wparam
|defwinproc
, FALSE
},
6517 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6518 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6519 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
6520 { BM_SETCHECK
, sent
|defwinproc
},
6521 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
, 0, 0 }, /* Sent here on Win7. */
6522 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6523 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6524 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
, 0, 0 }, /* Sent here on Win8+. */
6525 { WM_CAPTURECHANGED
, sent
|wparam
|defwinproc
, 0 },
6528 static const struct message WmLButtonUpBrokenSeq
[] =
6530 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
6533 static const struct message WmSetFontButtonSeq
[] =
6535 { WM_SETFONT
, sent
},
6537 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6538 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6541 static const struct message WmSetFontOwnerdrawSeq
[] =
6543 { WM_SETFONT
, sent
},
6545 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6546 { WM_CTLCOLORBTN
, sent
|defwinproc
},
6547 { WM_CTLCOLORBTN
, sent
|defwinproc
|wine_only
}, /* FIXME: Wine sends it twice for BS_OWNERDRAW */
6550 static const struct message WmSetFontStaticSeq
[] =
6552 { WM_SETFONT
, sent
},
6554 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
6555 { WM_CTLCOLORSTATIC
, sent
|defwinproc
},
6558 static const struct message WmSetTextButtonSeq
[] =
6560 { WM_SETTEXT
, sent
},
6561 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6562 { WM_CTLCOLORBTN
, sent
|parent
},
6563 { WM_CTLCOLORBTN
, sent
|parent
},
6564 { WM_COMMAND
, sent
|parent
|optional
},
6565 { WM_DRAWITEM
, sent
|parent
|optional
},
6568 static const struct message WmSetTextStaticSeq
[] =
6570 { WM_SETTEXT
, sent
},
6571 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6572 { WM_CTLCOLORSTATIC
, sent
|parent
},
6573 { WM_CTLCOLORSTATIC
, sent
|parent
},
6576 static const struct message WmSetTextGroupSeq
[] =
6578 { WM_SETTEXT
, sent
},
6579 { WM_CTLCOLORSTATIC
, sent
|parent
},
6580 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6581 { WM_CTLCOLORSTATIC
, sent
|parent
|msg_todo
}, /* FIXME: Missing in Wine */
6582 { WM_CTLCOLORSTATIC
, sent
|parent
|msg_todo
}, /* FIXME: Missing in Wine */
6585 static const struct message WmSetTextInvisibleSeq
[] =
6587 { WM_SETTEXT
, sent
},
6588 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6591 static const struct message WmSetStyleButtonSeq
[] =
6593 { BM_SETSTYLE
, sent
},
6594 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6595 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6597 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6598 { WM_CTLCOLORBTN
, sent
|parent
},
6601 static const struct message WmSetStyleStaticSeq
[] =
6603 { BM_SETSTYLE
, sent
},
6604 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6605 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6607 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6608 { WM_CTLCOLORSTATIC
, sent
|parent
},
6611 static const struct message WmSetStyleUserSeq
[] =
6613 { BM_SETSTYLE
, sent
},
6614 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6615 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6617 { WM_NCPAINT
, sent
|defwinproc
|wine_only
}, /* FIXME: Wine sends it */
6618 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6619 { WM_CTLCOLORBTN
, sent
|parent
},
6620 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_PAINT
) },
6623 static const struct message WmSetStyleOwnerdrawSeq
[] =
6625 { BM_SETSTYLE
, sent
},
6626 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6627 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6629 { WM_ERASEBKGND
, sent
|defwinproc
|optional
}, /* Win9x doesn't send it */
6630 { WM_CTLCOLORBTN
, sent
|parent
},
6631 { WM_CTLCOLORBTN
, sent
|parent
|optional
}, /* Win9x doesn't send it */
6632 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000010e4 },
6635 static const struct message WmSetStateButtonSeq
[] =
6637 { BM_SETSTATE
, sent
},
6638 { WM_CTLCOLORBTN
, sent
|parent
},
6639 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6640 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6643 static const struct message WmSetStateStaticSeq
[] =
6645 { BM_SETSTATE
, sent
},
6646 { WM_CTLCOLORSTATIC
, sent
|parent
},
6647 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6648 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6651 static const struct message WmSetStateUserSeq
[] =
6653 { BM_SETSTATE
, sent
},
6654 { WM_CTLCOLORBTN
, sent
|parent
},
6655 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_HILITE
) },
6656 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6657 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6660 static const struct message WmSetStateOwnerdrawSeq
[] =
6662 { BM_SETSTATE
, sent
},
6663 { WM_CTLCOLORBTN
, sent
|parent
},
6664 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000120e4 },
6665 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6666 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6669 static const struct message WmClearStateButtonSeq
[] =
6671 { BM_SETSTATE
, sent
},
6672 { WM_CTLCOLORBTN
, sent
|parent
},
6673 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_BUTTON
, BN_UNHILITE
) },
6674 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6675 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6678 static const struct message WmDisableButtonSeq
[] =
6680 { WM_LBUTTONDOWN
, sent
},
6681 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6682 { BM_SETSTATE
, sent
|defwinproc
},
6683 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6684 { WM_CTLCOLORBTN
, sent
|optional
},
6685 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6686 { WM_LBUTTONUP
, sent
},
6687 { BM_SETSTATE
, sent
|defwinproc
},
6688 { WM_CTLCOLORBTN
, sent
|defwinproc
|optional
},
6689 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6690 { BM_SETCHECK
, sent
|defwinproc
|optional
},
6691 { WM_CTLCOLORBTN
, sent
|optional
},
6692 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6693 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
6694 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
6695 { WM_CAPTURECHANGED
, sent
|defwinproc
},
6696 { WM_COMMAND
, sent
},
6699 static const struct message WmClearStateOwnerdrawSeq
[] =
6701 { BM_SETSTATE
, sent
},
6702 { WM_CTLCOLORBTN
, sent
|parent
},
6703 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_BUTTON
, 0x000020e4 },
6704 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
6705 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6708 static const struct message WmSetCheckIgnoredSeq
[] =
6710 { BM_SETCHECK
, sent
},
6711 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6714 static const struct message WmSetCheckStaticSeq
[] =
6716 { BM_SETCHECK
, sent
},
6717 { WM_CTLCOLORSTATIC
, sent
|parent
},
6718 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
6719 { WM_APP
, sent
|wparam
|lparam
, 0, 0 },
6723 static WNDPROC old_button_proc
;
6725 static LRESULT CALLBACK
button_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
6727 static LONG defwndproc_counter
= 0;
6729 struct recvd_message msg
;
6731 if (ignore_message( message
)) return 0;
6739 ok(GetCapture() == hwnd
, "GetCapture() = %p\n", GetCapture());
6741 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6747 MSG
*msg
= (MSG
*)lParam
;
6748 lParam
= MAKELPARAM(msg
->message
, msg
->wParam
);
6750 wParam
= (ULONG_PTR
)GetMenu(hwnd
);
6755 lParam
= (ULONG_PTR
)GetMenu(hwnd
);
6760 msg
.message
= message
;
6761 msg
.flags
= sent
|wparam
|lparam
;
6762 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
6763 msg
.wParam
= wParam
;
6764 msg
.lParam
= lParam
;
6765 msg
.descr
= "button";
6769 defwndproc_counter
++;
6770 ret
= CallWindowProcA(old_button_proc
, hwnd
, message
, wParam
, lParam
);
6771 defwndproc_counter
--;
6776 static void subclass_button(void)
6781 ret
= GetClassInfoA(0, "button", &cls
);
6782 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
6784 old_button_proc
= cls
.lpfnWndProc
;
6786 cls
.hInstance
= GetModuleHandleA(NULL
);
6787 cls
.lpfnWndProc
= button_hook_proc
;
6788 cls
.lpszClassName
= "my_button_class";
6789 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
6790 register_class(&cls
);
6793 static void test_button_messages(void)
6799 const struct message
*setfocus
;
6800 const struct message
*killfocus
;
6801 const struct message
*setstyle
;
6802 const struct message
*setstate
;
6803 const struct message
*clearstate
;
6804 const struct message
*setcheck
;
6805 const struct message
*lbuttondown
;
6806 const struct message
*lbuttonup
;
6807 const struct message
*setfont
;
6808 const struct message
*settext
;
6810 { BS_PUSHBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6811 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6812 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6813 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6814 WmSetTextButtonSeq
},
6815 { BS_DEFPUSHBUTTON
, DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
,
6816 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleButtonSeq
,
6817 WmSetStateButtonSeq
, WmSetStateButtonSeq
, WmSetCheckIgnoredSeq
,
6818 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6819 WmSetTextButtonSeq
},
6820 { BS_CHECKBOX
, DLGC_BUTTON
,
6821 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6822 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6823 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6824 WmSetTextStaticSeq
},
6825 { BS_AUTOCHECKBOX
, DLGC_BUTTON
,
6826 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6827 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6828 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6829 WmSetTextStaticSeq
},
6830 { BS_RADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6831 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6832 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6833 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6834 WmSetTextStaticSeq
},
6835 { BS_3STATE
, DLGC_BUTTON
,
6836 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6837 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6838 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6839 WmSetTextStaticSeq
},
6840 { BS_AUTO3STATE
, DLGC_BUTTON
,
6841 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6842 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6843 WmLButtonDownStaticSeq
, WmLButtonUpAutoSeq
, WmSetFontStaticSeq
,
6844 WmSetTextStaticSeq
},
6845 { BS_GROUPBOX
, DLGC_STATIC
,
6846 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6847 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckIgnoredSeq
,
6848 WmLButtonDownStaticSeq
, WmLButtonUpStaticSeq
, WmSetFontStaticSeq
,
6849 WmSetTextGroupSeq
},
6850 { BS_USERBUTTON
, DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
,
6851 WmSetFocusButtonSeq
, WmKillFocusButtonSeq
, WmSetStyleUserSeq
,
6852 WmSetStateUserSeq
, WmClearStateButtonSeq
, WmSetCheckIgnoredSeq
,
6853 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontButtonSeq
,
6854 WmSetTextButtonSeq
},
6855 { BS_AUTORADIOBUTTON
, DLGC_BUTTON
| DLGC_RADIOBUTTON
,
6856 WmSetFocusStaticSeq
, WmKillFocusStaticSeq
, WmSetStyleStaticSeq
,
6857 WmSetStateStaticSeq
, WmSetStateStaticSeq
, WmSetCheckStaticSeq
,
6858 NULL
/* avoid infinite loop */, WmLButtonUpBrokenSeq
, WmSetFontStaticSeq
,
6859 WmSetTextStaticSeq
},
6860 { BS_OWNERDRAW
, DLGC_BUTTON
,
6861 WmSetFocusOwnerdrawSeq
, WmKillFocusOwnerdrawSeq
, WmSetStyleOwnerdrawSeq
,
6862 WmSetStateOwnerdrawSeq
, WmClearStateOwnerdrawSeq
, WmSetCheckIgnoredSeq
,
6863 WmLButtonDownSeq
, WmLButtonUpSeq
, WmSetFontOwnerdrawSeq
,
6864 WmSetTextButtonSeq
},
6866 LOGFONTA logfont
= { 0 };
6867 HFONT zfont
, hfont2
;
6872 /* selection with VK_SPACE should capture button window */
6873 hwnd
= CreateWindowExA(0, "button", "test", BS_CHECKBOX
| WS_VISIBLE
| WS_POPUP
,
6874 0, 0, 50, 14, 0, 0, 0, NULL
);
6875 ok(hwnd
!= 0, "Failed to create button window\n");
6878 SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
6879 ok(GetCapture() == hwnd
, "Should be captured on VK_SPACE WM_KEYDOWN\n");
6880 SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
6881 DestroyWindow(hwnd
);
6885 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
6886 100, 100, 200, 200, 0, 0, 0, NULL
);
6887 ok(parent
!= 0, "Failed to create parent window\n");
6889 memset(&logfont
, 0, sizeof(logfont
));
6890 logfont
.lfHeight
= -12;
6891 logfont
.lfWeight
= FW_NORMAL
;
6892 strcpy(logfont
.lfFaceName
, "Tahoma");
6894 hfont2
= CreateFontIndirectA(&logfont
);
6895 ok(hfont2
!= NULL
, "Failed to create Tahoma font\n");
6897 for (i
= 0; i
< ARRAY_SIZE(button
); i
++)
6905 if (winetest_debug
> 1) trace("button style %08lx\n", button
[i
].style
);
6907 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_CHILD
| BS_NOTIFY
,
6908 0, 0, 50, 14, parent
, (HMENU
)ID_BUTTON
, 0, NULL
);
6909 ok(hwnd
!= 0, "Failed to create button window\n");
6911 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6912 style
&= ~(WS_CHILD
| BS_NOTIFY
);
6913 /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
6914 if (button
[i
].style
== BS_USERBUTTON
)
6915 ok(style
== BS_PUSHBUTTON
, "expected style BS_PUSHBUTTON got %lx\n", style
);
6917 ok(style
== button
[i
].style
, "expected style %lx got %lx\n", button
[i
].style
, style
);
6919 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
6920 ok(dlg_code
== button
[i
].dlg_code
, "%u: wrong dlg_code %08lx\n", i
, dlg_code
);
6922 ShowWindow(hwnd
, SW_SHOW
);
6929 log_all_parent_messages
++;
6931 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6933 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6934 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6935 ok_sequence(button
[i
].setfocus
, "SetFocus(hwnd) on a button", FALSE
);
6938 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6939 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6940 ok_sequence(button
[i
].killfocus
, "SetFocus(0) on a button", FALSE
);
6942 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
6944 SendMessageA(hwnd
, BM_SETSTYLE
, button
[i
].style
| BS_BOTTOM
, TRUE
);
6945 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6946 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6947 ok_sequence(button
[i
].setstyle
, "BM_SETSTYLE on a button", FALSE
);
6949 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6950 style
&= ~(WS_VISIBLE
| WS_CHILD
| BS_NOTIFY
);
6951 /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
6952 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6954 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6955 ok(state
== 0, "expected state 0, got %04lx\n", state
);
6959 SendMessageA(hwnd
, BM_SETSTATE
, TRUE
, 0);
6960 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6961 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6962 ok_sequence(button
[i
].setstate
, "BM_SETSTATE/TRUE on a button", FALSE
);
6964 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6965 ok(state
== 0x0004, "expected state 0x0004, got %04lx\n", state
);
6967 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6968 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6969 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6973 SendMessageA(hwnd
, BM_SETSTATE
, FALSE
, 0);
6974 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6975 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6976 ok_sequence(button
[i
].clearstate
, "BM_SETSTATE/FALSE on a button", FALSE
);
6978 state
= SendMessageA(hwnd
, BM_GETSTATE
, 0, 0);
6979 ok(state
== 0, "expected state 0, got %04lx\n", state
);
6981 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6982 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
6983 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
6985 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6986 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04lx\n", state
);
6990 SendMessageA(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
6991 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
6992 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
6993 ok_sequence(WmSetCheckIgnoredSeq
, "BM_SETCHECK on a button", FALSE
);
6995 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
6996 ok(state
== BST_UNCHECKED
, "expected BST_UNCHECKED, got %04lx\n", state
);
6998 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
6999 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
7000 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
7004 SendMessageA(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
7005 SendMessageA(hwnd
, WM_APP
, 0, 0); /* place a separator mark here */
7006 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7007 ok_sequence(button
[i
].setcheck
, "BM_SETCHECK on a button", FALSE
);
7009 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 1");
7010 sprintf(desc
, "button[%i]: WM_SETTEXT on a visible button", i
);
7011 ok_sequence(button
[i
].settext
, desc
, FALSE
);
7013 ShowWindow(hwnd
, SW_HIDE
);
7017 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 2");
7018 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
7019 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
7021 ShowWindow(hwnd
, SW_SHOW
);
7022 ShowWindow(parent
, SW_HIDE
);
7026 SendMessageA(hwnd
, WM_SETTEXT
, 0, (LPARAM
)"Text 3");
7027 sprintf(desc
, "button[%i]: WM_SETTEXT on an invisible button", i
);
7028 ok_sequence(WmSetTextInvisibleSeq
, desc
, FALSE
);
7030 ShowWindow(parent
, SW_SHOW
);
7033 state
= SendMessageA(hwnd
, BM_GETCHECK
, 0, 0);
7034 if (button
[i
].style
== BS_PUSHBUTTON
||
7035 button
[i
].style
== BS_DEFPUSHBUTTON
||
7036 button
[i
].style
== BS_GROUPBOX
||
7037 button
[i
].style
== BS_USERBUTTON
||
7038 button
[i
].style
== BS_OWNERDRAW
)
7039 ok(state
== BST_UNCHECKED
, "expected check 0, got %04lx\n", state
);
7041 ok(state
== BST_CHECKED
, "expected check 1, got %04lx\n", state
);
7043 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
7044 style
&= ~(WS_CHILD
| BS_NOTIFY
| WS_VISIBLE
);
7045 if (button
[i
].style
== BS_RADIOBUTTON
||
7046 button
[i
].style
== BS_AUTORADIOBUTTON
)
7047 ok(style
== (button
[i
].style
| WS_TABSTOP
), "expected style %04lx | WS_TABSTOP got %04lx\n", button
[i
].style
, style
);
7049 ok(style
== button
[i
].style
, "expected style %04lx got %04lx\n", button
[i
].style
, style
);
7051 log_all_parent_messages
--;
7053 DestroyWindow(hwnd
);
7055 hwnd
= CreateWindowExA(0, "my_button_class", "test", button
[i
].style
| WS_POPUP
| WS_VISIBLE
,
7056 0, 0, 50, 14, 0, 0, 0, NULL
);
7057 ok(hwnd
!= 0, "Failed to create button window\n");
7059 SetForegroundWindow(hwnd
);
7062 SetActiveWindow(hwnd
);
7066 if (button
[i
].lbuttondown
)
7068 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
7069 sprintf(desc
, "button[%i]: WM_LBUTTONDOWN on a button", i
);
7070 ok_sequence(button
[i
].lbuttondown
, desc
, FALSE
);
7073 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
7074 sprintf(desc
, "button[%i]: WM_LBUTTONUP on a button", i
);
7075 ok_sequence(button
[i
].lbuttonup
, desc
, FALSE
);
7078 zfont
= GetStockObject(DEFAULT_GUI_FONT
);
7079 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)zfont
, TRUE
);
7081 sprintf(desc
, "button[%i]: WM_SETFONT on a button", i
);
7082 ok_sequence(button
[i
].setfont
, desc
, FALSE
);
7084 /* Test that original font is not selected back after painting */
7085 hdc
= CreateCompatibleDC(0);
7087 prevfont
= SelectObject(hdc
, hfont2
);
7088 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
7089 SendMessageA(hwnd
, WM_PRINTCLIENT
, (WPARAM
)hdc
, 0);
7090 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i
);
7091 SelectObject(hdc
, prevfont
);
7093 prevfont
= SelectObject(hdc
, hfont2
);
7094 ok(prevfont
== GetStockObject(SYSTEM_FONT
), "Unexpected default font\n");
7095 SendMessageA(hwnd
, WM_PAINT
, (WPARAM
)hdc
, 0);
7096 ok(hfont2
!= GetCurrentObject(hdc
, OBJ_FONT
), "button[%u]: unexpected font selected after WM_PAINT\n", i
);
7097 SelectObject(hdc
, prevfont
);
7101 DestroyWindow(hwnd
);
7104 DeleteObject(hfont2
);
7105 DestroyWindow(parent
);
7107 /* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
7109 parent
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
7110 100, 100, 200, 200, 0, 0, 0, NULL
);
7111 ok (hwnd
!= 0, "Failed to create overlapped window\n");
7113 hwnd
= CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON
| WS_VISIBLE
| WS_CHILD
,
7114 0, 0, 50, 14, parent
, 0, 0, NULL
);
7116 EnableWindow(hwnd
, FALSE
);
7118 SendMessageA(hwnd
, WM_LBUTTONDOWN
, MK_LBUTTON
, 0);
7119 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
7120 ok_sequence(WmDisableButtonSeq
, "Mouseclick on a disabled button", FALSE
);
7122 DestroyWindow(hwnd
);
7123 DestroyWindow(parent
);
7126 static void test_button_bm_get_set_image(void)
7133 ICONINFO icon_info2x2
;
7139 DWORD default_style
= BS_PUSHBUTTON
| WS_TABSTOP
| WS_POPUP
| WS_VISIBLE
;
7143 hbmp1x1
= CreateCompatibleBitmap(hdc
, 1, 1);
7144 hbmp2x2
= CreateCompatibleBitmap(hdc
, 2, 2);
7145 ZeroMemory(&bm
, sizeof(bm
));
7146 ok(GetObjectW(hbmp1x1
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7147 ok(bm
.bmWidth
== 1 && bm
.bmHeight
== 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7148 bm
.bmWidth
, bm
.bmHeight
);
7149 ZeroMemory(&bm
, sizeof(bm
));
7150 ok(GetObjectW(hbmp2x2
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7151 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7152 bm
.bmWidth
, bm
.bmHeight
);
7154 hmask2x2
= CreateCompatibleBitmap(hdc
, 2, 2);
7155 ZeroMemory(&icon_info2x2
, sizeof(icon_info2x2
));
7156 icon_info2x2
.fIcon
= TRUE
;
7157 icon_info2x2
.hbmMask
= hmask2x2
;
7158 icon_info2x2
.hbmColor
= hbmp2x2
;
7159 hicon2x2
= CreateIconIndirect(&icon_info2x2
);
7161 ZeroMemory(&icon_info
, sizeof(icon_info
));
7162 ok(GetIconInfo(hicon2x2
, &icon_info
), "Expect GetIconInfo() success\n");
7163 ZeroMemory(&bm
, sizeof(bm
));
7164 ok(GetObjectW(icon_info
.hbmColor
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7165 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7166 bm
.bmWidth
, bm
.bmHeight
);
7167 DeleteObject(icon_info
.hbmColor
);
7168 DeleteObject(icon_info
.hbmMask
);
7170 /* Set bitmap with BS_BITMAP */
7171 hwnd
= CreateWindowA("Button", "test", default_style
| BS_BITMAP
, 0, 0, 100, 100, 0, 0, 0, 0);
7172 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7173 SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7174 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7175 ok(hbmp
!= 0, "Expect hbmp not 0\n");
7176 ZeroMemory(&bm
, sizeof(bm
));
7177 ok(GetObjectW(hbmp
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7178 ok(bm
.bmWidth
== 1 && bm
.bmHeight
== 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
7179 bm
.bmWidth
, bm
.bmHeight
);
7180 DestroyWindow(hwnd
);
7182 /* Set bitmap without BS_BITMAP */
7183 hwnd
= CreateWindowA("Button", "test", default_style
, 0, 0, 100, 100, 0, 0, 0, 0);
7184 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7185 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7186 ok(ret
== 0, "Expect ret to be 0\n");
7187 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7188 ok(hbmp
== NULL
, "Expect hbmp to be NULL\n");
7189 DestroyWindow(hwnd
);
7191 /* Set icon with BS_ICON */
7192 hwnd
= CreateWindowA("Button", "test", default_style
| BS_ICON
, 0, 0, 100, 100, 0, 0, 0, 0);
7193 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7194 SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7195 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7196 ok(hicon
!= NULL
, "Expect hicon not NULL\n");
7197 ZeroMemory(&icon_info
, sizeof(icon_info
));
7198 ok(GetIconInfo(hicon
, &icon_info
), "Expect GetIconInfo() success\n");
7199 ZeroMemory(&bm
, sizeof(bm
));
7200 ok(GetObjectW(icon_info
.hbmColor
, sizeof(bm
), &bm
), "Expect GetObjectW() success\n");
7201 ok(bm
.bmWidth
== 2 && bm
.bmHeight
== 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
7202 bm
.bmWidth
, bm
.bmHeight
);
7203 DeleteObject(icon_info
.hbmColor
);
7204 DeleteObject(icon_info
.hbmMask
);
7205 DestroyWindow(hwnd
);
7207 /* Set icon without BS_ICON */
7208 hwnd
= CreateWindowA("Button", "test", default_style
, 0, 0, 100, 100, 0, 0, 0, 0);
7209 ok(hwnd
!= NULL
, "Expect hwnd not NULL\n");
7210 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7211 ok(ret
== 0, "Expect ret to be 0\n");
7212 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7213 ok(hicon
== NULL
, "Expect hicon to be NULL\n");
7214 DestroyWindow(hwnd
);
7216 /* Set icon with BS_BITMAP */
7217 hwnd
= CreateWindowA("Button", "test", default_style
| BS_BITMAP
, 0, 0, 100, 100, 0, 0, 0, 0);
7218 ok(hwnd
!= NULL
, "Expect hwnd to be not NULL\n");
7219 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_ICON
, (LPARAM
)hicon2x2
);
7220 ok(ret
== 0, "Expect ret to be 0\n");
7221 hicon
= (HICON
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_ICON
, 0);
7222 ok(hicon
== NULL
, "Expect hicon to be NULL\n");
7223 DestroyWindow(hwnd
);
7225 /* Set bitmap with BS_ICON */
7226 hwnd
= CreateWindowA("Button", "test", default_style
| BS_ICON
, 0, 0, 100, 100, 0, 0, 0, 0);
7227 ok(hwnd
!= NULL
, "Expect hwnd to be not NULL\n");
7228 ret
= SendMessageA(hwnd
, BM_SETIMAGE
, (WPARAM
)IMAGE_BITMAP
, (LPARAM
)hbmp1x1
);
7229 ok(ret
== 0, "Expect ret to be 0\n");
7230 hbmp
= (HBITMAP
)SendMessageA(hwnd
, BM_GETIMAGE
, (WPARAM
)IMAGE_BITMAP
, 0);
7231 ok(hbmp
== NULL
, "Expect hbmp to be NULL\n");
7232 DestroyWindow(hwnd
);
7234 DestroyIcon(hicon2x2
);
7235 DeleteObject(hmask2x2
);
7236 DeleteObject(hbmp2x2
);
7237 DeleteObject(hbmp1x1
);
7241 #define ID_RADIO1 501
7242 #define ID_RADIO2 502
7243 #define ID_RADIO3 503
7246 static const struct message auto_radio_button_BM_CLICK
[] =
7248 { BM_CLICK
, sent
|wparam
|lparam
, 0, 0 },
7249 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7250 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
7251 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
7252 { WM_CTLCOLORSTATIC
, sent
|parent
},
7253 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7254 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7255 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
7256 { WM_CTLCOLORSTATIC
, sent
|parent
},
7257 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7258 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
7259 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO2
},
7260 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
7261 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO1
},
7262 { WM_CTLCOLORSTATIC
, sent
|parent
},
7263 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7264 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
7265 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, 0, ID_RADIO3
},
7266 { WM_CTLCOLORSTATIC
, sent
|parent
},
7267 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7268 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
7269 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
7270 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7271 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO2
, BN_CLICKED
) },
7272 { WM_NCHITTEST
, sent
|optional
, 0, 0 },
7273 { WM_SETCURSOR
, sent
|optional
, 0, 0 },
7274 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 },
7278 static const struct message auto_radio_button_VK_UP_child
[] =
7280 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_UP
, 0 },
7281 { WM_KEYUP
, sent
|wparam
|lparam
, VK_UP
, 0 },
7285 static const struct message auto_radio_button_VK_UP_parent
[] =
7287 { WM_KEYDOWN
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
7288 { WM_KEYUP
, sent
|wparam
|lparam
|parent
, VK_UP
, 0 },
7292 static const struct message auto_radio_button_VK_UP_dialog
[] =
7294 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7296 /* optional trailer seen on some windows setups */
7297 { WM_CHANGEUISTATE
, sent
|optional
},
7298 { WM_UPDATEUISTATE
, sent
|optional
},
7299 { WM_UPDATEUISTATE
, sent
|optional
},
7300 { WM_UPDATEUISTATE
, sent
|optional
},
7301 { WM_UPDATEUISTATE
, sent
|optional
},
7302 { WM_UPDATEUISTATE
, sent
|optional
},
7303 { WM_UPDATEUISTATE
, sent
|optional
},
7304 { WM_UPDATEUISTATE
, sent
|optional
},
7305 { WM_UPDATEUISTATE
, sent
|optional
},
7306 { WM_UPDATEUISTATE
, sent
|optional
},
7307 { WM_UPDATEUISTATE
, sent
|optional
},
7308 { WM_UPDATEUISTATE
, sent
|optional
},
7309 { WM_UPDATEUISTATE
, sent
|optional
},
7310 { WM_UPDATEUISTATE
, sent
|optional
},
7311 { WM_UPDATEUISTATE
, sent
|optional
},
7312 { WM_UPDATEUISTATE
, sent
|optional
},
7313 { WM_UPDATEUISTATE
, sent
|optional
},
7314 { WM_UPDATEUISTATE
, sent
|optional
},
7315 { WM_UPDATEUISTATE
, sent
|optional
},
7316 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7317 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7318 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7319 { WM_UPDATEUISTATE
, sent
|optional
},
7320 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7321 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7322 { WM_UPDATEUISTATE
, sent
|optional
},
7323 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
7324 { WM_CTLCOLORBTN
, sent
|parent
|optional
},
7325 { WM_UPDATEUISTATE
, sent
|optional
},
7326 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7327 { WM_CTLCOLORSTATIC
, sent
|parent
|optional
},
7331 static const struct message auto_radio_button_VK_DOWN_dialog
[] =
7333 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7334 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
7335 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7336 { HCBT_SETFOCUS
, hook
},
7337 { WM_KILLFOCUS
, sent
, 0, 0 },
7338 { WM_CTLCOLORSTATIC
, sent
|parent
},
7339 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO3
, BN_KILLFOCUS
) },
7340 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
7341 { WM_SETFOCUS
, sent
, 0, 0 },
7342 { WM_CTLCOLORSTATIC
, sent
|parent
},
7343 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_SETFOCUS
) },
7344 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
7345 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7346 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7347 { DM_GETDEFID
, sent
|parent
, 0, 0 },
7348 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7349 { BM_CLICK
, sent
|wparam
|lparam
, 1, 0 },
7350 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7351 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
7352 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
7353 { WM_CTLCOLORSTATIC
, sent
|parent
},
7354 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7355 { WM_LBUTTONUP
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7356 { BM_SETSTATE
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO1
},
7357 { WM_CTLCOLORSTATIC
, sent
|parent
},
7358 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7359 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO1
, 0 },
7360 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_CHECKED
, ID_RADIO1
},
7361 { WM_CTLCOLORSTATIC
, sent
|parent
},
7362 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7363 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO3
, 0 },
7364 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO3
},
7365 { WM_CTLCOLORSTATIC
, sent
|parent
},
7366 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7367 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_TEXT
, 0 },
7368 { WM_GETDLGCODE
, sent
|wparam
|lparam
|defwinproc
, ID_RADIO2
, 0 },
7369 { BM_SETCHECK
, sent
|wparam
|lparam
|defwinproc
, BST_UNCHECKED
, ID_RADIO2
},
7370 { WM_CTLCOLORSTATIC
, sent
|parent
},
7371 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
7372 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
7373 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
7374 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_RADIO1
, BN_CLICKED
) },
7375 { WM_NCHITTEST
, sent
|optional
, 0, 0 },
7376 { WM_SETCURSOR
, sent
|optional
, 0, 0 },
7377 { WM_MOUSEMOVE
, sent
|optional
, 0, 0 },
7379 { WM_CTLCOLORSTATIC
, sent
|parent
},
7383 static const struct message auto_radio_button_VK_DOWN_radio3
[] =
7385 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7386 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO2
},
7387 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO3
},
7388 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7389 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, MAKELPARAM(WM_KEYDOWN
, VK_DOWN
) },
7390 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7391 { WM_GETDLGCODE
, sent
|wparam
|lparam
, ID_RADIO1
, 0 },
7392 { WM_GETDLGCODE
, sent
|wparam
|lparam
|parent
, 0, 0 },
7393 { WM_USER
, sent
|parent
, 0, 0 },
7394 { BM_GETCHECK
, sent
|wparam
|lparam
, 0, ID_RADIO1
},
7398 static const struct message auto_radio_button_VK_UP_radio1
[] =
7400 { WM_GETDLGCODE
, sent
|parent
, 0, 0 },
7404 static INT_PTR WINAPI
radio_test_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
7406 ParentMsgCheckProcA(hwnd
, msg
, wp
, lp
);
7410 static void test_autoradio_BM_CLICK(void)
7412 HWND parent
, radio1
, radio2
, radio3
;
7419 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc
, 0);
7420 ok(parent
!= 0, "failed to create parent window\n");
7422 radio1
= GetDlgItem(parent
, ID_RADIO1
);
7423 radio2
= GetDlgItem(parent
, ID_RADIO2
);
7424 radio3
= GetDlgItem(parent
, ID_RADIO3
);
7426 /* this avoids focus messages in the generated sequence */
7432 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7433 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7434 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7435 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7436 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7437 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7439 SendMessageA(radio1
, BM_SETCHECK
, BST_CHECKED
, 0);
7441 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7442 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7443 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7444 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7445 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7446 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7448 SendMessageA(radio2
, BM_SETCHECK
, BST_CHECKED
, 0);
7450 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7451 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7452 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7453 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7454 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7455 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7457 SendMessageA(radio3
, BM_SETCHECK
, BST_CHECKED
, 0);
7459 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7460 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7461 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7462 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7463 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7464 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7466 GetWindowRect(radio2
, &rc
);
7467 SetCursorPos(rc
.left
+1, rc
.top
+1);
7472 log_all_parent_messages
++;
7474 SendMessageA(radio2
, BM_CLICK
, 0, 0);
7475 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7476 ok_sequence(auto_radio_button_BM_CLICK
, "BM_CLICK on auto-radio button", FALSE
);
7478 log_all_parent_messages
--;
7480 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7481 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7482 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7483 ok(ret
== BST_CHECKED
, "got %08lx\n", ret
);
7484 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7485 ok(ret
== BST_UNCHECKED
, "got %08lx\n", ret
);
7487 DestroyWindow(parent
);
7490 #define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)
7491 static void test_radio_dbg(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
, int line
)
7495 ret
= SendMessageA(radio1
, BM_GETCHECK
, 0, 0);
7496 ok_(__FILE__
,line
)(ret
== state1
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7497 ret
= SendMessageA(radio2
, BM_GETCHECK
, 0, 0);
7498 ok_(__FILE__
,line
)(ret
== state2
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7499 ret
= SendMessageA(radio3
, BM_GETCHECK
, 0, 0);
7500 ok_(__FILE__
,line
)(ret
== state3
? BST_CHECKED
: BST_UNCHECKED
, "got %08lx\n", ret
);
7503 static void set_radio(HWND radio1
, int state1
, HWND radio2
, int state2
, HWND radio3
, int state3
)
7505 SendMessageA(radio1
, BM_SETCHECK
, state1
? BST_CHECKED
: BST_UNCHECKED
, 0);
7506 SendMessageA(radio2
, BM_SETCHECK
, state2
? BST_CHECKED
: BST_UNCHECKED
, 0);
7507 SendMessageA(radio3
, BM_SETCHECK
, state3
? BST_CHECKED
: BST_UNCHECKED
, 0);
7510 static void test_autoradio_kbd_move(void)
7512 HWND parent
, radio1
, radio2
, radio3
, hwnd
;
7519 parent
= CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc
, 0);
7520 ok(parent
!= 0, "failed to create parent window\n");
7522 radio1
= GetDlgItem(parent
, ID_RADIO1
);
7523 radio2
= GetDlgItem(parent
, ID_RADIO2
);
7524 radio3
= GetDlgItem(parent
, ID_RADIO3
);
7529 test_radio(radio1
, 0, radio2
, 0, radio3
, 0);
7530 set_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7531 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7538 log_all_parent_messages
++;
7540 SendMessageA(radio3
, WM_KEYDOWN
, VK_UP
, 0);
7541 SendMessageA(radio3
, WM_KEYUP
, VK_UP
, 0);
7542 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7543 ok_sequence(auto_radio_button_VK_UP_child
, "press/release VK_UP on auto-radio button", FALSE
);
7545 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7550 DefDlgProcA(parent
, WM_KEYDOWN
, VK_UP
, 0);
7551 DefDlgProcA(parent
, WM_KEYUP
, VK_UP
, 0);
7552 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7553 ok_sequence(auto_radio_button_VK_UP_parent
, "press/release VK_UP on dialog", FALSE
);
7555 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7558 GetWindowRect(radio3
, &rc
);
7564 msg
.message
= WM_KEYDOWN
;
7567 msg
.pt
.x
= rc
.left
+ 1;
7568 msg
.pt
.y
= rc
.top
+ 1;
7569 ret
= IsDialogMessageA(parent
, &msg
);
7570 ok(ret
, "IsDialogMessage should return TRUE\n");
7571 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7572 if (0) /* actual message sequence is different on every run in some Windows setups */
7573 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #1", FALSE
);
7574 /* what really matters is that nothing has changed */
7575 test_radio(radio1
, 1, radio2
, 1, radio3
, 1);
7577 set_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7578 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7583 ret
= IsDialogMessageA(parent
, &msg
);
7584 ok(ret
, "IsDialogMessage should return TRUE\n");
7585 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7586 if (0) /* actual message sequence is different on every run in some Windows setups */
7587 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #2", FALSE
);
7588 /* what really matters is that nothing has changed */
7589 test_radio(radio1
, 0, radio2
, 1, radio3
, 1);
7591 /* switch from radio3 ro radio1 */
7593 GetWindowRect(radio3
, &rc
);
7599 msg
.message
= WM_KEYDOWN
;
7600 msg
.wParam
= VK_DOWN
;
7602 msg
.pt
.x
= rc
.left
+ 1;
7603 msg
.pt
.y
= rc
.top
+ 1;
7604 ret
= IsDialogMessageA(parent
, &msg
);
7605 ok(ret
, "IsDialogMessage should return TRUE\n");
7606 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7607 ok_sequence(auto_radio_button_VK_DOWN_dialog
, "IsDialogMessage(VK_DOWN)", TRUE
);
7609 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7612 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7613 GetWindowRect(radio1
, &rc
);
7616 msg
.message
= WM_KEYDOWN
;
7617 msg
.wParam
= VK_DOWN
;
7619 msg
.pt
.x
= rc
.left
+ 1;
7620 msg
.pt
.y
= rc
.top
+ 1;
7621 ret
= IsDialogMessageA(parent
, &msg
);
7622 ok(ret
, "IsDialogMessage should return TRUE\n");
7623 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7624 ok_sequence(auto_radio_button_VK_DOWN_radio3
, "down to radio3", TRUE
);
7626 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7629 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7635 msg
.message
= WM_KEYDOWN
;
7638 msg
.pt
.x
= rc
.left
+ 1;
7639 msg
.pt
.y
= rc
.top
+ 1;
7640 ret
= IsDialogMessageA(parent
, &msg
);
7641 ok(ret
, "IsDialogMessage should return TRUE\n");
7642 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7643 ok_sequence(auto_radio_button_VK_UP_radio1
, "up to radio1", TRUE
);
7645 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7648 ok(hwnd
== radio1
, "focus should be on radio1, not on %p\n", hwnd
);
7654 msg
.message
= WM_KEYDOWN
;
7657 msg
.pt
.x
= rc
.left
+ 1;
7658 msg
.pt
.y
= rc
.top
+ 1;
7659 ret
= IsDialogMessageA(parent
, &msg
);
7660 ok(ret
, "IsDialogMessage should return TRUE\n");
7661 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
7662 if (0) /* actual message sequence is different on every run in some Windows setups */
7663 ok_sequence(auto_radio_button_VK_UP_dialog
, "IsDialogMessage(VK_UP) #3", FALSE
);
7664 /* what really matters is that nothing has changed */
7665 test_radio(radio1
, 1, radio2
, 0, radio3
, 0);
7667 log_all_parent_messages
--;
7669 DestroyWindow(parent
);
7672 /****************** static message test *************************/
7673 static const struct message WmSetFontStaticSeq2
[] =
7675 { WM_SETFONT
, sent
},
7676 { WM_PAINT
, sent
|defwinproc
|optional
},
7677 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
7678 { WM_CTLCOLORSTATIC
, sent
|defwinproc
|optional
},
7682 static WNDPROC old_static_proc
;
7684 static LRESULT CALLBACK
static_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7686 static LONG defwndproc_counter
= 0;
7688 struct recvd_message msg
;
7690 if (ignore_message( message
)) return 0;
7693 msg
.message
= message
;
7694 msg
.flags
= sent
|wparam
|lparam
;
7695 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7696 msg
.wParam
= wParam
;
7697 msg
.lParam
= lParam
;
7698 msg
.descr
= "static";
7701 defwndproc_counter
++;
7702 ret
= CallWindowProcA(old_static_proc
, hwnd
, message
, wParam
, lParam
);
7703 defwndproc_counter
--;
7708 static void subclass_static(void)
7713 ret
= GetClassInfoA(0, "static", &cls
);
7714 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
7716 old_static_proc
= cls
.lpfnWndProc
;
7718 cls
.hInstance
= GetModuleHandleA(NULL
);
7719 cls
.lpfnWndProc
= static_hook_proc
;
7720 cls
.lpszClassName
= "my_static_class";
7721 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
7722 register_class(&cls
);
7725 static void test_static_messages(void)
7727 /* FIXME: make as comprehensive as the button message test */
7732 const struct message
*setfont
;
7734 { SS_LEFT
, DLGC_STATIC
,
7735 WmSetFontStaticSeq2
}
7743 for (i
= 0; i
< ARRAY_SIZE(static_ctrl
); i
++)
7745 hwnd
= CreateWindowExA(0, "my_static_class", "test", static_ctrl
[i
].style
| WS_POPUP
,
7746 0, 0, 50, 14, 0, 0, 0, NULL
);
7747 ok(hwnd
!= 0, "Failed to create static window\n");
7749 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
7750 ok(dlg_code
== static_ctrl
[i
].dlg_code
, "%u: wrong dlg_code %08lx\n", i
, dlg_code
);
7752 ShowWindow(hwnd
, SW_SHOW
);
7757 if (winetest_debug
> 1) trace("static style %08lx\n", static_ctrl
[i
].style
);
7758 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(DEFAULT_GUI_FONT
), TRUE
);
7759 ok_sequence(static_ctrl
[i
].setfont
, "WM_SETFONT on a static", FALSE
);
7761 DestroyWindow(hwnd
);
7765 /****************** ComboBox message test *************************/
7766 #define ID_COMBOBOX 0x000f
7768 static const struct message SetCurSelComboSeq
[] =
7770 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7771 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7772 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7773 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7774 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7775 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7776 { LB_GETTEXT
, sent
|wparam
, 0 },
7777 { WM_CTLCOLOREDIT
, sent
|parent
},
7778 { LB_GETITEMDATA
, sent
|wparam
|lparam
, 0, 0 },
7779 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_COMBOBOX
, 0x100010f3 },
7783 static const struct message SetCurSelComboSeq2
[] =
7785 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7786 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7787 { LB_SETTOPINDEX
, sent
|wparam
|lparam
, 0, 0 },
7788 { LB_GETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7789 { LB_GETTEXTLEN
, sent
|wparam
|lparam
, 0, 0 },
7790 { LB_GETTEXTLEN
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* TODO: it's sent on all Windows versions */
7791 { LB_GETTEXT
, sent
|wparam
, 0 },
7795 static const struct message SetCurSelComboSeq_edit
[] =
7797 { CB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
7798 { WM_SETTEXT
, sent
|wparam
, 0 },
7799 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
7803 static const struct message WmKeyDownComboSeq
[] =
7805 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7806 { WM_COMMAND
, sent
|wparam
|defwinproc
, MAKEWPARAM(1000, LBN_SELCHANGE
) },
7807 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDOK
) },
7808 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELCHANGE
) },
7809 { WM_CTLCOLOREDIT
, sent
|parent
},
7810 { WM_KEYUP
, sent
|wparam
|lparam
, VK_DOWN
, 0 },
7814 static const struct message WmSetPosComboSeq
[] =
7816 { WM_WINDOWPOSCHANGING
, sent
},
7817 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
7818 { WM_CHILDACTIVATE
, sent
},
7819 { WM_WINDOWPOSCHANGED
, sent
},
7820 { WM_MOVE
, sent
|defwinproc
},
7821 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7822 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
7823 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, TRUE
},
7824 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
7825 { WM_SIZE
, sent
|defwinproc
|wparam
, SIZE_RESTORED
},
7829 static const struct message WMSetFocusComboBoxSeq
[] =
7831 { WM_SETFOCUS
, sent
},
7832 { WM_KILLFOCUS
, sent
|parent
},
7833 { WM_SETFOCUS
, sent
},
7834 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7835 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7836 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7837 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7838 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7842 static const struct message SetFocusButtonSeq
[] =
7844 { WM_KILLFOCUS
, sent
},
7845 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7846 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7847 { WM_LBUTTONUP
, sent
|defwinproc
},
7848 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7849 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7850 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7851 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7852 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7853 { WM_CTLCOLORBTN
, sent
|parent
},
7857 static const struct message SetFocusComboBoxSeq
[] =
7859 { WM_CTLCOLORBTN
, sent
|parent
},
7860 { WM_SETFOCUS
, sent
},
7861 { WM_KILLFOCUS
, sent
|defwinproc
},
7862 { EM_GETPASSWORDCHAR
, sent
|optional
}, /* Sent on some Win10 machines */
7863 { WM_SETFOCUS
, sent
},
7864 { WM_COMMAND
, sent
|defwinproc
|wparam
, MAKEWPARAM(1001, EN_SETFOCUS
) },
7865 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, INT_MAX
},
7866 { WM_CTLCOLOREDIT
, sent
|defwinproc
|optional
},/* Not sent on W2000, XP or Server 2003 */
7867 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},/* Not sent on W2000, XP or Server 2003 */
7868 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SETFOCUS
) },
7872 static const struct message SetFocusButtonSeq2
[] =
7874 { WM_KILLFOCUS
, sent
},
7875 { CB_GETCOMBOBOXINFO
, sent
|optional
},/* Windows 2000 */
7876 { 0x0167, sent
|optional
},/* Undocumented message. Sent on all versions except Windows 2000 */
7877 { WM_LBUTTONUP
, sent
|defwinproc
},
7878 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_SELENDCANCEL
) },
7879 { EM_SETSEL
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
7880 { WM_CTLCOLOREDIT
, sent
|defwinproc
},
7881 { WM_CTLCOLOREDIT
, sent
|parent
},
7882 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_COMBOBOX
, CBN_KILLFOCUS
) },
7883 { WM_CTLCOLORBTN
, sent
|parent
},
7887 static WNDPROC old_combobox_proc
, edit_window_proc
, lbox_window_proc
;
7889 static LRESULT CALLBACK
combobox_edit_subclass_proc(HWND hwnd
, UINT message
,
7890 WPARAM wParam
, LPARAM lParam
)
7892 static LONG defwndproc_counter
= 0;
7894 struct recvd_message msg
;
7896 /* do not log painting messages */
7897 if (message
!= WM_PAINT
&&
7898 message
!= WM_NCPAINT
&&
7899 message
!= WM_SYNCPAINT
&&
7900 message
!= WM_ERASEBKGND
&&
7901 message
!= WM_NCHITTEST
&&
7902 message
!= WM_GETTEXT
&&
7903 !ignore_message( message
))
7906 msg
.message
= message
;
7907 msg
.flags
= sent
|wparam
|lparam
;
7908 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7909 msg
.wParam
= wParam
;
7910 msg
.lParam
= lParam
;
7911 msg
.descr
= "combo edit";
7915 defwndproc_counter
++;
7916 ret
= CallWindowProcA(edit_window_proc
, hwnd
, message
, wParam
, lParam
);
7917 defwndproc_counter
--;
7922 static LRESULT CALLBACK
combobox_lbox_subclass_proc(HWND hwnd
, UINT message
,
7923 WPARAM wParam
, LPARAM lParam
)
7925 static LONG defwndproc_counter
= 0;
7927 struct recvd_message msg
;
7929 /* do not log painting messages */
7930 if (message
!= WM_PAINT
&&
7931 message
!= WM_NCPAINT
&&
7932 message
!= WM_SYNCPAINT
&&
7933 message
!= WM_ERASEBKGND
&&
7934 message
!= WM_NCHITTEST
&&
7935 !ignore_message( message
))
7938 msg
.message
= message
;
7939 msg
.flags
= sent
|wparam
|lparam
;
7940 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7941 msg
.wParam
= wParam
;
7942 msg
.lParam
= lParam
;
7943 msg
.descr
= "combo lbox";
7947 defwndproc_counter
++;
7948 ret
= CallWindowProcA(lbox_window_proc
, hwnd
, message
, wParam
, lParam
);
7949 defwndproc_counter
--;
7954 static LRESULT CALLBACK
combobox_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
7956 static LONG defwndproc_counter
= 0;
7958 struct recvd_message msg
;
7960 /* do not log painting messages */
7961 if (message
!= WM_PAINT
&&
7962 message
!= WM_NCPAINT
&&
7963 message
!= WM_SYNCPAINT
&&
7964 message
!= WM_ERASEBKGND
&&
7965 message
!= WM_NCHITTEST
&&
7966 message
!= WM_GETTEXT
&&
7967 !ignore_message( message
))
7970 msg
.message
= message
;
7971 msg
.flags
= sent
|wparam
|lparam
;
7972 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
7973 msg
.wParam
= wParam
;
7974 msg
.lParam
= lParam
;
7975 msg
.descr
= "combo";
7979 defwndproc_counter
++;
7980 ret
= CallWindowProcA(old_combobox_proc
, hwnd
, message
, wParam
, lParam
);
7981 defwndproc_counter
--;
7986 static void subclass_combobox(void)
7991 ret
= GetClassInfoA(0, "ComboBox", &cls
);
7992 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
7994 old_combobox_proc
= cls
.lpfnWndProc
;
7996 cls
.hInstance
= GetModuleHandleA(NULL
);
7997 cls
.lpfnWndProc
= combobox_hook_proc
;
7998 cls
.lpszClassName
= "my_combobox_class";
7999 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
8000 register_class(&cls
);
8003 static void test_combobox_messages(void)
8005 HWND parent
, combo
, button
, edit
, lbox
;
8007 COMBOBOXINFO cbInfo
;
8010 subclass_combobox();
8012 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8013 100, 100, 200, 200, 0, 0, 0, NULL
);
8014 ok(parent
!= 0, "Failed to create parent window\n");
8017 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
8018 0, 0, 100, 150, parent
, (HMENU
)ID_COMBOBOX
, 0, NULL
);
8019 ok(combo
!= 0, "Failed to create combobox window\n");
8021 UpdateWindow(combo
);
8023 ret
= SendMessageA(combo
, WM_GETDLGCODE
, 0, 0);
8024 ok(ret
== (DLGC_WANTCHARS
| DLGC_WANTARROWS
), "wrong dlg_code %08Ix\n", ret
);
8026 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
8027 ok(ret
== 0, "expected 0, got %Id\n", ret
);
8028 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 1");
8029 ok(ret
== 1, "expected 1, got %Id\n", ret
);
8030 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 2");
8031 ok(ret
== 2, "expected 2, got %Id\n", ret
);
8033 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8037 log_all_parent_messages
++;
8038 SendMessageA(combo
, WM_KEYDOWN
, VK_DOWN
, 0);
8039 SendMessageA(combo
, WM_KEYUP
, VK_DOWN
, 0);
8040 log_all_parent_messages
--;
8041 ok_sequence(WmKeyDownComboSeq
, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE
);
8044 SetWindowPos(combo
, 0, 10, 10, 120, 130, SWP_NOZORDER
);
8045 ok_sequence(WmSetPosComboSeq
, "repositioning messages on a ComboBox", FALSE
);
8047 DestroyWindow(combo
);
8048 DestroyWindow(parent
);
8050 /* Start again. Test combobox text selection when getting and losing focus */
8051 parent
= CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
8052 10, 10, 300, 300, NULL
, NULL
, NULL
, NULL
);
8053 ok(parent
!= 0, "Failed to create parent window\n");
8055 combo
= CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD
| WS_VISIBLE
| CBS_DROPDOWN
,
8056 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
8057 ok(combo
!= 0, "Failed to create combobox window\n");
8059 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
8060 SetLastError(0xdeadbeef);
8061 res
= GetComboBoxInfo(combo
, &cbInfo
);
8062 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8063 edit
= cbInfo
.hwndItem
;
8065 edit_window_proc
= (WNDPROC
)SetWindowLongPtrA(edit
, GWLP_WNDPROC
,
8066 (ULONG_PTR
)combobox_edit_subclass_proc
);
8068 button
= CreateWindowExA(0, "Button", "OK", WS_CHILD
| WS_VISIBLE
| BS_DEFPUSHBUTTON
,
8069 5, 50, 100, 20, parent
, NULL
,
8070 (HINSTANCE
)GetWindowLongPtrA(parent
, GWLP_HINSTANCE
), NULL
);
8071 ok(button
!= 0, "Failed to create button window\n");
8074 log_all_parent_messages
++;
8075 SendMessageA(combo
, WM_SETFOCUS
, 0, (LPARAM
)edit
);
8076 log_all_parent_messages
--;
8077 ok_sequence(WMSetFocusComboBoxSeq
, "WM_SETFOCUS on a ComboBox", TRUE
);
8080 log_all_parent_messages
++;
8082 log_all_parent_messages
--;
8083 ok_sequence(SetFocusButtonSeq
, "SetFocus on a Button", TRUE
);
8085 SendMessageA(combo
, WM_SETTEXT
, 0, (LPARAM
)"Wine Test");
8088 log_all_parent_messages
++;
8090 log_all_parent_messages
--;
8091 ok_sequence(SetFocusComboBoxSeq
, "SetFocus on a ComboBox", TRUE
);
8094 log_all_parent_messages
++;
8096 log_all_parent_messages
--;
8097 ok_sequence(SetFocusButtonSeq2
, "SetFocus on a Button (2)", TRUE
);
8100 SendMessageA(combo
, WM_SETREDRAW
, FALSE
, 0);
8102 log_all_parent_messages
++;
8103 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8104 log_all_parent_messages
--;
8105 ok_sequence(SetCurSelComboSeq_edit
, "CB_SETCURSEL on a ComboBox with edit control", FALSE
);
8107 DestroyWindow(button
);
8108 DestroyWindow(combo
);
8110 combo
= CreateWindowExA(0, "my_combobox_class", "test",
8111 WS_CHILD
| WS_VISIBLE
| CBS_OWNERDRAWFIXED
| CBS_DROPDOWNLIST
,
8112 5, 5, 100, 100, parent
, (HMENU
)ID_COMBOBOX
, NULL
, NULL
);
8113 ok(combo
!= 0, "Failed to create combobox window\n");
8115 ret
= SendMessageA(combo
, CB_ADDSTRING
, 0, (LPARAM
)"item 0");
8116 ok(ret
== 0, "expected 0, got %Id\n", ret
);
8118 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
8119 SetLastError(0xdeadbeef);
8120 res
= GetComboBoxInfo(combo
, &cbInfo
);
8121 ok(res
, "Failed to get COMBOBOXINFO structure; LastError: %lu\n", GetLastError());
8122 lbox
= cbInfo
.hwndList
;
8123 lbox_window_proc
= (WNDPROC
)SetWindowLongPtrA(lbox
, GWLP_WNDPROC
,
8124 (ULONG_PTR
)combobox_lbox_subclass_proc
);
8127 log_all_parent_messages
++;
8128 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8129 log_all_parent_messages
--;
8130 ok_sequence(SetCurSelComboSeq
, "CB_SETCURSEL on a ComboBox", FALSE
);
8132 ShowWindow(combo
, SW_HIDE
);
8134 log_all_parent_messages
++;
8135 SendMessageA(combo
, CB_SETCURSEL
, 0, 0);
8136 log_all_parent_messages
--;
8137 ok_sequence(SetCurSelComboSeq2
, "CB_SETCURSEL on a ComboBox", FALSE
);
8139 DestroyWindow(combo
);
8140 DestroyWindow(parent
);
8143 /****************** WM_IME_KEYDOWN message test *******************/
8145 static const struct message WmImeKeydownMsgSeq_0
[] =
8147 { WM_IME_KEYDOWN
, wparam
, VK_RETURN
},
8148 { WM_CHAR
, wparam
, 'A' },
8152 static const struct message WmImeKeydownMsgSeq_1
[] =
8154 { WM_KEYDOWN
, optional
|wparam
, VK_RETURN
},
8155 { WM_CHAR
, optional
|wparam
, VK_RETURN
},
8159 static LRESULT WINAPI
wmime_keydown_procA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
8161 struct recvd_message msg
;
8164 msg
.message
= message
;
8165 msg
.flags
= wparam
|lparam
;
8166 msg
.wParam
= wParam
;
8167 msg
.lParam
= lParam
;
8168 msg
.descr
= "wmime_keydown";
8171 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
8174 static void register_wmime_keydown_class(void)
8178 ZeroMemory(&cls
, sizeof(WNDCLASSA
));
8179 cls
.lpfnWndProc
= wmime_keydown_procA
;
8180 cls
.hInstance
= GetModuleHandleA(0);
8181 cls
.lpszClassName
= "wmime_keydown_class";
8182 register_class(&cls
);
8185 static void test_wmime_keydown_message(void)
8190 if (winetest_debug
> 1) trace("Message sequences by WM_IME_KEYDOWN\n");
8192 register_wmime_keydown_class();
8193 hwnd
= CreateWindowExA(0, "wmime_keydown_class", NULL
, WS_OVERLAPPEDWINDOW
,
8194 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
8199 SendMessageA(hwnd
, WM_IME_KEYDOWN
, VK_RETURN
, 0x1c0001);
8200 SendMessageA(hwnd
, WM_CHAR
, 'A', 1);
8201 ok_sequence(WmImeKeydownMsgSeq_0
, "WM_IME_KEYDOWN 0", FALSE
);
8203 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
8205 TranslateMessage(&msg
);
8206 DispatchMessageA(&msg
);
8208 ok_sequence(WmImeKeydownMsgSeq_1
, "WM_IME_KEYDOWN 1", FALSE
);
8210 DestroyWindow(hwnd
);
8213 /************* painting message test ********************/
8215 void dump_region(HRGN hrgn
)
8218 RGNDATA
*data
= NULL
;
8223 printf( "null region\n" );
8226 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) return;
8227 if (!(data
= malloc( size
))) return;
8228 GetRegionData( hrgn
, size
, data
);
8229 printf("%ld rects:", data
->rdh
.nCount
);
8230 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
< data
->rdh
.nCount
; i
++, rect
++)
8231 printf( " %s", wine_dbgstr_rect( rect
));
8236 #define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn )
8237 static void check_update_rgn_( int line
, HWND hwnd
, HRGN hrgn
)
8241 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
8242 HRGN update
= CreateRectRgn( 0, 0, 0, 0 );
8244 ret
= GetUpdateRgn( hwnd
, update
, FALSE
);
8245 ok( ret
!= ERROR
, "GetUpdateRgn failed\n" );
8246 if (ret
== NULLREGION
)
8248 ok_(__FILE__
,line
)( !hrgn
, "Update region shouldn't be empty\n" );
8252 if (CombineRgn( tmp
, hrgn
, update
, RGN_XOR
) != NULLREGION
)
8254 ok_(__FILE__
,line
)( 0, "Regions are different\n" );
8255 if (winetest_debug
> 0)
8257 printf( "Update region: " );
8258 dump_region( update
);
8259 printf( "Wanted region: " );
8260 dump_region( hrgn
);
8264 GetRgnBox( update
, &r1
);
8265 GetUpdateRect( hwnd
, &r2
, FALSE
);
8266 ok_(__FILE__
,line
)( EqualRect( &r1
, &r2
), "Rectangles are different: %s / %s\n",
8267 wine_dbgstr_rect( &r1
), wine_dbgstr_rect( &r2
));
8269 DeleteObject( tmp
);
8270 DeleteObject( update
);
8273 static const struct message WmInvalidateRgn
[] = {
8274 { WM_NCPAINT
, sent
},
8275 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8279 static const struct message WmGetUpdateRect
[] = {
8280 { WM_NCPAINT
, sent
},
8281 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8286 static const struct message WmInvalidateFull
[] = {
8287 { WM_NCPAINT
, sent
|wparam
, 1 },
8288 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8292 static const struct message WmInvalidateErase
[] = {
8293 { WM_NCPAINT
, sent
|wparam
, 1 },
8294 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8295 { WM_ERASEBKGND
, sent
},
8299 static const struct message WmInvalidatePaint
[] = {
8301 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
8302 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8306 static const struct message WmInvalidateErasePaint
[] = {
8308 { WM_NCPAINT
, sent
|wparam
|beginpaint
, 1 },
8309 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8310 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8314 static const struct message WmInvalidateErasePaint2
[] = {
8316 { WM_NCPAINT
, sent
|beginpaint
},
8317 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8318 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8322 static const struct message WmErase
[] = {
8323 { WM_ERASEBKGND
, sent
},
8327 static const struct message WmPaint
[] = {
8332 static const struct message WmParentOnlyPaint
[] = {
8333 { WM_PAINT
, sent
|parent
},
8337 static const struct message WmInvalidateParent
[] = {
8338 { WM_NCPAINT
, sent
|parent
},
8339 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
8340 { WM_ERASEBKGND
, sent
|parent
},
8344 static const struct message WmInvalidateParentChild
[] = {
8345 { WM_NCPAINT
, sent
|parent
},
8346 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
8347 { WM_ERASEBKGND
, sent
|parent
},
8348 { WM_NCPAINT
, sent
},
8349 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8350 { WM_ERASEBKGND
, sent
},
8354 static const struct message WmInvalidateParentChild2
[] = {
8355 { WM_ERASEBKGND
, sent
|parent
},
8356 { WM_NCPAINT
, sent
},
8357 { WM_GETTEXT
, sent
|defwinproc
|optional
},
8358 { WM_ERASEBKGND
, sent
},
8362 static const struct message WmParentPaint
[] = {
8363 { WM_PAINT
, sent
|parent
},
8368 static const struct message WmParentPaintNc
[] = {
8369 { WM_PAINT
, sent
|parent
},
8371 { WM_NCPAINT
, sent
|beginpaint
},
8372 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8373 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8374 { WM_GETMINMAXINFO
, sent
|optional
},
8378 static const struct message WmChildPaintNc
[] = {
8380 { WM_NCPAINT
, sent
|beginpaint
},
8381 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8382 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8386 static const struct message WmParentErasePaint
[] = {
8387 { WM_PAINT
, sent
|parent
},
8388 { WM_NCPAINT
, sent
|parent
|beginpaint
},
8389 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
8390 { WM_ERASEBKGND
, sent
|parent
|beginpaint
|optional
},
8392 { WM_NCPAINT
, sent
|beginpaint
},
8393 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
8394 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
8398 static const struct message WmParentOnlyNcPaint
[] = {
8399 { WM_PAINT
, sent
|parent
},
8400 { WM_NCPAINT
, sent
|parent
|beginpaint
},
8401 { WM_GETTEXT
, sent
|parent
|beginpaint
|defwinproc
|optional
},
8405 static const struct message WmSetParentStyle
[] = {
8406 { WM_STYLECHANGING
, sent
|parent
},
8407 { WM_STYLECHANGED
, sent
|parent
},
8411 static void test_paint_messages(void)
8418 HWND hparent
, hchild
;
8419 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
8420 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
8421 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
8422 100, 100, 200, 200, 0, 0, 0, NULL
);
8423 ok (hwnd
!= 0, "Failed to create overlapped window\n");
8425 ShowWindow( hwnd
, SW_SHOW
);
8426 UpdateWindow( hwnd
);
8430 check_update_rgn( hwnd
, 0 );
8431 SetRectRgn( hrgn
, 10, 10, 20, 20 );
8432 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8433 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8434 check_update_rgn( hwnd
, hrgn
);
8435 SetRectRgn( hrgn2
, 20, 20, 30, 30 );
8436 ret
= RedrawWindow( hwnd
, NULL
, hrgn2
, RDW_INVALIDATE
);
8437 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8438 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_OR
);
8439 check_update_rgn( hwnd
, hrgn
);
8440 /* validate everything */
8441 ret
= RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8442 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8443 check_update_rgn( hwnd
, 0 );
8445 /* test empty region */
8446 SetRectRgn( hrgn
, 10, 10, 10, 15 );
8447 ret
= RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8448 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8449 check_update_rgn( hwnd
, 0 );
8450 /* test empty rect */
8451 SetRect( &rect
, 10, 10, 10, 15 );
8452 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8453 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8454 check_update_rgn( hwnd
, 0 );
8456 /* test a zeroed rectangle */
8457 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8458 SetRect( &rect
, 0, 0, 0, 0 );
8459 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8460 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8461 check_update_rgn( hwnd
, 0 );
8463 /* a well ordered rectangle */
8464 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8465 SetRect( &rect
, 10, 5, 17, 21 );
8466 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8467 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8468 SetRectRgn( hrgn
, 10, 5, 17, 21 );
8469 check_update_rgn( hwnd
, hrgn
);
8471 /* empty rectangle, top and bottom are swapped but left and right have
8473 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8474 SetRect( &rect
, 5, 30, 5, 10 );
8475 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8476 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8477 check_update_rgn( hwnd
, 0 );
8479 /* empty rectangle, left and right are swapped but top and bottom have
8481 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8482 SetRect( &rect
, 17, 10, 5, 10 );
8483 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8484 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8485 check_update_rgn( hwnd
, 0 );
8487 /* Left and right are swapped */
8488 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8489 SetRect( &rect
, 21, 12, 7, 30 );
8490 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8491 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8492 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8493 check_update_rgn( hwnd
, hrgn
);
8495 /* Top and bottom are swapped */
8496 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8497 SetRect( &rect
, 7, 30, 21, 12 );
8498 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8499 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8500 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8501 check_update_rgn( hwnd
, hrgn
);
8503 /* both reference points are swapped */
8504 RedrawWindow( hwnd
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
8505 SetRect( &rect
, 21, 30, 7, 12 );
8506 ret
= RedrawWindow( hwnd
, &rect
, NULL
, RDW_INVALIDATE
);
8507 ok(ret
, "RedrawWindow returned %d instead of TRUE\n", ret
);
8508 SetRectRgn( hrgn
, 7, 12, 21, 30 );
8509 check_update_rgn( hwnd
, hrgn
);
8511 /* flush pending messages */
8515 GetClientRect( hwnd
, &rect
);
8516 SetRectRgn( hrgn
, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
8517 /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
8518 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8520 SetRectEmpty( &rect
);
8521 ok(InvalidateRect(0, &rect
, FALSE
), "InvalidateRect(0, &rc, FALSE) failed\n");
8522 check_update_rgn( hwnd
, hrgn
);
8523 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8525 ok_sequence( WmPaint
, "Paint", FALSE
);
8526 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8527 check_update_rgn( hwnd
, 0 );
8529 SetRectEmpty( &rect
);
8530 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8531 "RedrawWindow failed\n");
8532 check_update_rgn( hwnd
, 0 );
8534 SetRectEmpty( &rect
);
8535 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_VALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8536 "RedrawWindow failed\n");
8537 check_update_rgn( hwnd
, 0 );
8539 GetWindowRect( hwnd
, &rect
);
8540 ok(RedrawWindow(0, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8541 "RedrawWindow failed\n");
8542 check_update_rgn( hwnd
, 0 );
8545 ok(RedrawWindow(0, &rect
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8546 "RedrawWindow failed\n");
8547 check_update_rgn( hwnd
, hrgn
);
8548 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8550 ok_sequence( WmPaint
, "Paint", FALSE
);
8551 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8552 check_update_rgn( hwnd
, 0 );
8554 ok(RedrawWindow(GetDesktopWindow(), &rect
, 0,
8555 RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8556 "RedrawWindow failed\n");
8557 ret
= GetUpdateRgn( hwnd
, hrgn2
, FALSE
);
8558 ok( ret
== NULLREGION
|| broken(ret
== SIMPLEREGION
), /* <= win7 */
8559 "region should be null (%d)\n", ret
);
8560 if (ret
== SIMPLEREGION
) ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8561 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8564 ok(RedrawWindow(GetDesktopWindow(), NULL
, 0,
8565 RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8566 "RedrawWindow failed\n");
8567 ret
= GetUpdateRgn( hwnd
, hrgn2
, FALSE
);
8568 ok( ret
== NULLREGION
|| broken(ret
== SIMPLEREGION
), /* <= win7 */
8569 "region should be null (%d)\n", ret
);
8570 if (ret
== SIMPLEREGION
) ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8571 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8574 SetRectRgn( hrgn2
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8575 ok(RedrawWindow(0, NULL
, hrgn2
, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
),
8576 "RedrawWindow failed\n");
8577 check_update_rgn( hwnd
, hrgn
);
8578 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8580 ok_sequence( WmPaint
, "Paint", FALSE
);
8581 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8582 check_update_rgn( hwnd
, 0 );
8584 ok(RedrawWindow(0, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
),
8585 "RedrawWindow failed\n");
8586 check_update_rgn( hwnd
, 0 );
8588 ok(RedrawWindow(0, NULL
, 0, RDW_ALLCHILDREN
| RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
),
8589 "RedrawWindow failed\n");
8590 check_update_rgn( hwnd
, hrgn
);
8591 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8593 ok_sequence( WmPaint
, "Paint", FALSE
);
8594 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8595 check_update_rgn( hwnd
, 0 );
8597 /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
8598 * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
8600 SetRectEmpty( &rect
);
8601 if (ValidateRect(0, &rect
) && /* not supported on Win9x */
8602 GetUpdateRect(hwnd
, NULL
, FALSE
)) /* or >= Win 8 */
8604 check_update_rgn( hwnd
, hrgn
);
8605 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8607 ok_sequence( WmPaint
, "Paint", FALSE
);
8608 RedrawWindow( hwnd
, NULL
, NULL
, RDW_VALIDATE
);
8609 check_update_rgn( hwnd
, 0 );
8612 SetLastError(0xdeadbeef);
8613 ok(!InvalidateRgn(0, NULL
, FALSE
), "InvalidateRgn(0, NULL, FALSE) should fail\n");
8614 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| GetLastError() == 0xdeadbeef,
8615 "wrong error code %ld\n", GetLastError());
8616 check_update_rgn( hwnd
, 0 );
8618 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8620 SetLastError(0xdeadbeef);
8621 ok(!ValidateRgn(0, NULL
), "ValidateRgn(0, NULL) should fail\n");
8622 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
8623 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8624 "wrong error code %ld\n", GetLastError());
8625 check_update_rgn( hwnd
, 0 );
8627 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8629 SetLastError(0xdeadbeef);
8630 ok(!UpdateWindow(NULL
), "UpdateWindow(NULL) should fail\n");
8631 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
||
8632 broken( GetLastError() == 0xdeadbeef ) /* win9x */,
8633 "wrong error code %ld\n", GetLastError());
8634 check_update_rgn( hwnd
, 0 );
8636 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
8638 /* now with frame */
8639 SetRectRgn( hrgn
, -5, -5, 20, 20 );
8641 /* flush pending messages */
8644 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8645 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
8647 SetRectRgn( hrgn
, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */
8648 check_update_rgn( hwnd
, hrgn
);
8651 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
8652 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
8655 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
8656 ok_sequence( WmInvalidateFull
, "InvalidateFull", FALSE
);
8658 GetClientRect( hwnd
, &rect
);
8659 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8660 check_update_rgn( hwnd
, hrgn
);
8663 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_ERASENOW
);
8664 ok_sequence( WmInvalidateErase
, "InvalidateErase", FALSE
);
8667 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
| RDW_UPDATENOW
);
8668 ok_sequence( WmInvalidatePaint
, "InvalidatePaint", FALSE
);
8669 check_update_rgn( hwnd
, 0 );
8672 RedrawWindow( hwnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
| RDW_UPDATENOW
);
8673 ok_sequence( WmInvalidateErasePaint
, "InvalidateErasePaint", FALSE
);
8674 check_update_rgn( hwnd
, 0 );
8677 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8678 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
);
8679 SetRectRgn( hrgn
, 0, 0, 50, 100 );
8680 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
);
8681 SetRectRgn( hrgn
, 50, 0, 100, 100 );
8682 check_update_rgn( hwnd
, hrgn
);
8683 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
8684 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
); /* must not generate messages, everything is valid */
8685 check_update_rgn( hwnd
, 0 );
8688 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8689 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
8690 SetRectRgn( hrgn
, 0, 0, 100, 50 );
8691 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_ERASENOW
);
8692 ok_sequence( WmErase
, "Erase", FALSE
);
8693 SetRectRgn( hrgn
, 0, 50, 100, 100 );
8694 check_update_rgn( hwnd
, hrgn
);
8697 SetRectRgn( hrgn
, 0, 0, 100, 100 );
8698 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
8699 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8700 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOERASE
| RDW_UPDATENOW
);
8701 ok_sequence( WmPaint
, "Paint", FALSE
);
8704 SetRectRgn( hrgn
, -4, -4, -2, -2 );
8705 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8706 SetRectRgn( hrgn
, -200, -200, -198, -198 );
8707 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
| RDW_ERASENOW
);
8708 ok_sequence( WmEmptySeq
, "EmptySeq", FALSE
);
8711 SetRectRgn( hrgn
, -4, -4, -2, -2 );
8712 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8713 SetRectRgn( hrgn
, -4, -4, -3, -3 );
8714 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOFRAME
);
8715 SetRectRgn( hrgn
, 0, 0, 1, 1 );
8716 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_UPDATENOW
);
8717 ok_sequence( WmPaint
, "Paint", FALSE
);
8720 SetRectRgn( hrgn
, -4, -4, -1, -1 );
8721 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8722 RedrawWindow( hwnd
, NULL
, 0, RDW_ERASENOW
);
8723 /* make sure no WM_PAINT was generated */
8725 ok_sequence( WmInvalidateRgn
, "InvalidateRgn", FALSE
);
8728 SetRectRgn( hrgn
, -4, -4, -1, -1 );
8729 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
);
8730 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
8732 if (msg
.hwnd
== hwnd
&& msg
.message
== WM_PAINT
)
8734 /* GetUpdateRgn must return empty region since only nonclient area is invalidated */
8735 INT ret
= GetUpdateRgn( hwnd
, hrgn
, FALSE
);
8736 ok( ret
== NULLREGION
, "Invalid GetUpdateRgn result %d\n", ret
);
8737 ret
= GetUpdateRect( hwnd
, &rect
, FALSE
);
8738 ok( ret
, "Invalid GetUpdateRect result %d\n", ret
);
8739 /* this will send WM_NCPAINT and validate the non client area */
8740 ret
= GetUpdateRect( hwnd
, &rect
, TRUE
);
8741 ok( !ret
, "Invalid GetUpdateRect result %d\n", ret
);
8743 DispatchMessageA( &msg
);
8745 ok_sequence( WmGetUpdateRect
, "GetUpdateRect", FALSE
);
8747 DestroyWindow( hwnd
);
8749 /* now test with a child window */
8751 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
8752 100, 100, 200, 200, 0, 0, 0, NULL
);
8753 ok (hparent
!= 0, "Failed to create parent window\n");
8755 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
8756 10, 10, 100, 100, hparent
, 0, 0, NULL
);
8757 ok (hchild
!= 0, "Failed to create child window\n");
8759 ShowWindow( hparent
, SW_SHOW
);
8760 UpdateWindow( hparent
);
8761 UpdateWindow( hchild
);
8764 log_all_parent_messages
++;
8766 SetRect( &rect
, 0, 0, 50, 50 );
8767 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8768 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8769 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild", FALSE
);
8771 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8773 MapWindowPoints( hchild
, hparent
, &pt
, 1 );
8774 SetRectRgn( hrgn
, 0, 0, 50 - pt
.x
, 50 - pt
.y
);
8775 check_update_rgn( hchild
, hrgn
);
8776 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8777 check_update_rgn( hparent
, hrgn
);
8778 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8779 ok_sequence( WmInvalidateParent
, "InvalidateParent", FALSE
);
8780 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8781 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8784 ok_sequence( WmParentPaintNc
, "WmParentPaintNc", FALSE
);
8786 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8787 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8788 ok_sequence( WmInvalidateParent
, "InvalidateParent2", FALSE
);
8789 RedrawWindow( hchild
, NULL
, 0, RDW_ERASENOW
);
8790 ok_sequence( WmEmptySeq
, "EraseNow child", FALSE
);
8792 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
8793 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
| RDW_ALLCHILDREN
);
8794 ok_sequence( WmInvalidateParentChild2
, "InvalidateParentChild2", FALSE
);
8796 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8798 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8799 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8800 ok_sequence( WmInvalidateParentChild
, "InvalidateParentChild3", FALSE
);
8802 /* flush all paint messages */
8806 /* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */
8807 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
| RDW_ALLCHILDREN
);
8808 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8809 check_update_rgn( hparent
, hrgn
);
8810 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8811 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8812 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8813 check_update_rgn( hparent
, hrgn
);
8815 /* flush all paint messages */
8817 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8820 /* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */
8821 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8822 SetRectRgn( hrgn
, 0, 0, 50, 50 );
8823 check_update_rgn( hparent
, hrgn
);
8824 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8825 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8826 SetRectRgn( hrgn2
, 10, 10, 50, 50 );
8827 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
8828 check_update_rgn( hparent
, hrgn
);
8829 /* flush all paint messages */
8833 /* same as above but parent gets completely validated */
8834 SetRect( &rect
, 20, 20, 30, 30 );
8835 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8836 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8837 check_update_rgn( hparent
, hrgn
);
8838 RedrawWindow( hchild
, NULL
, 0, RDW_UPDATENOW
);
8839 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8840 check_update_rgn( hparent
, 0 ); /* no update region */
8842 ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
); /* and no paint messages */
8844 /* make sure RDW_VALIDATE on child doesn't have the same effect */
8846 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8847 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8848 check_update_rgn( hparent
, hrgn
);
8849 RedrawWindow( hchild
, NULL
, 0, RDW_VALIDATE
| RDW_NOERASE
);
8850 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8851 check_update_rgn( hparent
, hrgn
);
8853 /* same as above but normal WM_PAINT doesn't validate parent */
8855 SetRect( &rect
, 20, 20, 30, 30 );
8856 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8857 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8858 check_update_rgn( hparent
, hrgn
);
8859 /* no WM_PAINT in child while parent still pending */
8860 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8861 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8862 while (PeekMessageA( &msg
, hparent
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8863 ok_sequence( WmParentErasePaint
, "WmParentErasePaint", FALSE
);
8866 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8867 /* no WM_PAINT in child while parent still pending */
8868 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8869 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8870 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_NOERASE
| RDW_NOCHILDREN
);
8871 /* now that parent is valid child should get WM_PAINT */
8872 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8873 ok_sequence( WmInvalidateErasePaint2
, "WmInvalidateErasePaint2", FALSE
);
8874 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8875 ok_sequence( WmEmptySeq
, "No other message", FALSE
);
8877 /* same thing with WS_CLIPCHILDREN in parent */
8879 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) | WS_CLIPCHILDREN
);
8880 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8881 /* changing style invalidates non client area, but we need to invalidate something else to see it */
8882 RedrawWindow( hparent
, &rect
, 0, RDW_UPDATENOW
);
8883 ok_sequence( WmEmptySeq
, "No message", FALSE
);
8884 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_UPDATENOW
);
8885 ok_sequence( WmParentOnlyNcPaint
, "WmParentOnlyNcPaint", FALSE
);
8888 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8889 SetRectRgn( hrgn
, 20, 20, 30, 30 );
8890 check_update_rgn( hparent
, hrgn
);
8891 /* no WM_PAINT in child while parent still pending */
8892 while (PeekMessageA( &msg
, hchild
, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8893 ok_sequence( WmEmptySeq
, "No WM_PAINT", FALSE
);
8894 /* WM_PAINT in parent first */
8895 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
8896 ok_sequence( WmParentPaintNc
, "WmParentPaintNc2", FALSE
);
8898 /* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */
8900 SetRect( &rect
, 0, 0, 30, 30 );
8901 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
);
8902 SetRectRgn( hrgn
, 0, 0, 30, 30 );
8903 check_update_rgn( hparent
, hrgn
);
8905 ok_sequence( WmParentPaintNc
, "WmParentPaintNc3", FALSE
);
8907 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8909 SetRect( &rect
, -10, 0, 30, 30 );
8910 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8911 SetRect( &rect
, 0, 0, 20, 20 );
8912 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8913 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8914 ok_sequence( WmChildPaintNc
, "WmChildPaintNc", FALSE
);
8916 /* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */
8918 SetRect( &rect
, -10, 0, 30, 30 );
8919 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
8920 SetRect( &rect
, 0, 0, 100, 100 );
8921 RedrawWindow( hparent
, &rect
, 0, RDW_VALIDATE
| RDW_ALLCHILDREN
);
8922 RedrawWindow( hparent
, NULL
, 0, RDW_UPDATENOW
);
8923 ok_sequence( WmEmptySeq
, "WmChildPaintNc2", FALSE
);
8924 RedrawWindow( hparent
, NULL
, 0, RDW_ERASENOW
);
8925 ok_sequence( WmEmptySeq
, "WmChildPaintNc3", FALSE
);
8927 /* WS_CLIPCHILDREN doesn't exclude children from update region */
8929 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
8930 GetClientRect( hparent
, &rect
);
8931 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8932 check_update_rgn( hparent
, hrgn
);
8935 RedrawWindow( hparent
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_ALLCHILDREN
);
8936 GetClientRect( hparent
, &rect
);
8937 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
8938 check_update_rgn( hparent
, hrgn
);
8941 /* test RDW_INTERNALPAINT behavior */
8944 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_NOCHILDREN
);
8946 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8948 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
| RDW_ALLCHILDREN
);
8950 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8952 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8954 ok_sequence( WmParentOnlyPaint
, "WmParentOnlyPaint", FALSE
);
8956 style
= GetWindowLongA(hparent
, GWL_STYLE
);
8957 ok(style
& WS_CLIPCHILDREN
, "Got unexpected style %#lx.\n", style
);
8958 UpdateWindow( hparent
);
8961 if (winetest_debug
> 1) trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
8962 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8963 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8964 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8966 ok_sequence(WmSWP_FrameChanged_clip
, "SetWindowPos:FrameChanged_clip", FALSE
);
8968 UpdateWindow( hparent
);
8971 if (winetest_debug
> 1) trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
8972 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8973 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
8974 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8976 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
8978 SetWindowLongA( hparent
, GWL_STYLE
, GetWindowLongA(hparent
,GWL_STYLE
) & ~WS_CLIPCHILDREN
);
8979 ok_sequence( WmSetParentStyle
, "WmSetParentStyle", FALSE
);
8980 RedrawWindow( hparent
, NULL
, 0, RDW_INTERNALPAINT
);
8982 ok_sequence( WmParentPaint
, "WmParentPaint", FALSE
);
8984 style
= GetWindowLongA(hparent
, GWL_STYLE
);
8985 ok(!(style
& WS_CLIPCHILDREN
), "Got unexpected style %#lx.\n", style
);
8986 UpdateWindow( hparent
);
8989 if (winetest_debug
> 1) trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
8990 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
8991 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
8992 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
8994 ok_sequence(WmSWP_FrameChanged_noclip
, "SetWindowPos:FrameChanged_noclip", FALSE
);
8996 UpdateWindow( hparent
);
8999 if (winetest_debug
> 1) trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
9000 RedrawWindow( hchild
, NULL
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
9001 SetWindowPos( hparent
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
| SWP_DEFERERASE
|
9002 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
9004 ok_sequence(WmSWP_FrameChangedDeferErase
, "SetWindowPos:FrameChangedDeferErase", FALSE
);
9006 ok(GetWindowLongA( hparent
, GWL_STYLE
) & WS_VISIBLE
, "parent should be visible\n");
9007 ok(GetWindowLongA( hchild
, GWL_STYLE
) & WS_VISIBLE
, "child should be visible\n");
9009 UpdateWindow( hparent
);
9012 if (winetest_debug
> 1) trace("testing SetWindowPos(-10000, -10000) on child\n");
9013 SetWindowPos( hchild
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9014 check_update_rgn( hchild
, 0 );
9017 #if 0 /* this one doesn't pass under Wine yet */
9018 UpdateWindow( hparent
);
9021 if (winetest_debug
> 1) trace("testing ShowWindow(SW_MINIMIZE) on child\n");
9022 ShowWindow( hchild
, SW_MINIMIZE
);
9023 check_update_rgn( hchild
, 0 );
9027 UpdateWindow( hparent
);
9030 if (winetest_debug
> 1) trace("testing SetWindowPos(-10000, -10000) on parent\n");
9031 SetWindowPos( hparent
, 0, -10000, -10000, 0, 0, SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9032 check_update_rgn( hparent
, 0 );
9035 log_all_parent_messages
--;
9036 DestroyWindow( hparent
);
9037 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
9039 /* tests for moving windows off-screen (needs simple WS_POPUP windows) */
9041 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP
| WS_VISIBLE
,
9042 100, 100, 200, 200, 0, 0, 0, NULL
);
9043 ok (hparent
!= 0, "Failed to create parent window\n");
9045 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD
| WS_VISIBLE
,
9046 10, 10, 100, 100, hparent
, 0, 0, NULL
);
9047 ok (hchild
!= 0, "Failed to create child window\n");
9049 ShowWindow( hparent
, SW_SHOW
);
9050 UpdateWindow( hparent
);
9051 UpdateWindow( hchild
);
9055 /* moving child outside of parent boundaries changes update region */
9056 SetRect( &rect
, 0, 0, 40, 40 );
9057 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
9058 SetRectRgn( hrgn
, 0, 0, 40, 40 );
9059 check_update_rgn( hchild
, hrgn
);
9060 MoveWindow( hchild
, -10, 10, 100, 100, FALSE
);
9061 SetRectRgn( hrgn
, 10, 0, 40, 40 );
9062 check_update_rgn( hchild
, hrgn
);
9063 MoveWindow( hchild
, -10, -10, 100, 100, FALSE
);
9064 SetRectRgn( hrgn
, 10, 10, 40, 40 );
9065 check_update_rgn( hchild
, hrgn
);
9067 /* moving parent off-screen does too */
9068 SetRect( &rect
, 0, 0, 100, 100 );
9069 RedrawWindow( hparent
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
| RDW_NOCHILDREN
);
9070 SetRectRgn( hrgn
, 0, 0, 100, 100 );
9071 check_update_rgn( hparent
, hrgn
);
9072 SetRectRgn( hrgn
, 10, 10, 40, 40 );
9073 check_update_rgn( hchild
, hrgn
);
9074 MoveWindow( hparent
, -20, -20, 200, 200, FALSE
);
9075 GetUpdateRect( hparent
, &rect2
, FALSE
);
9076 if (!EqualRect( &rect2
, &rect
)) /* Win 8 and later don't crop update to screen */
9081 SetRectRgn( hrgn
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
9082 check_update_rgn( hparent
, hrgn
);
9083 SetRectRgn( hrgn
, rect
.left
+ 10, rect
.top
+ 10, 40, 40 );
9084 check_update_rgn( hchild
, hrgn
);
9086 /* invalidated region is cropped by the parent rects */
9087 SetRect( &rect
, 0, 0, 50, 50 );
9088 RedrawWindow( hchild
, &rect
, 0, RDW_INVALIDATE
| RDW_ERASE
);
9089 SetRectRgn( hrgn
, rect2
.left
+ 10, rect2
.top
+ 10, 50, 50 );
9090 check_update_rgn( hchild
, hrgn
);
9092 DestroyWindow( hparent
);
9093 ok(!IsWindow(hchild
), "child must be destroyed with its parent\n");
9096 DeleteObject( hrgn
);
9097 DeleteObject( hrgn2
);
9100 static void visualize_region_differences( HWND hwnd
, HWND hother
, HRGN hrgn_expect
, HRGN hrgn_actual
)
9102 HBRUSH b_expectonly
, b_actualonly
, b_intersect
;
9103 HRGN hrgn_intersect
;
9104 HWND hstatic
, hshow
, hhide
;
9109 DWORD start_time
, elapsed
, timeout
= 60 * 1000;
9110 BOOL toggle
= TRUE
, stop
= FALSE
;
9112 start_time
= GetTickCount();
9114 b_expectonly
= CreateSolidBrush( RGB( 64, 64, 255 ));
9115 b_actualonly
= CreateSolidBrush( RGB( 255, 64, 64 ));
9116 b_intersect
= CreateSolidBrush( RGB( 159, 64, 159 ));
9118 hrgn_intersect
= CreateRectRgn( 0, 0, 0, 0 );
9119 CombineRgn( hrgn_intersect
, hrgn_expect
, hrgn_actual
, RGN_AND
);
9121 GetClientRect( hwnd
, &rect
);
9122 hdc
= GetDC( hwnd
);
9123 hbitmap
= CreateCompatibleBitmap( hdc
, rect
.right
, rect
.bottom
);
9124 hdctmp
= CreateCompatibleDC( hdc
);
9125 ReleaseDC( hwnd
, hdc
);
9127 SelectObject( hdctmp
, hbitmap
);
9128 FillRgn( hdctmp
, hrgn_expect
, b_expectonly
);
9129 FillRgn( hdctmp
, hrgn_actual
, b_actualonly
);
9130 FillRgn( hdctmp
, hrgn_intersect
, b_intersect
);
9132 DeleteObject( hdctmp
);
9133 DeleteObject( hrgn_intersect
);
9134 DeleteObject( b_intersect
);
9135 DeleteObject( b_actualonly
);
9136 DeleteObject( b_expectonly
);
9138 hstatic
= CreateWindowExA( 0, WC_STATICA
, "", WS_CHILD
| SS_BITMAP
,
9139 0, 0, rect
.right
, rect
.bottom
, hwnd
, 0, 0, NULL
);
9140 SendMessageA( hstatic
, STM_SETIMAGE
, IMAGE_BITMAP
, (LPARAM
)hbitmap
);
9147 if (stop
) toggle
= hshow
== hother
;
9153 hdwp
= BeginDeferWindowPos( !!hhide
+ !!hshow
);
9156 DeferWindowPos( hdwp
, hhide
, NULL
, 0, 0, 0, 0,
9157 SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
);
9161 DeferWindowPos( hdwp
, hshow
, HWND_TOP
, 0, 0, 0, 0,
9162 SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
);
9164 EndDeferWindowPos( hdwp
);
9172 if ((elapsed
= GetTickCount() - start_time
) >= timeout
)
9177 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, timeout
- elapsed
, QS_ALLINPUT
);
9178 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
9180 TranslateMessage( &msg
);
9181 DispatchMessageA( &msg
);
9182 if (msg
.message
== WM_MOUSEMOVE
)
9184 start_time
= GetTickCount();
9186 else if (msg
.message
== WM_LBUTTONUP
|| (msg
.message
== WM_CHAR
&& msg
.wParam
== VK_SPACE
))
9190 else if (msg
.message
== WM_RBUTTONUP
|| (msg
.message
== WM_CHAR
&& msg
.wParam
== VK_RETURN
))
9197 DestroyWindow( hstatic
);
9198 DeleteObject( hbitmap
);
9201 #define subtest_swp_paint_regions(w,p,c) subtest_swp_paint_regions_(__LINE__,w,p,c)
9203 static void subtest_swp_paint_regions_( int line
, int wrap_toplevel
, LPCSTR parent_class
, LPCSTR child_class
)
9205 static const struct exposure_test
{
9206 int ex_style
, style
;
9207 BOOL shuffle_zorder
;
9208 } exposure_tests
[] = {
9209 { 0, WS_CLIPCHILDREN
, FALSE
},
9211 { WS_EX_COMPOSITED
, WS_CLIPCHILDREN
, TRUE
},
9212 { WS_EX_COMPOSITED
, 0, FALSE
},
9213 { WS_EX_COMPOSITED
, 0, TRUE
},
9216 HWND htoplevel
= NULL
, hparent
, hchild
, hauxchild
;
9217 const RECT rect_old
= { 10, 10, 100, 100 };
9218 HRGN hrgn_old_vis
= CreateRectRgn( 0, 0, 0, 0 );
9219 HRGN hrgn_new_vis
= CreateRectRgn( 0, 0, 0, 0 );
9220 HRGN hrgn_expect
= CreateRectRgn( 0, 0, 0, 0 );
9221 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9222 HRGN hrgn_old_vis_child
= CreateRectRgn( 0, 0, 0, 0 );
9223 HRGN hrgn_new_vis_child
= CreateRectRgn( 0, 0, 0, 0 );
9224 HRGN hrgn_expect_child
= CreateRectRgn( 0, 0, 0, 0 );
9225 HRGN hrgn_actual_child
= CreateRectRgn( 0, 0, 0, 0 );
9227 BOOL is_composition_possible
, has_parentdc_anomaly
;
9228 WNDCLASSA parent_wc
;
9232 htoplevel
= CreateWindowExA( 0, "SimpleWindowClass", "Test toplevel", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9233 100, 100, 400, 400, 0, 0, 0, NULL
);
9234 ok( htoplevel
!= 0, "Failed to create top-level window: %lu\n", GetLastError() );
9235 base_style
= WS_CHILD
| WS_VISIBLE
;
9239 base_style
= WS_OVERLAPPEDWINDOW
| WS_VISIBLE
;
9242 ok( GetClassInfoA( GetModuleHandleA( NULL
), parent_class
, &parent_wc
),
9243 "GetClassInfoA failed\n" );
9245 is_composition_possible
= (base_style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
||
9246 (parent_wc
.style
& CS_PARENTDC
) == 0;
9248 has_parentdc_anomaly
= (base_style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
&&
9249 (parent_wc
.style
& CS_PARENTDC
) != 0;
9251 hparent
= CreateWindowExA( 0, parent_class
, "Test parent", base_style
,
9252 80, 80, 200, 200, htoplevel
, 0, 0, NULL
);
9253 ok( hparent
!= 0, "Creating parent window (%s) returned error %lu\n",
9254 debugstr_a( parent_class
), GetLastError() );
9256 hchild
= CreateWindowExA( 0, child_class
, "Test child", WS_CHILD
| WS_VISIBLE
| WS_BORDER
,
9257 rect_old
.left
, rect_old
.top
,
9258 rect_old
.right
- rect_old
.left
, rect_old
.bottom
- rect_old
.top
,
9259 hparent
, 0, 0, NULL
);
9260 ok( hchild
!= 0, "Creating child window (%s) returned error %lu\n",
9261 debugstr_a( child_class
), GetLastError() );
9263 hauxchild
= CreateWindowExA( 0, child_class
, "Auxiliary child for z order test", WS_CHILD
| WS_VISIBLE
,
9264 110, 0, 0, 0, hparent
, 0, 0, NULL
);
9265 ok( hauxchild
!= 0, "Creating child window (%s) returned error %lu\n",
9266 debugstr_a( child_class
), GetLastError() );
9268 for (i
= 0; i
< ARRAY_SIZE(exposure_tests
); i
++)
9270 const struct exposure_test
*extest
= &exposure_tests
[i
];
9271 BOOL has_ws_ex_composited
= (extest
->ex_style
& WS_EX_COMPOSITED
) != 0;
9272 BOOL is_composited
= is_composition_possible
&& has_ws_ex_composited
;
9273 BOOL is_zorder_redraw
= is_composited
&& extest
->shuffle_zorder
;
9276 winetest_push_context( "%d: SetWindowPos redraw #%Id (ex_style = %#x, style = %#x, shuffle_zorder = %d)",
9277 line
, i
, extest
->ex_style
, extest
->style
, extest
->shuffle_zorder
);
9279 SetWindowLongA( hparent
, GWL_EXSTYLE
, extest
->ex_style
);
9280 SetWindowLongA( hparent
, GWL_STYLE
, base_style
| extest
->style
);
9281 RedrawWindow( hparent
, NULL
, NULL
, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
9283 for (delta
= -20; delta
<= 0; delta
+= 20)
9285 RECT rect_old_vis
, rect_new
, rect_new_vis
;
9286 RECT rect_parent_clip
, rect_child_clip
;
9287 RECT rect_old_vis_child
, rect_new_vis_child
;
9290 winetest_push_context( "delta = %+d", delta
);
9292 SetWindowPos( hchild
, HWND_TOP
,
9295 rect_old
.right
- rect_old
.left
,
9296 rect_old
.bottom
- rect_old
.top
,
9299 rect_new
= rect_old
;
9300 OffsetRect( &rect_new
, delta
, delta
);
9302 rect_old_vis_child
= rect_old
;
9303 MapWindowPoints( hparent
, hchild
, (POINT
*)&rect_old_vis_child
, 2 );
9305 SetRectRgn( hrgn_actual
, 0, 0, 0, 0 );
9306 SetRectRgn( hrgn_actual_child
, 0, 0, 0, 0 );
9308 UpdateWindow( hparent
);
9311 if (extest
->shuffle_zorder
)
9313 /* bring sibling to top/bottom first so we can trigger z-order change */
9314 SetWindowPos( hauxchild
, HWND_TOP
, 0, 0, 0, 0,
9315 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
9318 SetWindowPos( hchild
, HWND_TOP
,
9321 rect_new
.right
- rect_new
.left
,
9322 rect_new
.bottom
- rect_new
.top
,
9324 (extest
->shuffle_zorder
? 0 : SWP_NOZORDER
) );
9326 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9327 "GetUpdateRgn on parentshall succeed\n" );
9328 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9329 "GetUpdateRgn on child shall succeed\n" );
9331 /* Compute parent window expose region */
9332 GetClientRect( hparent
, &rect_parent_clip
);
9333 IntersectRect( &rect_old_vis
, &rect_old
, &rect_parent_clip
);
9334 SetRectRgn( hrgn_old_vis
, rect_old_vis
.left
, rect_old_vis
.top
, rect_old_vis
.right
, rect_old_vis
.bottom
);
9335 IntersectRect( &rect_new_vis
, &rect_new
, &rect_parent_clip
);
9336 SetRectRgn( hrgn_new_vis
, rect_new_vis
.left
, rect_new_vis
.top
, rect_new_vis
.right
, rect_new_vis
.bottom
);
9338 if (!EqualRect( &rect_old
, &rect_new
) || is_zorder_redraw
)
9340 CombineRgn( hrgn_expect
, hrgn_old_vis
, hrgn_new_vis
, is_composited
? RGN_OR
: RGN_DIFF
);
9344 SetRectRgn( hrgn_expect
, 0, 0, 0, 0 );
9347 rgn_ok
= EqualRgn( hrgn_expect
, hrgn_actual
);
9348 if (!rgn_ok
&& broken( has_parentdc_anomaly
&& is_composited
/* Win7 */ ))
9350 if (winetest_debug
> 1)
9352 trace( "Forcing non-composited update region (broken)\n" );
9358 ok( !!rgn_ok
, "Parent update region shall match expected region\n" );
9363 trace( "Expected parent update region: " );
9364 dump_region( hrgn_expect
);
9365 trace( "Actual parent update region: " );
9366 dump_region( hrgn_actual
);
9367 trace( "Old child window visible area: %s\n", wine_dbgstr_rect( &rect_old_vis
) );
9368 trace( "New child window visible area: %s\n", wine_dbgstr_rect( &rect_new_vis
) );
9371 if (winetest_interactive
)
9375 visualize_region_differences( hparent
, hchild
, hrgn_expect
, hrgn_actual
);
9378 /* Let the position change be visible to the user */
9382 rect_new_vis_child
= rect_new
;
9383 MapWindowPoints( hparent
, hchild
, (POINT
*)&rect_new_vis_child
, 2 );
9385 /* Compute child window expose region */
9386 GetClientRect( hchild
, &rect_child_clip
);
9389 RECT rect_outer_clip
;
9390 GetClientRect( hparent
, &rect_outer_clip
);
9391 MapWindowPoints( hparent
, hchild
, (POINT
*)&rect_outer_clip
, 2 );
9392 IntersectRect( &rect_child_clip
, &rect_child_clip
, &rect_outer_clip
);
9394 IntersectRect( &rect_old_vis_child
, &rect_old_vis_child
, &rect_child_clip
);
9395 SetRectRgn( hrgn_old_vis_child
, rect_old_vis_child
.left
, rect_old_vis_child
.top
, rect_old_vis_child
.right
, rect_old_vis_child
.bottom
);
9396 IntersectRect( &rect_new_vis_child
, &rect_new_vis_child
, &rect_child_clip
);
9397 SetRectRgn( hrgn_new_vis_child
, rect_new_vis_child
.left
, rect_new_vis_child
.top
, rect_new_vis_child
.right
, rect_new_vis_child
.bottom
);
9399 if (!EqualRect( &rect_old
, &rect_new
) || is_zorder_redraw
)
9401 CombineRgn( hrgn_expect_child
, hrgn_new_vis_child
, hrgn_old_vis_child
, is_composited
? RGN_OR
: RGN_DIFF
);
9405 SetRectRgn( hrgn_expect_child
, 0, 0, 0, 0 );
9408 rgn_ok
= EqualRgn( hrgn_expect_child
, hrgn_actual_child
);
9409 if (!rgn_ok
&& broken( has_parentdc_anomaly
&& is_composited
/* Win7 */ ))
9411 if (winetest_debug
> 1)
9413 trace( "Forcing non-composited update region (broken)\n" );
9419 ok( !!rgn_ok
, "Child update region shall match expected region\n" );
9424 trace( "Expected child update region: " );
9425 dump_region( hrgn_expect_child
);
9426 trace( "Actual child update region: " );
9427 dump_region( hrgn_actual_child
);
9428 trace( "Old child window client visible area: %s\n", wine_dbgstr_rect( &rect_old_vis_child
) );
9429 trace( "New child window client visible area: %s\n", wine_dbgstr_rect( &rect_new_vis_child
) );
9432 if (winetest_interactive
)
9436 visualize_region_differences( hchild
, NULL
, hrgn_expect_child
, hrgn_actual_child
);
9439 /* Let the position change be visible to the user */
9443 winetest_pop_context();
9446 winetest_pop_context();
9449 DestroyWindow( hauxchild
);
9450 DestroyWindow( hchild
);
9451 DestroyWindow( hparent
);
9452 if (htoplevel
) DestroyWindow( htoplevel
);
9454 DeleteObject( hrgn_actual_child
);
9455 DeleteObject( hrgn_expect_child
);
9456 DeleteObject( hrgn_new_vis_child
);
9457 DeleteObject( hrgn_old_vis_child
);
9458 DeleteObject( hrgn_actual
);
9459 DeleteObject( hrgn_expect
);
9460 DeleteObject( hrgn_new_vis
);
9461 DeleteObject( hrgn_old_vis
);
9464 static void test_swp_paint_regions(void)
9466 subtest_swp_paint_regions( 1, "SimpleWindowClass", "SimpleWindowClass" );
9467 subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClass" );
9468 subtest_swp_paint_regions( 0, "SimpleWindowClass", "SimpleWindowClassWithParentDC" );
9469 subtest_swp_paint_regions( 0, "SimpleWindowClassWithParentDC", "SimpleWindowClass" );
9472 static void test_swp_paint_region_on_show(void)
9474 HRGN hrgn_actual_child
= CreateRectRgn( 0, 0, 0, 0 );
9475 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9476 const RECT rect_1
= { 10, 10, 100, 100 };
9477 const RECT rect_2
= { 20, 20, 120, 120 };
9478 RECT rect_expect_child
, rect_expect
;
9479 RECT rect_actual_child
, rect_actual
;
9480 HWND hparent
, hchild
;
9483 hparent
= CreateWindowExA( 0, "SimpleWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9484 80, 80, 200, 200, NULL
, 0, 0, NULL
);
9485 ok( hparent
!= 0, "Creating parent window returned error %lu\n", GetLastError() );
9487 hchild
= CreateWindowExA( 0, "SimpleWindowClass", "Test child", WS_CHILD
| WS_BORDER
,
9488 0, 0, 100, 100, hparent
, 0, 0, NULL
);
9489 ok( hchild
!= 0, "Creating child window returned error %lu\n", GetLastError() );
9491 if (winetest_debug
> 1) trace("testing show window (no move / size)\n");
9493 SetWindowPos( hchild
, HWND_TOP
,
9494 rect_1
.left
, rect_1
.top
, rect_1
.right
- rect_1
.left
, rect_1
.bottom
- rect_1
.top
,
9495 SWP_HIDEWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9497 UpdateWindow( hparent
);
9500 SetWindowPos( hchild
, HWND_TOP
, 0, 0, 0, 0,
9501 SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOMOVE
);
9503 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9504 "GetUpdateRgn on parent shall succeed\n" );
9505 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9506 "GetUpdateRgn on child shall succeed\n" );
9508 result
= GetRgnBox( hrgn_actual
, &rect_actual
);
9509 ok( result
== SIMPLEREGION
, "GetRgnBox (on parent) returned %d\n", result
);
9510 if (result
== COMPLEXREGION
) dump_region( hrgn_actual
);
9512 rect_expect
= rect_1
;
9513 ok( EqualRect( &rect_actual
, &rect_expect
), "parent update region: got %s, expected %s\n",
9514 wine_dbgstr_rect( &rect_actual
), wine_dbgstr_rect( &rect_expect
) );
9516 result
= GetRgnBox( hrgn_actual_child
, &rect_actual_child
);
9517 ok( result
== SIMPLEREGION
, "GetRgnBox (on child) returned %d\n", result
);
9518 if (result
== COMPLEXREGION
) dump_region( hrgn_actual_child
);
9520 ok( GetClientRect( hchild
, &rect_expect_child
), "GetClientRect failed\n" );
9521 ok( EqualRect( &rect_actual_child
, &rect_expect_child
), "child update region: got %s, expected %s\n",
9522 wine_dbgstr_rect( &rect_actual_child
), wine_dbgstr_rect( &rect_expect_child
) );
9524 if (winetest_debug
> 1) trace("testing show window (with move / resize)\n");
9526 SetWindowPos( hchild
, HWND_TOP
,
9527 rect_1
.left
, rect_1
.top
, rect_1
.right
- rect_1
.left
, rect_1
.bottom
- rect_1
.top
,
9528 SWP_HIDEWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9530 UpdateWindow( hparent
);
9533 SetWindowPos( hchild
, HWND_TOP
,
9536 rect_2
.right
- rect_2
.left
,
9537 rect_2
.bottom
- rect_2
.top
,
9538 SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
);
9540 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9541 "GetUpdateRgn on parent shall succeed\n" );
9542 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9543 "GetUpdateRgn on child shall succeed\n" );
9545 result
= GetRgnBox( hrgn_actual
, &rect_actual
);
9546 ok( result
== SIMPLEREGION
, "GetRgnBox (on parent) returned %d\n", result
);
9547 if (result
== COMPLEXREGION
) dump_region( hrgn_actual
);
9549 rect_expect
= rect_2
;
9550 ok( EqualRect( &rect_actual
, &rect_expect
), "parent update region: got %s, expected %s\n",
9551 wine_dbgstr_rect( &rect_actual
), wine_dbgstr_rect( &rect_expect
) );
9553 result
= GetRgnBox( hrgn_actual_child
, &rect_actual_child
);
9554 ok( result
== SIMPLEREGION
, "GetRgnBox (on child) returned %d\n", result
);
9555 if (result
== COMPLEXREGION
) dump_region( hrgn_actual_child
);
9557 ok( GetClientRect( hchild
, &rect_expect_child
), "GetClientRect failed\n" );
9558 ok( EqualRect( &rect_actual_child
, &rect_expect_child
), "child update region: got %s, expected %s\n",
9559 wine_dbgstr_rect( &rect_actual_child
), wine_dbgstr_rect( &rect_expect_child
) );
9561 DestroyWindow( hchild
);
9562 DestroyWindow( hparent
);
9563 DeleteObject( hrgn_actual_child
);
9564 DeleteObject( hrgn_actual
);
9567 static void test_swp_paint_region_on_extend_zerosize(void)
9569 HRGN hrgn_actual_child
= CreateRectRgn( 0, 0, 0, 0 );
9570 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9571 const RECT rect_1
= { 10, 10, 100, 100 };
9572 RECT rect_expect_child
, rect_expect
;
9573 RECT rect_actual_child
, rect_actual
;
9574 HWND hparent
, hchild
;
9577 hparent
= CreateWindowExA( 0, "SimpleWindowClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
9578 80, 80, 200, 200, NULL
, 0, 0, NULL
);
9579 ok( hparent
!= 0, "Creating parent window returned error %lu\n", GetLastError() );
9581 hchild
= CreateWindowExA( 0, "SimpleWindowClass", "Test child (no border)", WS_CHILD
| WS_VISIBLE
,
9582 10, 10, 0, 0, hparent
, 0, 0, NULL
);
9583 ok( hchild
!= 0, "Creating child window returned error %lu\n", GetLastError() );
9585 if (winetest_debug
> 1) trace("testing extending zero-size window\n");
9587 UpdateWindow( hparent
);
9590 SetWindowPos( hchild
, HWND_TOP
,
9593 rect_1
.right
- rect_1
.left
,
9594 rect_1
.bottom
- rect_1
.top
,
9595 SWP_NOACTIVATE
| SWP_NOZORDER
);
9597 ok( GetUpdateRgn( hparent
, hrgn_actual
, FALSE
) != ERROR
,
9598 "GetUpdateRgn on parent shall succeed\n" );
9599 ok( GetUpdateRgn( hchild
, hrgn_actual_child
, FALSE
) != ERROR
,
9600 "GetUpdateRgn on child shall succeed\n" );
9602 result
= GetRgnBox( hrgn_actual
, &rect_actual
);
9603 ok( result
== SIMPLEREGION
, "GetRgnBox (on parent) returned %d\n", result
);
9604 if (result
== COMPLEXREGION
) dump_region( hrgn_actual
);
9606 rect_expect
= rect_1
;
9607 ok( EqualRect( &rect_actual
, &rect_expect
), "parent update region: got %s, expected %s\n",
9608 wine_dbgstr_rect( &rect_actual
), wine_dbgstr_rect( &rect_expect
) );
9610 result
= GetRgnBox( hrgn_actual_child
, &rect_actual_child
);
9611 ok( result
== SIMPLEREGION
, "GetRgnBox (on child) returned %d\n", result
);
9612 if (result
== COMPLEXREGION
) dump_region( hrgn_actual_child
);
9614 ok( GetClientRect( hchild
, &rect_expect_child
), "GetClientRect failed\n" );
9615 ok( EqualRect( &rect_actual_child
, &rect_expect_child
), "child update region: got %s, expected %s\n",
9616 wine_dbgstr_rect( &rect_actual_child
), wine_dbgstr_rect( &rect_expect_child
) );
9618 DestroyWindow( hchild
);
9619 DestroyWindow( hparent
);
9620 DeleteObject( hrgn_actual_child
);
9621 DeleteObject( hrgn_actual
);
9624 static void subtest_hvredraw(HWND hparent
, UINT class_style
, DWORD style
)
9626 static const struct movesize_test
{
9628 } movesize_tests
[] = {
9637 HRGN hrgn_old_vis
= CreateRectRgn( 0, 0, 0, 0 );
9638 HRGN hrgn_new_vis
= CreateRectRgn( 0, 0, 0, 0 );
9639 HRGN hrgn_expect
= CreateRectRgn( 0, 0, 0, 0 );
9640 HRGN hrgn_actual
= CreateRectRgn( 0, 0, 0, 0 );
9641 const int x0
= 100, y0
= 100, w0
= 150, h0
= 150;
9645 .style
= class_style
,
9646 .lpfnWndProc
= DefWindowProcA
,
9647 .hInstance
= GetModuleHandleA(0),
9648 .hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
),
9649 .hbrBackground
= GetStockObject(WHITE_BRUSH
),
9650 .lpszClassName
= "TestHVRedrawClass"
9653 register_class(&cls
);
9655 hwnd
= CreateWindowExA( 0, cls
.lpszClassName
, "Test window", style
, x0
, y0
, w0
, h0
, hparent
, 0, 0, NULL
);
9656 ok(hwnd
!= NULL
, "Failed to create the window\n");
9658 ShowWindow( hwnd
, SW_SHOW
);
9659 UpdateWindow( hwnd
);
9661 for (i
= 0; i
< ARRAY_SIZE(movesize_tests
); i
++)
9663 const struct movesize_test
*test
= &movesize_tests
[i
];
9664 int is_redraw
= (test
->dw
!= 0 && (class_style
& CS_HREDRAW
)) ||
9665 (test
->dh
!= 0 && (class_style
& CS_VREDRAW
));
9666 RECT rect_old_vis
, rect_new_vis
;
9669 winetest_push_context( "%x %08lx SetWindowPos redraw #%Id (%d, %d, %d, %d)",
9670 class_style
, style
, i
, test
->dx
, test
->dy
, test
->dw
, test
->dh
);
9672 SetWindowPos( hwnd
, HWND_TOP
, x0
, y0
, w0
, h0
, SWP_NOACTIVATE
);
9674 GetClientRect( hwnd
, &rect_old_vis
);
9675 SetRectRgn( hrgn_old_vis
, rect_old_vis
.left
, rect_old_vis
.top
, rect_old_vis
.right
, rect_old_vis
.bottom
);
9677 UpdateWindow( hparent
);
9680 SetWindowPos( hwnd
, HWND_TOP
,
9681 x0
+ test
->dx
, y0
+ test
->dy
,
9682 w0
+ test
->dw
, h0
+ test
->dh
, SWP_NOACTIVATE
);
9683 ok( GetUpdateRgn( hwnd
, hrgn_actual
, FALSE
) != ERROR
, "GetUpdateRgn shall succeed\n" );
9685 GetClientRect( hwnd
, &rect_new_vis
);
9686 SetRectRgn( hrgn_new_vis
, rect_new_vis
.left
, rect_new_vis
.top
, rect_new_vis
.right
, rect_new_vis
.bottom
);
9687 CombineRgn( hrgn_expect
, hrgn_new_vis
, hrgn_old_vis
, is_redraw
? RGN_COPY
: RGN_DIFF
);
9689 rgn_ok
= EqualRgn( hrgn_expect
, hrgn_actual
);
9690 ok( !!rgn_ok
, "Update region shall match expected region\n" );
9694 trace( "Expected update region: " );
9695 dump_region( hrgn_expect
);
9696 trace( "Actual update region: " );
9697 dump_region( hrgn_actual
);
9698 trace( "Old window visible area: %s\n", wine_dbgstr_rect( &rect_old_vis
) );
9699 trace( "New window visible area: %s\n", wine_dbgstr_rect( &rect_new_vis
) );
9702 if (winetest_interactive
)
9706 visualize_region_differences( hwnd
, NULL
, hrgn_expect
, hrgn_actual
);
9709 /* Let the position change be visible to the user */
9713 winetest_pop_context();
9716 DestroyWindow( hwnd
);
9717 DeleteObject( hrgn_actual
);
9718 DeleteObject( hrgn_expect
);
9719 DeleteObject( hrgn_new_vis
);
9720 DeleteObject( hrgn_old_vis
);
9721 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
9725 static void test_hvredraw(void)
9729 subtest_hvredraw( NULL
, CS_HREDRAW
, WS_OVERLAPPEDWINDOW
);
9730 subtest_hvredraw( NULL
, CS_VREDRAW
, WS_OVERLAPPEDWINDOW
);
9731 subtest_hvredraw( NULL
, CS_HREDRAW
|CS_VREDRAW
, WS_OVERLAPPEDWINDOW
);
9733 htoplevel
= CreateWindowExA( 0, "SimpleWindowClass", "Test toplevel",
9734 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_VISIBLE
,
9735 100, 100, 400, 400, 0, 0, 0, NULL
);
9736 ok( htoplevel
!= 0, "Failed to create top-level window: %lu\n", GetLastError() );
9738 subtest_hvredraw( htoplevel
, CS_HREDRAW
, WS_CHILD
| WS_BORDER
);
9739 subtest_hvredraw( htoplevel
, CS_VREDRAW
, WS_CHILD
| WS_BORDER
);
9740 subtest_hvredraw( htoplevel
, CS_HREDRAW
|CS_VREDRAW
, WS_CHILD
| WS_BORDER
);
9742 DestroyWindow( htoplevel
);
9745 struct run_in_temp_desktop_args
9750 void (*test_func
)(void);
9753 static DWORD WINAPI
run_in_temp_desktop_thread_func(LPVOID param
)
9755 HDESK prev_thr_desktop
, prev_inp_desktop
, post_inp_desktop
, temp_desktop
;
9756 char temp_desktop_name
[1024], curr_desktop_name
[1024];
9757 struct run_in_temp_desktop_args
*args
= param
;
9758 const char *file
= args
->file
;
9759 int line
= args
->line
;
9764 result
= QueryPerformanceCounter( &qpc
);
9765 ok_(file
, line
)( result
, "QueryPerformanceCounter error %lu\n", GetLastError() );
9768 * Temporary desktops from previous runs may leak due to a Windows bug.
9769 * Generate a unique name that is unlikely to collide with previous runs.
9771 result
= snprintf( temp_desktop_name
, ARRAY_SIZE(temp_desktop_name
),
9772 "WineTest-%08lX-%08lX-%08lX%08lX-%s",
9773 GetCurrentProcessId(), GetCurrentThreadId(),
9774 qpc
.HighPart
, qpc
.LowPart
, args
->name
);
9775 ok_(file
, line
)( result
> 0 && result
< ARRAY_SIZE(temp_desktop_name
),
9776 "sprintf returned %d (out of memory, or name too long?)\n", result
);
9778 if (winetest_debug
> 1)
9779 trace_(file
, line
)( "creating desktop: %s\n", debugstr_a( temp_desktop_name
) );
9781 temp_desktop
= CreateDesktopA( temp_desktop_name
, NULL
, NULL
, 0, GENERIC_ALL
, NULL
);
9782 ok_(file
, line
)( temp_desktop
!= NULL
, "CreateDesktopA(%s, ..) error %lu\n",
9783 debugstr_a( temp_desktop_name
), GetLastError() );
9785 prev_inp_desktop
= OpenInputDesktop( 0, FALSE
, DESKTOP_SWITCHDESKTOP
);
9786 ok_(file
, line
)( prev_inp_desktop
!= NULL
, "OpenInputDesktop [prev] error %lu\n", GetLastError() );
9788 if (winetest_debug
> 1)
9789 trace_(file
, line
)( "sanity check: no concurrent WineTest desktop\n" );
9792 * Check if the desktop has not been properly restored. This is done to
9793 * avoid any possible hard-to-debug failures due to unexpected desktop.
9795 result
= GetUserObjectInformationA( prev_inp_desktop
, UOI_NAME
,
9796 curr_desktop_name
, sizeof(curr_desktop_name
), &length
);
9797 ok_(file
, line
)( result
, "GetUserObjectInformationA error %lu [rl = %lu]\n",
9798 GetLastError(), length
);
9799 ok_(file
, line
)( _strnicmp( curr_desktop_name
, temp_desktop_name
, 8 ) != 0,
9800 "unexpected input desktop name %s (concurrent WineTest run?)\n",
9801 debugstr_a( curr_desktop_name
) );
9803 if (winetest_debug
> 1)
9804 trace_(file
, line
)( "switching desktop to: %s (%p)\n", debugstr_a( temp_desktop_name
), temp_desktop
);
9806 result
= SwitchDesktop( temp_desktop
);
9807 ok_(file
, line
)( result
, "SwitchDesktop(temp_desktop=%p) error %lu\n",
9808 temp_desktop
, GetLastError() );
9810 prev_thr_desktop
= GetThreadDesktop( GetCurrentThreadId() );
9811 ok_(file
, line
)( prev_thr_desktop
!= NULL
, "GetThreadDesktop error %lu\n", GetLastError() );
9813 result
= SetThreadDesktop( temp_desktop
);
9814 ok_(file
, line
)( result
, "SetThreadDesktop(temp_desktop=%p) error %lu\n",
9815 temp_desktop
, GetLastError() );
9817 if (winetest_debug
> 1)
9818 trace_(file
, line
)( "running test function %s()\n", args
->name
);
9822 if (winetest_debug
> 1)
9823 trace_(file
, line
)( "sanity check: input desktop has not been changed\n" );
9826 * Check if the input desktop has been tampered with. This is done to
9827 * avoid any possible hard-to-debug failures due to unexpected desktop.
9829 post_inp_desktop
= OpenInputDesktop( 0, FALSE
, DESKTOP_ENUMERATE
);
9830 ok_(file
, line
)( post_inp_desktop
!= NULL
, "OpenInputDesktop [post] error %lu\n", GetLastError() );
9832 result
= GetUserObjectInformationA( post_inp_desktop
, UOI_NAME
,
9833 curr_desktop_name
, sizeof(curr_desktop_name
), &length
);
9834 ok_(file
, line
)( result
, "GetUserObjectInformationA(post_inp_desktop=%p) error %lu [rl = %lu]\n",
9835 post_inp_desktop
, GetLastError(), length
);
9836 ok_(file
, line
)( strcmp( curr_desktop_name
, temp_desktop_name
) == 0,
9837 "different desktop name: %s != %s (no switch or concurrent WineTest run?)\n",
9838 debugstr_a( curr_desktop_name
), debugstr_a( temp_desktop_name
) );
9840 result
= CloseDesktop( post_inp_desktop
);
9841 ok_(file
, line
)( result
, "CloseDesktop(post_inp_desktop=%p) error %lu\n",
9842 post_inp_desktop
, GetLastError() );
9844 if (winetest_debug
> 1)
9845 trace_(file
, line
)( "restoring previous desktop\n" );
9847 result
= SetThreadDesktop( prev_thr_desktop
);
9848 ok_(file
, line
)( result
|| broken( GetLastError() == ERROR_BUSY
) /* == W10 */,
9849 "SetThreadDesktop(prev_thr_desktop=%p) error %lu\n",
9850 prev_thr_desktop
, GetLastError() );
9852 result
= SwitchDesktop( prev_inp_desktop
);
9853 ok_(file
, line
)( result
, "SwitchDesktop(prev_inp_desktop=%p) error %lu\n",
9854 prev_inp_desktop
, GetLastError() );
9856 result
= CloseDesktop( prev_inp_desktop
);
9857 ok_(file
, line
)( result
, "CloseDesktop(prev_inp_desktop=%p) error %lu\n",
9858 prev_inp_desktop
, GetLastError() );
9860 if (winetest_debug
> 1)
9861 trace_(file
, line
)( "closing desktop: %s (%p)\n", debugstr_a( temp_desktop_name
), temp_desktop
);
9863 result
= CloseDesktop( temp_desktop
);
9864 ok_(file
, line
)( result
|| broken( GetLastError() == ERROR_BUSY
) /* == W10 */,
9865 "CloseDesktop(temp_desktop=%p) error %lu\n",
9866 temp_desktop
, GetLastError() );
9871 #define run_in_temp_desktop(f) run_in_temp_desktop_(__FILE__, __LINE__, #f, f)
9872 static void run_in_temp_desktop_(const char *file
, int line
, const char *name
, void (*test_func
)(void))
9874 struct run_in_temp_desktop_args args
;
9881 args
.test_func
= test_func
;
9883 thread
= CreateThread( NULL
, 0, run_in_temp_desktop_thread_func
, &args
, 0, NULL
);
9884 ok_(file
, line
)( thread
!= NULL
, "CreateThread error %lu\n", GetLastError() );
9886 result
= WaitForSingleObject( thread
, INFINITE
);
9887 ok_(file
, line
)( result
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lu, error %lu\n",
9888 result
, GetLastError() );
9890 CloseHandle( thread
);
9899 HANDLE getmessage_complete
;
9902 static DWORD WINAPI
thread_proc(void *param
)
9905 struct wnd_event
*wnd_event
= param
;
9907 wnd_event
->hwnd
= CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW
,
9908 100, 100, 200, 200, 0, 0, 0, NULL
);
9909 ok(wnd_event
->hwnd
!= 0, "Failed to create overlapped window\n");
9911 SetEvent(wnd_event
->start_event
);
9913 while (GetMessageA(&msg
, 0, 0, 0))
9915 TranslateMessage(&msg
);
9916 DispatchMessageA(&msg
);
9919 ok(IsWindow(wnd_event
->hwnd
), "window should still exist\n");
9924 static DWORD CALLBACK
create_grand_child_thread( void *param
)
9926 struct wnd_event
*wnd_event
= param
;
9930 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
9931 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
9932 ok (hchild
!= 0, "Failed to create child window\n");
9935 SetEvent( wnd_event
->start_event
);
9939 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 1000, QS_ALLINPUT
);
9940 if (!IsWindow( hchild
)) break; /* will be destroyed when parent thread exits */
9941 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9946 static DWORD CALLBACK
create_child_thread( void *param
)
9948 struct wnd_event
*wnd_event
= param
;
9949 struct wnd_event child_event
;
9953 child_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", "Test child",
9954 WS_CHILD
| WS_VISIBLE
, 0, 0, 10, 10, wnd_event
->hwnd
, 0, 0, NULL
);
9955 ok (child_event
.hwnd
!= 0, "Failed to create child window\n");
9956 SetFocus( child_event
.hwnd
);
9959 child_event
.start_event
= wnd_event
->start_event
;
9960 wnd_event
->grand_child
= CreateThread(NULL
, 0, create_grand_child_thread
, &child_event
, 0, &tid
);
9963 DWORD ret
= MsgWaitForMultipleObjects(1, &child_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
9964 if (ret
!= 1) break;
9965 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
9967 ret
= WaitForSingleObject( wnd_event
->stop_event
, 5000 );
9968 ok( !ret
, "WaitForSingleObject failed %lx\n", ret
);
9972 static const char manifest_dep
[] =
9973 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
9974 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
9975 " <file name=\"testdep.dll\" />"
9978 static const char manifest_main
[] =
9979 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
9980 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
9982 " <dependentAssembly>"
9983 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
9984 " </dependentAssembly>"
9988 static void create_manifest_file(const char *filename
, const char *manifest
)
9990 WCHAR path
[MAX_PATH
];
9994 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
9995 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
9996 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError());
9997 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
10001 static HANDLE
test_create(const char *file
)
10003 WCHAR path
[MAX_PATH
];
10007 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
10008 memset(&actctx
, 0, sizeof(ACTCTXW
));
10009 actctx
.cbSize
= sizeof(ACTCTXW
);
10010 actctx
.lpSource
= path
;
10012 handle
= CreateActCtxW(&actctx
);
10013 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %lu\n", GetLastError());
10015 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%ld\n", actctx
.cbSize
);
10016 ok(actctx
.dwFlags
== 0, "dwFlags=%ld\n", actctx
.dwFlags
);
10017 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
10018 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
10019 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
10020 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
10021 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
10022 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
10023 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
10028 static void test_interthread_messages(void)
10030 HANDLE hThread
, context
, handle
, event
;
10036 int len
, expected_len
;
10037 struct wnd_event wnd_event
;
10040 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
10041 if (!wnd_event
.start_event
)
10043 win_skip("skipping interthread message test under win9x\n");
10047 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
10048 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
10050 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10052 CloseHandle(wnd_event
.start_event
);
10054 SetLastError(0xdeadbeef);
10055 ok(!DestroyWindow(wnd_event
.hwnd
), "DestroyWindow succeeded\n");
10056 ok(GetLastError() == ERROR_ACCESS_DENIED
|| GetLastError() == 0xdeadbeef,
10057 "wrong error code %ld\n", GetLastError());
10059 proc
= (WNDPROC
)GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
10060 ok(proc
!= NULL
, "GetWindowLongPtrA(GWLP_WNDPROC) error %ld\n", GetLastError());
10062 expected_len
= lstrlenA("window caption text");
10063 memset(buf
, 0, sizeof(buf
));
10064 SetLastError(0xdeadbeef);
10065 len
= CallWindowProcA(proc
, wnd_event
.hwnd
, WM_GETTEXT
, sizeof(buf
), (LPARAM
)buf
);
10066 ok(len
== expected_len
, "CallWindowProcA(WM_GETTEXT) error %ld, len %d, expected len %d\n", GetLastError(), len
, expected_len
);
10067 ok(!lstrcmpA(buf
, "window caption text"), "window text mismatch\n");
10069 msg
.hwnd
= wnd_event
.hwnd
;
10070 msg
.message
= WM_GETTEXT
;
10071 msg
.wParam
= sizeof(buf
);
10072 msg
.lParam
= (LPARAM
)buf
;
10073 memset(buf
, 0, sizeof(buf
));
10074 SetLastError(0xdeadbeef);
10075 len
= DispatchMessageA(&msg
);
10076 ok((!len
&& GetLastError() == ERROR_MESSAGE_SYNC_ONLY
) || broken(len
), /* nt4 */
10077 "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %ld\n", len
, GetLastError());
10079 /* the following test causes an exception in user.exe under win9x */
10080 msg
.hwnd
= wnd_event
.hwnd
;
10081 msg
.message
= WM_TIMER
;
10083 msg
.lParam
= GetWindowLongPtrA(wnd_event
.hwnd
, GWLP_WNDPROC
);
10084 SetLastError(0xdeadbeef);
10085 len
= DispatchMessageA(&msg
);
10086 ok(!len
&& GetLastError() == 0xdeadbeef,
10087 "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %ld\n", len
, GetLastError());
10089 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
10090 ok( ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
10092 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10093 CloseHandle(hThread
);
10095 ok(!IsWindow(wnd_event
.hwnd
), "window should be destroyed on thread exit\n");
10097 wnd_event
.hwnd
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
10098 100, 100, 200, 200, 0, 0, 0, NULL
);
10099 ok (wnd_event
.hwnd
!= 0, "Failed to create parent window\n");
10102 log_all_parent_messages
++;
10103 wnd_event
.start_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
10104 wnd_event
.stop_event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
10105 hThread
= CreateThread( NULL
, 0, create_child_thread
, &wnd_event
, 0, &tid
);
10108 ret
= MsgWaitForMultipleObjects(1, &wnd_event
.start_event
, FALSE
, 1000, QS_SENDMESSAGE
);
10109 if (ret
!= 1) break;
10110 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
10112 ok( !ret
, "MsgWaitForMultipleObjects failed %x\n", ret
);
10113 /* now wait for the thread without processing messages; this shouldn't deadlock */
10114 SetEvent( wnd_event
.stop_event
);
10115 ret
= WaitForSingleObject( hThread
, 5000 );
10116 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
10117 CloseHandle( hThread
);
10119 ret
= WaitForSingleObject( wnd_event
.grand_child
, 5000 );
10120 ok( !ret
, "WaitForSingleObject failed %x\n", ret
);
10121 CloseHandle( wnd_event
.grand_child
);
10123 CloseHandle( wnd_event
.start_event
);
10124 CloseHandle( wnd_event
.stop_event
);
10126 ok_sequence(WmExitThreadSeq
, "destroy child on thread exit", FALSE
);
10127 log_all_parent_messages
--;
10128 DestroyWindow( wnd_event
.hwnd
);
10130 /* Activation context tests */
10131 create_manifest_file("testdep1.manifest", manifest_dep
);
10132 create_manifest_file("main.manifest", manifest_main
);
10134 context
= test_create("main.manifest");
10135 DeleteFileA("testdep1.manifest");
10136 DeleteFileA("main.manifest");
10138 handle
= (void*)0xdeadbeef;
10139 ret
= GetCurrentActCtx(&handle
);
10140 ok(ret
, "GetCurrentActCtx failed: %lu\n", GetLastError());
10141 ok(handle
== 0, "active context %p\n", handle
);
10143 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
10144 hThread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
10145 ok(hThread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
10146 ok(WaitForSingleObject(wnd_event
.start_event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10147 CloseHandle(wnd_event
.start_event
);
10149 /* context is activated after thread creation, so it doesn't inherit it by default */
10150 ret
= ActivateActCtx(context
, &cookie
);
10151 ok(ret
, "activation failed: %lu\n", GetLastError());
10154 ret
= GetCurrentActCtx(&handle
);
10155 ok(ret
, "GetCurrentActCtx failed: %lu\n", GetLastError());
10156 ok(handle
!= 0, "active context %p\n", handle
);
10157 ReleaseActCtx(handle
);
10159 /* destination window will test for active context */
10160 ret
= SendMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, 0);
10161 ok(ret
, "thread window returned %d\n", ret
);
10163 event
= CreateEventW(NULL
, 0, 0, NULL
);
10164 ret
= PostMessageA(wnd_event
.hwnd
, WM_USER
+10, 0, (LPARAM
)event
);
10165 ok(ret
, "thread window returned %d\n", ret
);
10166 ok(WaitForSingleObject(event
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10167 CloseHandle(event
);
10169 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
10170 ok(ret
, "PostMessageA(WM_QUIT) error %ld\n", GetLastError());
10172 ok(WaitForSingleObject(hThread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
10173 CloseHandle(hThread
);
10175 ret
= DeactivateActCtx(0, cookie
);
10176 ok(ret
, "DeactivateActCtx failed: %lu\n", GetLastError());
10177 ReleaseActCtx(context
);
10181 static const struct message WmVkN
[] = {
10182 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10183 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10184 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
10185 { WM_CHAR
, wparam
|lparam
, 'n', 1 },
10186 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1002,1), 0 },
10187 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10188 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10189 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10192 static const struct message WmShiftVkN
[] = {
10193 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10194 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10195 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
10196 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10197 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10198 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
10199 { WM_CHAR
, wparam
|lparam
, 'N', 1 },
10200 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1001,1), 0 },
10201 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10202 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10203 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10204 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
10205 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10206 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10209 static const struct message WmCtrlVkN
[] = {
10210 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10211 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10212 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10213 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10214 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10215 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 1 },
10216 { WM_CHAR
, wparam
|lparam
, 0x000e, 1 },
10217 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
10218 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10219 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10220 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10221 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10222 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10223 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10226 static const struct message WmCtrlVkN_2
[] = {
10227 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10228 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10229 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10230 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10231 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10232 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1000,1), 0 },
10233 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10234 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10235 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10236 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10237 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10238 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10241 static const struct message WmAltVkN
[] = {
10242 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10243 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10244 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10245 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10246 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10247 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
10248 { WM_SYSCHAR
, wparam
|lparam
, 'n', 0x20000001 },
10249 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'n', 0x20000001 },
10250 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 'n' },
10251 { HCBT_SYSCOMMAND
, hook
},
10252 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10253 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
10254 { 0x00AE, sent
|defwinproc
|optional
}, /* XP */
10255 { WM_GETTEXT
, sent
|defwinproc
|optional
}, /* XP */
10256 { WM_INITMENU
, sent
|defwinproc
},
10257 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10258 { WM_MENUCHAR
, sent
|defwinproc
|wparam
, MAKEWPARAM('n',MF_SYSMENU
) },
10259 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
10260 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10261 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,0xffff) },
10262 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10263 { WM_EXITMENULOOP
, sent
|defwinproc
},
10264 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) }, /* Win95 bug */
10265 { WM_EXITMENULOOP
, sent
|defwinproc
|optional
}, /* Win95 bug */
10266 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10267 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10268 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10269 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10270 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10271 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10274 static const struct message WmAltVkN_2
[] = {
10275 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10276 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10277 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10278 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10279 { WM_SYSKEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10280 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1003,1), 0 },
10281 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10282 { WM_SYSKEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10283 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10284 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10285 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10286 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10289 static const struct message WmCtrlAltVkN
[] = {
10290 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10291 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10292 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10293 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10294 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10295 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10296 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10297 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10298 { WM_KEYDOWN
, sent
|wparam
|lparam
, 'N', 0x20000001 },
10299 { WM_CHAR
, optional
},
10300 { WM_CHAR
, sent
|optional
},
10301 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10302 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10303 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10304 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10305 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10306 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10307 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10308 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10309 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10312 static const struct message WmCtrlShiftVkN
[] = {
10313 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10314 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10315 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10316 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10317 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10318 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
10319 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
10320 { WM_KEYDOWN
, wparam
|lparam
, 'N', 1 },
10321 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1004,1), 0 },
10322 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
10323 { WM_KEYUP
, wparam
|lparam
, 'N', 0xc0000001 },
10324 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xc0000001 },
10325 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
10326 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10327 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10328 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10329 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10330 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10333 static const struct message WmCtrlAltShiftVkN
[] = {
10334 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 1 }, /* XP */
10335 { WM_KEYDOWN
, wparam
|lparam
, VK_CONTROL
, 1 },
10336 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_CONTROL
, 1 },
10337 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10338 { WM_KEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10339 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10340 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0x20000001 }, /* XP */
10341 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 0x20000001 },
10342 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x20000001 },
10343 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x20000001 }, /* XP */
10344 { WM_KEYDOWN
, wparam
|lparam
, 'N', 0x20000001 },
10345 { WM_COMMAND
, sent
|wparam
|lparam
, MAKEWPARAM(1005,1), 0 },
10346 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xe0000001 }, /* XP */
10347 { WM_KEYUP
, wparam
|lparam
, 'N', 0xe0000001 },
10348 { WM_KEYUP
, sent
|wparam
|lparam
, 'N', 0xe0000001 },
10349 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xe0000001 }, /* XP */
10350 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
10351 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xe0000001 },
10352 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10353 { WM_KEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10354 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10355 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_CONTROL
, 0xc0000001 }, /* XP */
10356 { WM_KEYUP
, wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10357 { WM_KEYUP
, sent
|wparam
|lparam
, VK_CONTROL
, 0xc0000001 },
10360 static const struct message WmAltPressRelease
[] = {
10361 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 }, /* XP */
10362 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_MENU
, 0x20000001 },
10363 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
10364 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10365 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10366 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10367 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
|lparam
, SC_KEYMENU
, 0 },
10368 { HCBT_SYSCOMMAND
, hook
},
10369 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10370 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
10371 { WM_INITMENU
, sent
|defwinproc
},
10372 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10373 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
10374 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 1 },
10376 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x30000001 }, /* XP */
10378 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10379 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0, },
10380 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10381 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
10382 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10383 { WM_EXITMENULOOP
, sent
|defwinproc
},
10384 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 }, /* XP */
10385 { WM_SYSKEYUP
, wparam
|lparam
, VK_MENU
, 0xc0000001 },
10386 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
10389 static const struct message WmShiftMouseButton
[] = {
10390 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10391 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10392 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 1 },
10393 { WM_MOUSEMOVE
, wparam
|optional
, 0, 0 },
10394 { WM_MOUSEMOVE
, sent
|wparam
|optional
, 0, 0 },
10395 { WM_LBUTTONDOWN
, wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
10396 { WM_LBUTTONDOWN
, sent
|wparam
, MK_LBUTTON
|MK_SHIFT
, 0 },
10397 { WM_LBUTTONUP
, wparam
|optional
, MK_SHIFT
, 0 }, /* < w1064v1809 */
10398 { WM_LBUTTONUP
, sent
|wparam
|optional
, MK_SHIFT
, 0 }, /* < w1064v1809 */
10399 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xc0000001 }, /* XP */
10400 { WM_KEYUP
, wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10401 { WM_KEYUP
, sent
|wparam
|lparam
, VK_SHIFT
, 0xc0000001 },
10402 { WM_LBUTTONUP
, optional
, 0, 0 }, /* >= w1064v1809 */
10403 { WM_LBUTTONUP
, sent
|optional
, 0, 0 }, /* >= w1064v1809 */
10406 static const struct message WmF1Seq
[] = {
10407 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 1 }, /* XP */
10408 { WM_KEYDOWN
, wparam
|lparam
, VK_F1
, 1 },
10409 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_F1
, 0x00000001 },
10410 { WM_KEYF1
, wparam
|lparam
, 0, 0 },
10411 { WM_KEYF1
, sent
|wparam
|lparam
, 0, 0 },
10412 { WM_HELP
, sent
|defwinproc
},
10413 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F1
, 0xc0000001 }, /* XP */
10414 { WM_KEYUP
, wparam
|lparam
, VK_F1
, 0xc0000001 },
10415 { WM_KEYUP
, sent
|wparam
|lparam
, VK_F1
, 0xc0000001 },
10418 static const struct message WmVkAppsSeq
[] = {
10419 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 1 }, /* XP */
10420 { WM_KEYDOWN
, wparam
|lparam
, VK_APPS
, 1 },
10421 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_APPS
, 0x00000001 },
10422 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_APPS
, 0xc0000001 }, /* XP */
10423 { WM_KEYUP
, wparam
|lparam
, VK_APPS
, 0xc0000001 },
10424 { WM_KEYUP
, sent
|wparam
|lparam
, VK_APPS
, 0xc0000001 },
10425 { WM_CONTEXTMENU
, lparam
, /*hwnd*/0, -1 },
10426 { WM_CONTEXTMENU
, sent
|lparam
, /*hwnd*/0, -1 },
10429 static const struct message WmVkF10Seq
[] = {
10430 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
10431 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
10432 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
10433 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
10434 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
10435 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
10436 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
10437 { HCBT_SYSCOMMAND
, hook
},
10438 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10439 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
10440 { WM_INITMENU
, sent
|defwinproc
},
10441 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10442 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
10443 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 1 },
10445 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0x10000001 }, /* XP */
10447 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
10448 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10449 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0, },
10450 { WM_CAPTURECHANGED
, sent
|defwinproc
},
10451 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|optional
, MAKEWPARAM(0,0xffff) },
10452 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10453 { WM_EXITMENULOOP
, sent
|defwinproc
},
10454 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
10455 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
10456 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
10459 static const struct message WmShiftF10Seq
[] = {
10460 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 1 }, /* XP */
10461 { WM_KEYDOWN
, wparam
|lparam
, VK_SHIFT
, 1 },
10462 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_SHIFT
, 0x00000001 },
10463 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 1 }, /* XP */
10464 { WM_SYSKEYDOWN
, wparam
|lparam
, VK_F10
, 1 },
10465 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_F10
, 0x00000001 },
10466 { WM_CONTEXTMENU
, sent
|defwinproc
|lparam
, /*hwnd*/0, -1 },
10467 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_F10
, 0xc0000001 }, /* XP */
10468 { WM_SYSKEYUP
, wparam
|lparam
, VK_F10
, 0xc0000001 },
10469 { WM_SYSKEYUP
, sent
|wparam
|lparam
, VK_F10
, 0xc0000001 },
10470 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_KEYMENU
},
10471 { HCBT_SYSCOMMAND
, hook
},
10472 { WM_ENTERMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10473 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
10474 { WM_INITMENU
, sent
|defwinproc
},
10475 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10476 { WM_MENUSELECT
, sent
|defwinproc
|wparam
, MAKEWPARAM(0,MF_SYSMENU
|MF_POPUP
|MF_HILITE
), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY
) },
10477 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 1 },
10478 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_SHIFT
, 0xd0000001 }, /* XP */
10479 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0x10000001 }, /* XP */
10480 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10481 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
10482 { WM_CAPTURECHANGED
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10483 { WM_MENUSELECT
, sent
|defwinproc
|wparam
|lparam
, 0xffff0000, 0 },
10484 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_SYSMENU
, 0 },
10485 { WM_EXITMENULOOP
, sent
|defwinproc
|wparam
|lparam
, 0, 0 },
10486 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 }, /* XP */
10487 { WM_KEYUP
, wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
10488 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
10492 static void pump_msg_loop(HWND hwnd
, HACCEL hAccel
)
10496 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
10498 struct recvd_message log_msg
;
10500 /* ignore some unwanted messages */
10501 if (msg
.message
== WM_MOUSEMOVE
||
10502 msg
.message
== WM_TIMER
||
10503 ignore_message( msg
.message
))
10506 log_msg
.hwnd
= msg
.hwnd
;
10507 log_msg
.message
= msg
.message
;
10508 log_msg
.flags
= wparam
|lparam
;
10509 log_msg
.wParam
= msg
.wParam
;
10510 log_msg
.lParam
= msg
.lParam
;
10511 log_msg
.descr
= "accel";
10512 add_message(&log_msg
);
10514 if (!hAccel
|| !TranslateAcceleratorA(hwnd
, hAccel
, &msg
))
10516 TranslateMessage(&msg
);
10517 DispatchMessageA(&msg
);
10522 static void test_accelerators(void)
10528 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
10529 100, 100, 200, 200, 0, 0, 0, NULL
);
10530 BOOL us_kbd
= (GetKeyboardLayout(0) == (HKL
)(ULONG_PTR
)0x04090409);
10533 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
10534 UpdateWindow(hwnd
);
10539 ok(GetFocus() == hwnd
, "wrong focus window %p\n", GetFocus());
10541 state
= GetKeyState(VK_SHIFT
);
10542 ok(!(state
& 0x8000), "wrong Shift state %04x\n", state
);
10543 state
= GetKeyState(VK_CAPITAL
);
10544 ok(state
== 0, "wrong CapsLock state %04x\n", state
);
10546 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
10547 ok(!!hAccel
, "Failed to load accelerators, error %lu.\n", GetLastError());
10550 pump_msg_loop(hwnd
, 0);
10555 skip("skipping ascii VK events on non-us keyboard\n");
10559 if (winetest_debug
> 1) trace("testing VK_N press/release\n");
10561 keybd_event('N', 0, 0, 0);
10562 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10563 pump_msg_loop(hwnd
, hAccel
);
10564 if (!sequence_cnt
) /* we didn't get any message */
10566 skip( "queuing key events not supported\n" );
10569 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
10571 if (winetest_debug
> 1) trace("testing Shift+VK_N press/release\n");
10573 keybd_event(VK_SHIFT
, 0, 0, 0);
10574 keybd_event('N', 0, 0, 0);
10575 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10576 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10577 pump_msg_loop(hwnd
, hAccel
);
10578 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
10580 if (winetest_debug
> 1) trace("testing Ctrl+VK_N press/release\n");
10582 keybd_event(VK_CONTROL
, 0, 0, 0);
10583 keybd_event('N', 0, 0, 0);
10584 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10585 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10586 pump_msg_loop(hwnd
, hAccel
);
10587 ok_sequence(WmCtrlVkN
, "Ctrl+VK_N press/release", FALSE
);
10589 if (winetest_debug
> 1) trace("testing Alt+VK_N press/release\n");
10591 keybd_event(VK_MENU
, 0, 0, 0);
10592 keybd_event('N', 0, 0, 0);
10593 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10594 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10595 pump_msg_loop(hwnd
, hAccel
);
10596 ok_sequence(WmAltVkN
, "Alt+VK_N press/release", FALSE
);
10598 if (winetest_debug
> 1) trace("testing Ctrl+Alt+VK_N press/release 1\n");
10600 keybd_event(VK_CONTROL
, 0, 0, 0);
10601 keybd_event(VK_MENU
, 0, 0, 0);
10602 keybd_event('N', 0, 0, 0);
10603 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10604 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10605 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10606 pump_msg_loop(hwnd
, hAccel
);
10607 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 1", FALSE
);
10609 ret
= DestroyAcceleratorTable(hAccel
);
10610 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
10612 hAccel
= LoadAcceleratorsA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(2));
10613 ok(!!hAccel
, "Failed to load accelerators, error %lu.\n", GetLastError());
10615 if (winetest_debug
> 1) trace("testing VK_N press/release\n");
10617 keybd_event('N', 0, 0, 0);
10618 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10619 pump_msg_loop(hwnd
, hAccel
);
10620 ok_sequence(WmVkN
, "VK_N press/release", FALSE
);
10622 if (winetest_debug
> 1) trace("testing Shift+VK_N press/release\n");
10624 keybd_event(VK_SHIFT
, 0, 0, 0);
10625 keybd_event('N', 0, 0, 0);
10626 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10627 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10628 pump_msg_loop(hwnd
, hAccel
);
10629 ok_sequence(WmShiftVkN
, "Shift+VK_N press/release", FALSE
);
10631 if (winetest_debug
> 1) trace("testing Ctrl+VK_N press/release 2\n");
10633 keybd_event(VK_CONTROL
, 0, 0, 0);
10634 keybd_event('N', 0, 0, 0);
10635 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10636 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10637 pump_msg_loop(hwnd
, hAccel
);
10638 ok_sequence(WmCtrlVkN_2
, "Ctrl+VK_N press/release 2", FALSE
);
10640 if (winetest_debug
> 1) trace("testing Alt+VK_N press/release 2\n");
10642 keybd_event(VK_MENU
, 0, 0, 0);
10643 keybd_event('N', 0, 0, 0);
10644 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10645 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10646 pump_msg_loop(hwnd
, hAccel
);
10647 ok_sequence(WmAltVkN_2
, "Alt+VK_N press/release 2", FALSE
);
10649 if (winetest_debug
> 1) trace("testing Ctrl+Alt+VK_N press/release 2\n");
10651 keybd_event(VK_CONTROL
, 0, 0, 0);
10652 keybd_event(VK_MENU
, 0, 0, 0);
10653 keybd_event('N', 0, 0, 0);
10654 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10655 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10656 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10657 pump_msg_loop(hwnd
, hAccel
);
10658 ok_sequence(WmCtrlAltVkN
, "Ctrl+Alt+VK_N press/release 2", FALSE
);
10660 if (winetest_debug
> 1) trace("testing Ctrl+Shift+VK_N press/release\n");
10662 keybd_event(VK_CONTROL
, 0, 0, 0);
10663 keybd_event(VK_SHIFT
, 0, 0, 0);
10664 keybd_event('N', 0, 0, 0);
10665 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10666 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10667 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10668 pump_msg_loop(hwnd
, hAccel
);
10669 ok_sequence(WmCtrlShiftVkN
, "Ctrl+Shift+VK_N press/release", FALSE
);
10671 if (winetest_debug
> 1) trace("testing Ctrl+Alt+Shift+VK_N press/release\n");
10673 keybd_event(VK_CONTROL
, 0, 0, 0);
10674 keybd_event(VK_MENU
, 0, 0, 0);
10675 keybd_event(VK_SHIFT
, 0, 0, 0);
10676 keybd_event('N', 0, 0, 0);
10677 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
10678 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10679 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10680 keybd_event(VK_CONTROL
, 0, KEYEVENTF_KEYUP
, 0);
10681 pump_msg_loop(hwnd
, hAccel
);
10682 ok_sequence(WmCtrlAltShiftVkN
, "Ctrl+Alt+Shift+VK_N press/release", FALSE
);
10684 ret
= DestroyAcceleratorTable(hAccel
);
10685 ok( ret
, "DestroyAcceleratorTable error %ld\n", GetLastError());
10688 if (winetest_debug
> 1) trace("testing Alt press/release\n");
10690 keybd_event(VK_MENU
, 0, 0, 0);
10691 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10692 keybd_event(VK_MENU
, 0, 0, 0);
10693 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
10694 pump_msg_loop(hwnd
, 0);
10695 /* this test doesn't pass in Wine for managed windows */
10696 ok_sequence(WmAltPressRelease
, "Alt press/release", TRUE
);
10698 if (winetest_debug
> 1) trace("testing VK_F1 press/release\n");
10699 keybd_event(VK_F1
, 0, 0, 0);
10700 keybd_event(VK_F1
, 0, KEYEVENTF_KEYUP
, 0);
10701 pump_msg_loop(hwnd
, 0);
10702 ok_sequence(WmF1Seq
, "F1 press/release", FALSE
);
10704 if (winetest_debug
> 1) trace("testing VK_APPS press/release\n");
10705 keybd_event(VK_APPS
, 0, 0, 0);
10706 keybd_event(VK_APPS
, 0, KEYEVENTF_KEYUP
, 0);
10707 pump_msg_loop(hwnd
, 0);
10708 ok_sequence(WmVkAppsSeq
, "VK_APPS press/release", FALSE
);
10710 if (winetest_debug
> 1) trace("testing VK_F10 press/release\n");
10711 keybd_event(VK_F10
, 0, 0, 0);
10712 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
10713 keybd_event(VK_F10
, 0, 0, 0);
10714 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
10715 pump_msg_loop(hwnd
, 0);
10716 ok_sequence(WmVkF10Seq
, "VK_F10 press/release", TRUE
);
10718 if (winetest_debug
> 1) trace("testing SHIFT+F10 press/release\n");
10719 keybd_event(VK_SHIFT
, 0, 0, 0);
10720 keybd_event(VK_F10
, 0, 0, 0);
10721 keybd_event(VK_F10
, 0, KEYEVENTF_KEYUP
, 0);
10722 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10723 keybd_event(VK_ESCAPE
, 0, 0, 0);
10724 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
10725 pump_msg_loop(hwnd
, 0);
10726 ok_sequence(WmShiftF10Seq
, "SHIFT+F10 press/release", TRUE
);
10728 if (winetest_debug
> 1) trace("testing Shift+MouseButton press/release\n");
10729 /* first, move mouse pointer inside of the window client area */
10730 GetClientRect(hwnd
, &rc
);
10731 MapWindowPoints(hwnd
, 0, (LPPOINT
)&rc
, 2);
10732 rc
.left
+= (rc
.right
- rc
.left
)/2;
10733 rc
.top
+= (rc
.bottom
- rc
.top
)/2;
10734 SetCursorPos(rc
.left
, rc
.top
);
10735 SetActiveWindow(hwnd
);
10740 if (pt
.x
== rc
.left
&& pt
.y
== rc
.top
)
10743 keybd_event(VK_SHIFT
, 0, 0, 0);
10744 mouse_event(MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0);
10745 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
10746 keybd_event(VK_SHIFT
, 0, KEYEVENTF_KEYUP
, 0);
10747 pump_msg_loop(hwnd
, 0);
10748 for (i
= 0; i
< sequence_cnt
; i
++) if (sequence
[i
].message
== WM_LBUTTONDOWN
) break;
10749 if (i
< sequence_cnt
)
10750 ok_sequence(WmShiftMouseButton
, "Shift+MouseButton press/release", FALSE
);
10752 skip( "Shift+MouseButton event didn't get to the window\n" );
10756 if (hAccel
) DestroyAcceleratorTable(hAccel
);
10757 DestroyWindow(hwnd
);
10760 /************* window procedures ********************/
10762 static LRESULT
MsgCheckProc (BOOL unicode
, HWND hwnd
, UINT message
,
10763 WPARAM wParam
, LPARAM lParam
)
10765 static LONG defwndproc_counter
= 0;
10766 static LONG beginpaint_counter
= 0;
10768 struct recvd_message msg
;
10770 if (ignore_message( message
)) return 0;
10776 LONG style
= GetWindowLongA(hwnd
, GWL_STYLE
);
10777 ok((BOOL
)wParam
== !(style
& WS_DISABLED
),
10778 "wrong WS_DISABLED state: %Id != %d\n", wParam
, !(style
& WS_DISABLED
));
10782 case WM_CAPTURECHANGED
:
10783 if (test_DestroyWindow_flag
)
10785 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
10786 if (style
& WS_CHILD
)
10787 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
10788 else if (style
& WS_POPUP
)
10789 lParam
= WND_POPUP_ID
;
10791 lParam
= WND_PARENT_ID
;
10799 ok(!GetWindow(hwnd
, GW_CHILD
), "children should be unlinked at this point\n");
10800 capture
= GetCapture();
10803 ok(capture
== hwnd
, "capture should NOT be released at this point (capture %p)\n", capture
);
10804 if (winetest_debug
> 1) trace("current capture %p, releasing...\n", capture
);
10810 ok(GetAncestor(hwnd
, GA_PARENT
) != 0, "parent should NOT be unlinked at this point\n");
10811 if (test_DestroyWindow_flag
)
10813 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
);
10814 if (style
& WS_CHILD
)
10815 lParam
= GetWindowLongPtrA(hwnd
, GWLP_ID
);
10816 else if (style
& WS_POPUP
)
10817 lParam
= WND_POPUP_ID
;
10819 lParam
= WND_PARENT_ID
;
10823 /* test_accelerators() depends on this */
10829 ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo
;
10830 HANDLE handle
, event
= (HANDLE
)lParam
;
10833 handle
= (void*)0xdeadbeef;
10834 ret
= GetCurrentActCtx(&handle
);
10835 ok(ret
, "failed to get current context, %lu\n", GetLastError());
10836 ok(handle
== 0, "got active context %p\n", handle
);
10838 memset(&basicinfo
, 0xff, sizeof(basicinfo
));
10839 ret
= QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
, handle
, 0, ActivationContextBasicInformation
,
10840 &basicinfo
, sizeof(basicinfo
), NULL
);
10841 ok(ret
, "got %d, error %ld\n", ret
, GetLastError());
10842 ok(basicinfo
.hActCtx
== NULL
, "got %p\n", basicinfo
.hActCtx
);
10843 ok(basicinfo
.dwFlags
== 0, "got %lx\n", basicinfo
.dwFlags
);
10845 if (event
) SetEvent(event
);
10851 case WM_MOUSEACTIVATE
:
10852 case WM_NCMOUSEMOVE
:
10854 case WM_IME_SELECT
:
10859 msg
.message
= message
;
10860 msg
.flags
= sent
|wparam
|lparam
;
10861 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10862 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
10863 msg
.wParam
= wParam
;
10864 msg
.lParam
= lParam
;
10865 msg
.descr
= "MsgCheckProc";
10868 if (message
== WM_GETMINMAXINFO
&& (GetWindowLongA(hwnd
, GWL_STYLE
) & WS_CHILD
))
10870 HWND parent
= GetParent(hwnd
);
10872 MINMAXINFO
*minmax
= (MINMAXINFO
*)lParam
;
10874 GetClientRect(parent
, &rc
);
10875 if (winetest_debug
> 1)
10877 trace("parent %p client size = (%ld x %ld)\n", parent
, rc
.right
, rc
.bottom
);
10878 trace("Reserved=%ld,%ld MaxSize=%ld,%ld MaxPos=%ld,%ld MinTrack=%ld,%ld MaxTrack=%ld,%ld\n",
10879 minmax
->ptReserved
.x
, minmax
->ptReserved
.y
,
10880 minmax
->ptMaxSize
.x
, minmax
->ptMaxSize
.y
,
10881 minmax
->ptMaxPosition
.x
, minmax
->ptMaxPosition
.y
,
10882 minmax
->ptMinTrackSize
.x
, minmax
->ptMinTrackSize
.y
,
10883 minmax
->ptMaxTrackSize
.x
, minmax
->ptMaxTrackSize
.y
);
10885 ok(minmax
->ptMaxSize
.x
== rc
.right
, "default width of maximized child %ld != %ld\n",
10886 minmax
->ptMaxSize
.x
, rc
.right
);
10887 ok(minmax
->ptMaxSize
.y
== rc
.bottom
, "default height of maximized child %ld != %ld\n",
10888 minmax
->ptMaxSize
.y
, rc
.bottom
);
10891 if (message
== WM_PAINT
)
10894 beginpaint_counter
++;
10895 BeginPaint( hwnd
, &ps
);
10896 beginpaint_counter
--;
10897 EndPaint( hwnd
, &ps
);
10901 if (!test_context_menu
&& message
== WM_CONTEXTMENU
)
10903 /* don't create context menu */
10907 defwndproc_counter
++;
10908 ret
= unicode
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
10909 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10910 defwndproc_counter
--;
10915 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10917 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
10920 static LRESULT WINAPI
MsgCheckProcW(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10922 return MsgCheckProc (TRUE
, hwnd
, message
, wParam
, lParam
);
10925 static LRESULT WINAPI
PopupMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10927 static LONG defwndproc_counter
= 0;
10929 struct recvd_message msg
;
10931 if (ignore_message( message
)) return 0;
10935 case WM_QUERYENDSESSION
:
10936 case WM_ENDSESSION
:
10937 lParam
&= ~0x01; /* Vista adds a 0x01 flag */
10942 msg
.message
= message
;
10943 msg
.flags
= sent
|wparam
|lparam
;
10944 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10945 msg
.wParam
= wParam
;
10946 msg
.lParam
= lParam
;
10947 msg
.descr
= "popup";
10950 if (message
== WM_CREATE
)
10952 DWORD style
= GetWindowLongA(hwnd
, GWL_STYLE
) | WS_VISIBLE
;
10953 SetWindowLongA(hwnd
, GWL_STYLE
, style
);
10956 defwndproc_counter
++;
10957 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
10958 defwndproc_counter
--;
10963 static LRESULT WINAPI
ParentMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
10965 static LONG defwndproc_counter
= 0;
10966 static LONG beginpaint_counter
= 0;
10968 struct recvd_message msg
;
10970 if (ignore_message( message
)) return 0;
10972 if (log_all_parent_messages
||
10973 message
== WM_PARENTNOTIFY
|| message
== WM_CANCELMODE
||
10974 message
== WM_SETFOCUS
|| message
== WM_KILLFOCUS
||
10975 message
== WM_ENABLE
|| message
== WM_ENTERIDLE
||
10976 message
== WM_DRAWITEM
|| message
== WM_MEASUREITEM
|| message
== WM_COMPAREITEM
||
10977 message
== WM_COMMAND
|| message
== WM_IME_SETCONTEXT
)
10986 case WM_NCMOUSEMOVE
:
10991 msg
.message
= message
;
10992 msg
.flags
= sent
|parent
|wparam
|lparam
;
10993 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
10994 if (beginpaint_counter
) msg
.flags
|= beginpaint
;
10995 msg
.wParam
= wParam
;
10996 msg
.lParam
= lParam
;
10997 msg
.descr
= "parent";
11001 if (message
== WM_PAINT
)
11004 beginpaint_counter
++;
11005 BeginPaint( hwnd
, &ps
);
11006 beginpaint_counter
--;
11007 EndPaint( hwnd
, &ps
);
11011 defwndproc_counter
++;
11012 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
11013 defwndproc_counter
--;
11015 return message
== WM_COMPAREITEM
? -1 : ret
;
11018 static LRESULT CALLBACK
StopQuitMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
11020 if (message
== WM_CREATE
)
11021 PostMessageA(hwnd
, WM_CLOSE
, 0, 0);
11022 else if (message
== WM_CLOSE
)
11024 /* Only the first WM_QUIT will survive the window destruction */
11025 PostMessageA(hwnd
, WM_USER
, 0x1234, 0x5678);
11026 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
11027 PostMessageA(hwnd
, WM_QUIT
, 0x4321, 0x8765);
11030 return DefWindowProcA(hwnd
, message
, wp
, lp
);
11033 static LRESULT WINAPI
TestDlgProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11035 static LONG defwndproc_counter
= 0;
11037 struct recvd_message msg
;
11039 if (ignore_message( message
)) return 0;
11043 DefDlgProcA(hwnd
, DM_SETDEFID
, 1, 0);
11044 ret
= DefDlgProcA(hwnd
, DM_GETDEFID
, 0, 0);
11045 if (after_end_dialog
)
11046 ok( ret
== 0, "DM_GETDEFID should return 0 after EndDialog, got %Ix\n", ret
);
11048 ok(HIWORD(ret
) == DC_HASDEFID
, "DM_GETDEFID should return DC_HASDEFID, got %Ix\n", ret
);
11052 msg
.message
= message
;
11053 msg
.flags
= sent
|wparam
|lparam
;
11054 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11055 msg
.wParam
= wParam
;
11056 msg
.lParam
= lParam
;
11057 msg
.descr
= "dialog";
11060 defwndproc_counter
++;
11061 ret
= DefDlgProcA(hwnd
, message
, wParam
, lParam
);
11062 defwndproc_counter
--;
11067 static LRESULT WINAPI
ShowWindowProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11069 static LONG defwndproc_counter
= 0;
11071 struct recvd_message msg
;
11073 /* log only specific messages we are interested in */
11076 #if 0 /* probably log these as well */
11081 case WM_SHOWWINDOW
:
11084 case WM_GETMINMAXINFO
:
11085 case WM_WINDOWPOSCHANGING
:
11086 case WM_WINDOWPOSCHANGED
:
11089 default: /* ignore */
11090 /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/
11091 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
11095 msg
.message
= message
;
11096 msg
.flags
= sent
|wparam
|lparam
;
11097 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11098 msg
.wParam
= wParam
;
11099 msg
.lParam
= lParam
;
11100 msg
.descr
= "show";
11103 defwndproc_counter
++;
11104 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
11105 defwndproc_counter
--;
11110 static LRESULT WINAPI
PaintLoopProcA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
11114 case WM_CREATE
: return 0;
11123 if (PeekMessageA(&msg2
, 0, 0, 0, 1))
11125 TranslateMessage(&msg2
);
11126 DispatchMessageA(&msg2
);
11130 else ok(broken(1), "infinite loop\n");
11132 paint_loop_done
= TRUE
;
11133 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
11136 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
11139 static LRESULT WINAPI
HotkeyMsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
11141 static LONG defwndproc_counter
= 0;
11143 struct recvd_message msg
;
11144 DWORD queue_status
;
11146 if (ignore_message( message
)) return 0;
11148 if ((message
>= WM_KEYFIRST
&& message
<= WM_KEYLAST
) ||
11149 message
== WM_HOTKEY
|| message
>= WM_APP
)
11152 msg
.message
= message
;
11153 msg
.flags
= sent
|wparam
|lparam
;
11154 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
11155 msg
.wParam
= wParam
;
11156 msg
.lParam
= lParam
;
11157 msg
.descr
= "HotkeyMsgCheckProcA";
11161 defwndproc_counter
++;
11162 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
11163 defwndproc_counter
--;
11165 if (message
== WM_APP
)
11167 queue_status
= GetQueueStatus(QS_HOTKEY
);
11168 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
11169 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
11170 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %lx\n", queue_status
);
11171 PostMessageA(hwnd
, WM_APP
+1, 0, 0);
11173 else if (message
== WM_APP
+1)
11175 queue_status
= GetQueueStatus(QS_HOTKEY
);
11176 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %lx\n", queue_status
);
11182 static void register_classes(void)
11188 cls
.lpfnWndProc
= MsgCheckProcA
;
11189 cls
.cbClsExtra
= 0;
11190 cls
.cbWndExtra
= 0;
11191 cls
.hInstance
= GetModuleHandleA(0);
11193 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
11194 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
11195 cls
.lpszMenuName
= NULL
;
11196 cls
.lpszClassName
= "TestWindowClass";
11197 register_class(&cls
);
11199 cls
.lpfnWndProc
= HotkeyMsgCheckProcA
;
11200 cls
.lpszClassName
= "HotkeyWindowClass";
11201 register_class(&cls
);
11203 cls
.lpfnWndProc
= ShowWindowProcA
;
11204 cls
.lpszClassName
= "ShowWindowClass";
11205 register_class(&cls
);
11207 cls
.lpfnWndProc
= PopupMsgCheckProcA
;
11208 cls
.lpszClassName
= "TestPopupClass";
11209 register_class(&cls
);
11211 cls
.lpfnWndProc
= ParentMsgCheckProcA
;
11212 cls
.lpszClassName
= "TestParentClass";
11213 register_class(&cls
);
11215 cls
.lpfnWndProc
= StopQuitMsgCheckProcA
;
11216 cls
.lpszClassName
= "StopQuitClass";
11217 register_class(&cls
);
11219 cls
.lpfnWndProc
= DefWindowProcA
;
11220 cls
.lpszClassName
= "SimpleWindowClass";
11221 register_class(&cls
);
11223 cls
.lpfnWndProc
= PaintLoopProcA
;
11224 cls
.lpszClassName
= "PaintLoopWindowClass";
11225 register_class(&cls
);
11227 cls
.style
= CS_NOCLOSE
;
11228 cls
.lpszClassName
= "NoCloseWindowClass";
11229 register_class(&cls
);
11231 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
11233 cls
.hInstance
= GetModuleHandleA(0);
11234 cls
.hbrBackground
= 0;
11235 cls
.lpfnWndProc
= TestDlgProcA
;
11236 cls
.lpszClassName
= "TestDialogClass";
11237 register_class(&cls
);
11239 cls
.lpfnWndProc
= DefWindowProcA
;
11240 cls
.style
= CS_PARENTDC
;
11241 cls
.lpszClassName
= "SimpleWindowClassWithParentDC";
11242 register_class(&cls
);
11245 clsW
.lpfnWndProc
= MsgCheckProcW
;
11246 clsW
.cbClsExtra
= 0;
11247 clsW
.cbWndExtra
= 0;
11248 clsW
.hInstance
= GetModuleHandleW(0);
11250 clsW
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
11251 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
11252 clsW
.lpszMenuName
= NULL
;
11253 clsW
.lpszClassName
= testWindowClassW
;
11254 RegisterClassW(&clsW
); /* ignore error, this fails on Win9x */
11257 static BOOL
is_our_logged_class(HWND hwnd
)
11261 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
11263 if (!lstrcmpiA(buf
, "TestWindowClass") ||
11264 !lstrcmpiA(buf
, "ShowWindowClass") ||
11265 !lstrcmpiA(buf
, "TestParentClass") ||
11266 !lstrcmpiA(buf
, "TestPopupClass") ||
11267 !lstrcmpiA(buf
, "SimpleWindowClass") ||
11268 !lstrcmpiA(buf
, "TestDialogClass") ||
11269 !lstrcmpiA(buf
, "MDI_frame_class") ||
11270 !lstrcmpiA(buf
, "MDI_client_class") ||
11271 !lstrcmpiA(buf
, "MDI_child_class") ||
11272 !lstrcmpiA(buf
, "my_button_class") ||
11273 !lstrcmpiA(buf
, "my_edit_class") ||
11274 !lstrcmpiA(buf
, "static") ||
11275 !lstrcmpiA(buf
, "ListBox") ||
11276 !lstrcmpiA(buf
, "ComboBox") ||
11277 !lstrcmpiA(buf
, "MyDialogClass") ||
11278 !lstrcmpiA(buf
, "#32770") ||
11279 !lstrcmpiA(buf
, "#32768"))
11285 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
11289 ok(cbt_hook_thread_id
== GetCurrentThreadId(), "we didn't ask for events from other threads\n");
11291 if (nCode
== HCBT_CLICKSKIPPED
)
11293 /* ignore this event, XP sends it a lot when switching focus between windows */
11294 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
11297 if (nCode
== HCBT_SYSCOMMAND
|| nCode
== HCBT_KEYSKIPPED
)
11299 struct recvd_message msg
;
11302 msg
.message
= nCode
;
11303 msg
.flags
= hook
|wparam
|lparam
;
11304 msg
.wParam
= wParam
;
11305 msg
.lParam
= lParam
;
11309 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
11312 if (nCode
== HCBT_DESTROYWND
)
11314 if (test_DestroyWindow_flag
)
11316 DWORD style
= GetWindowLongA((HWND
)wParam
, GWL_STYLE
);
11317 if (style
& WS_CHILD
)
11318 lParam
= GetWindowLongPtrA((HWND
)wParam
, GWLP_ID
);
11319 else if (style
& WS_POPUP
)
11320 lParam
= WND_POPUP_ID
;
11322 lParam
= WND_PARENT_ID
;
11326 /* Log also SetFocus(0) calls */
11327 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
11329 if (is_our_logged_class(hwnd
))
11331 struct recvd_message msg
;
11334 msg
.message
= nCode
;
11335 msg
.flags
= hook
|wparam
|lparam
;
11336 msg
.wParam
= wParam
;
11337 msg
.lParam
= lParam
;
11341 return CallNextHookEx(hCBT_hook
, nCode
, wParam
, lParam
);
11344 static void CALLBACK
win_event_proc(HWINEVENTHOOK hevent
,
11352 ok(thread_id
== winevent_hook_thread_id
, "we didn't ask for events from other threads\n");
11354 /* ignore mouse cursor events */
11355 if (object_id
== OBJID_CURSOR
) return;
11357 if (!hwnd
|| is_our_logged_class(hwnd
))
11359 struct recvd_message msg
;
11362 msg
.message
= event
;
11363 msg
.flags
= winevent_hook
|wparam
|lparam
;
11364 msg
.wParam
= object_id
;
11365 msg
.lParam
= child_id
;
11371 static const WCHAR wszUnicode
[] = {'U','n','i','c','o','d','e',0};
11372 static const WCHAR wszAnsi
[] = {'U',0};
11374 static const GUID iface_guid
= {0x66666666};
11376 static LRESULT CALLBACK
MsgConversionProcW(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
11378 const DEV_BROADCAST_DEVICEINTERFACE_A
*ifaceA
= (const void *)lParam
;
11382 case CB_FINDSTRINGEXACT
:
11383 if (!lstrcmpW((LPCWSTR
)lParam
, wszUnicode
))
11385 if (!lstrcmpW((LPCWSTR
)lParam
, wszAnsi
))
11389 case WM_DEVICECHANGE
:
11390 if (wParam
== DBT_DEVICEARRIVAL
&& IsEqualGUID(&ifaceA
->dbcc_classguid
, &iface_guid
))
11392 DWORD expect_size
= offsetof(DEV_BROADCAST_DEVICEINTERFACE_A
, dbcc_name
[strlen(ifaceA
->dbcc_name
)]);
11394 ok(ifaceA
->dbcc_size
== expect_size
, "Expected %lu, got %lu.\n", expect_size
, ifaceA
->dbcc_size
);
11395 ok(ifaceA
->dbcc_devicetype
== DBT_DEVTYP_DEVICEINTERFACE
,
11396 "Got notification type %#lx.\n", ifaceA
->dbcc_devicetype
);
11397 ok(!ifaceA
->dbcc_reserved
, "Got reserved %#lx.\n", ifaceA
->dbcc_reserved
);
11398 ok(!strcmp(ifaceA
->dbcc_name
, "test name"), "Got name %s.\n", debugstr_a(ifaceA
->dbcc_name
));
11402 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
11405 static const struct message WmGetTextLengthAfromW
[] = {
11406 { WM_GETTEXTLENGTH
, sent
},
11407 { WM_GETTEXT
, sent
|optional
},
11411 static const WCHAR dummy_window_text
[] = {'d','u','m','m','y',' ','t','e','x','t',0};
11413 /* dummy window proc for WM_GETTEXTLENGTH test */
11414 static LRESULT CALLBACK
get_text_len_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
11418 case WM_GETTEXTLENGTH
:
11419 return lstrlenW(dummy_window_text
) + 37; /* some random length */
11421 lstrcpynW( (LPWSTR
)lp
, dummy_window_text
, wp
);
11422 return lstrlenW( (LPWSTR
)lp
);
11424 return DefWindowProcW( hwnd
, msg
, wp
, lp
);
11428 static void test_message_conversion(void)
11430 static const WCHAR wszMsgConversionClass
[] =
11431 {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0};
11433 DEV_BROADCAST_DEVICEINTERFACE_A
*dev_interface
= (void *)buffer
;
11437 WNDPROC wndproc
, newproc
;
11441 cls
.lpfnWndProc
= MsgConversionProcW
;
11442 cls
.cbClsExtra
= 0;
11443 cls
.cbWndExtra
= 0;
11444 cls
.hInstance
= GetModuleHandleW(NULL
);
11446 cls
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
11447 cls
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
11448 cls
.lpszMenuName
= NULL
;
11449 cls
.lpszClassName
= wszMsgConversionClass
;
11450 /* this call will fail on Win9x, but that doesn't matter as this test is
11451 * meaningless on those platforms */
11452 if(!RegisterClassW(&cls
)) return;
11454 hwnd
= CreateWindowExW(0, wszMsgConversionClass
, NULL
, WS_OVERLAPPED
,
11455 100, 100, 200, 200, 0, 0, 0, NULL
);
11456 ok(hwnd
!= NULL
, "Window creation failed\n");
11460 wndproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
11461 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11462 ok(lRes
== 0, "String should have been converted\n");
11463 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11464 ok(lRes
== 1, "String shouldn't have been converted\n");
11468 wndproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, GWLP_WNDPROC
);
11469 lRes
= CallWindowProcA(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11470 ok(lRes
== 1, "String shouldn't have been converted\n");
11471 lRes
= CallWindowProcW(wndproc
, hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11472 ok(lRes
== 1, "String shouldn't have been converted\n");
11474 /* Synchronous messages */
11476 lRes
= SendMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11477 ok(lRes
== 0, "String should have been converted\n");
11478 lRes
= SendMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11479 ok(lRes
== 1, "String shouldn't have been converted\n");
11481 /* Asynchronous messages */
11484 lRes
= PostMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11485 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11486 "PostMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11488 lRes
= PostMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11489 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11490 "PostMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11492 lRes
= PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11493 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11494 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11496 lRes
= PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11497 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11498 "PosThreadtMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11500 lRes
= SendNotifyMessageA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11501 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11502 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11504 lRes
= SendNotifyMessageW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
);
11505 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11506 "SendNotifyMessage on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11508 lRes
= SendMessageCallbackA(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
11509 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11510 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11512 lRes
= SendMessageCallbackW(hwnd
, CB_FINDSTRINGEXACT
, 0, (LPARAM
)wszUnicode
, NULL
, 0);
11513 ok(lRes
== 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY
|| GetLastError() == ERROR_INVALID_PARAMETER
),
11514 "SendMessageCallback on sync only message returned %Id, last error %ld\n", lRes
, GetLastError());
11516 /* Test WM_DEVICECHANGE. */
11518 dev_interface
->dbcc_devicetype
= DBT_DEVTYP_DEVICEINTERFACE
;
11519 dev_interface
->dbcc_reserved
= 0;
11520 dev_interface
->dbcc_classguid
= iface_guid
;
11521 strcpy(dev_interface
->dbcc_name
, "test name");
11522 dev_interface
->dbcc_size
= offsetof(DEV_BROADCAST_DEVICEINTERFACE_A
,
11523 dbcc_name
[strlen(dev_interface
->dbcc_name
)]);
11524 lRes
= SendMessageA(hwnd
, WM_DEVICECHANGE
, DBT_DEVICEARRIVAL
, (LPARAM
)dev_interface
);
11525 ok(lRes
== 2, "Got %Id, error %lu.\n", lRes
, GetLastError());
11527 DestroyWindow(hwnd
);
11529 /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
11531 hwnd
= CreateWindowW (testWindowClassW
, wszUnicode
,
11532 WS_OVERLAPPEDWINDOW
,
11533 100, 100, 200, 200, 0, 0, 0, NULL
);
11534 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
11536 lRes
= SendMessageA (hwnd
, WM_GETTEXTLENGTH
, 0, 0);
11537 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
11538 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
11539 "got bad length %Id\n", lRes
);
11542 lRes
= CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
),
11543 hwnd
, WM_GETTEXTLENGTH
, 0, 0);
11544 ok_sequence(WmGetTextLengthAfromW
, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE
);
11545 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, wszUnicode
, lstrlenW(wszUnicode
), NULL
, 0, NULL
, NULL
),
11546 "got bad length %Id\n", lRes
);
11548 wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)get_text_len_proc
);
11549 newproc
= (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
);
11550 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
11551 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
11552 NULL
, 0, NULL
, NULL
) ||
11553 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
11554 "got bad length %Id\n", lRes
);
11556 SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)wndproc
); /* restore old wnd proc */
11557 lRes
= CallWindowProcA( newproc
, hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
11558 ok( lRes
== WideCharToMultiByte( CP_ACP
, 0, dummy_window_text
, lstrlenW(dummy_window_text
),
11559 NULL
, 0, NULL
, NULL
) ||
11560 broken(lRes
== lstrlenW(dummy_window_text
) + 37),
11561 "got bad length %Id\n", lRes
);
11563 ret
= DestroyWindow(hwnd
);
11564 ok( ret
, "DestroyWindow() error %ld\n", GetLastError());
11574 static VOID CALLBACK
tfunc(HWND hwnd
, UINT uMsg
, UINT_PTR id
, DWORD dwTime
)
11578 #define TIMER_ID 0x19
11579 #define TIMER_COUNT 500 /* 499 samples */
11580 #define TIMER_DURATION_EXPECTED 10000 /* 10 ms */
11581 #define TIMER_DURATION_ALT 15600 /* 15.6 ms */
11582 #define TIMER_DURATION_TOLERANCE 1000 /* 1 ms */
11584 static int count
= 0;
11585 static ULONGLONG timer_ticks
[TIMER_COUNT
];
11586 static int timer_duration
= 0;
11588 static int compare_ulonglong(const void *a
, const void *b
)
11591 la
= *(ULONGLONG
*)a
;
11592 lb
= *(ULONGLONG
*)b
;
11593 return (la
> lb
) - (la
< lb
);
11596 static void timer_fired(void)
11598 if (count
< TIMER_COUNT
)
11600 LARGE_INTEGER performance_counter
;
11603 ret
= QueryPerformanceCounter(&performance_counter
);
11604 ok(ret
, "QueryPerformanceCounter failed\n");
11606 timer_ticks
[count
] = performance_counter
.QuadPart
;
11611 if (count
== TIMER_COUNT
)
11613 LARGE_INTEGER performance_frequency
;
11616 /* calculate durations */
11617 for (int i
=0; i
< TIMER_COUNT
-1; i
++)
11618 timer_ticks
[i
] = timer_ticks
[i
+1] - timer_ticks
[i
];
11620 qsort(timer_ticks
, TIMER_COUNT
- 1, sizeof(timer_ticks
[0]), compare_ulonglong
);
11622 ret
= QueryPerformanceFrequency(&performance_frequency
);
11623 ok(ret
, "QueryPerformanceFrequency failed\n");
11625 /* median duration, converted to microseconds */
11626 timer_duration
= (int)(timer_ticks
[(TIMER_COUNT
- 1) / 2] * 1000000 / performance_frequency
.QuadPart
);
11630 static void CALLBACK
callback_count(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
11635 static DWORD exception
;
11636 static void CALLBACK
callback_exception(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
11639 RaiseException(exception
, 0, 0, NULL
);
11642 static DWORD WINAPI
timer_thread_proc(LPVOID x
)
11644 struct timer_info
*info
= x
;
11647 r
= KillTimer(info
->hWnd
, 0x19);
11648 ok(r
,"KillTimer failed in thread\n");
11649 r
= SetTimer(info
->hWnd
,TIMER_ID
,10000,tfunc
);
11650 ok(r
,"SetTimer failed in thread\n");
11651 ok(r
==TIMER_ID
,"SetTimer id different\n");
11652 r
= SetEvent(info
->handles
[0]);
11653 ok(r
,"SetEvent failed in thread\n");
11657 static void test_timers(void)
11659 struct timer_info info
;
11663 info
.hWnd
= CreateWindowA("TestWindowClass", NULL
,
11664 WS_OVERLAPPEDWINDOW
,
11665 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
11668 info
.id
= SetTimer(info
.hWnd
,TIMER_ID
,10000,tfunc
);
11669 ok(info
.id
, "SetTimer failed\n");
11670 ok(info
.id
==TIMER_ID
, "SetTimer timer ID different\n");
11671 info
.handles
[0] = CreateEventW(NULL
,0,0,NULL
);
11672 info
.handles
[1] = CreateThread(NULL
,0,timer_thread_proc
,&info
,0,&id
);
11674 WaitForMultipleObjects(2, info
.handles
, FALSE
, INFINITE
);
11676 WaitForSingleObject(info
.handles
[1], INFINITE
);
11678 CloseHandle(info
.handles
[0]);
11679 CloseHandle(info
.handles
[1]);
11681 ok( KillTimer(info
.hWnd
, TIMER_ID
), "KillTimer failed\n");
11683 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
11684 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
11688 id
= SetTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
11689 ok(id
!= 0, "did not get id from SetTimer.\n");
11690 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
11691 while (count
< TIMER_COUNT
&& GetMessageA(&msg
, info
.hWnd
, 0, 0))
11692 DispatchMessageA(&msg
);
11693 ok(abs(timer_duration
-TIMER_DURATION_EXPECTED
) < TIMER_DURATION_TOLERANCE
/* xp, win7 */
11694 || broken(abs(timer_duration
- TIMER_DURATION_ALT
) < TIMER_DURATION_TOLERANCE
) /* most common */,
11695 "did not get expected median timeout (%d != ~%d).\n",
11696 timer_duration
, TIMER_DURATION_EXPECTED
);
11697 ok(KillTimer(info
.hWnd
, id
), "KillTimer failed\n");
11698 /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
11699 if (pSetSystemTimer
)
11702 id
= pSetSystemTimer(info
.hWnd
, TIMER_ID
, 0, callback_count
);
11703 ok(id
!= 0, "did not get id from SetSystemTimer.\n");
11704 ok(id
==TIMER_ID
, "SetTimer timer ID different\n");
11705 while (count
< TIMER_COUNT
&& GetMessageA(&msg
, info
.hWnd
, 0, 0))
11707 if (msg
.message
== WM_SYSTIMER
)
11709 ok(msg
.message
!= WM_TIMER
, "unexpected WM_TIMER\n");
11710 DispatchMessageA(&msg
);
11712 ok(abs(timer_duration
-TIMER_DURATION_EXPECTED
) < TIMER_DURATION_TOLERANCE
11713 || broken(abs(timer_duration
- TIMER_DURATION_ALT
) < TIMER_DURATION_TOLERANCE
) /* most common */,
11714 "did not get expected median timeout (%d != ~%d).\n",
11715 timer_duration
, TIMER_DURATION_EXPECTED
);
11716 ok(pKillSystemTimer(info
.hWnd
, id
), "KillSystemTimer failed\n");
11719 ok(DestroyWindow(info
.hWnd
), "failed to destroy window\n");
11722 static void test_timers_no_wnd(void)
11724 static UINT_PTR ids
[0xffff];
11731 id
= SetTimer(NULL
, 0, 100, callback_count
);
11732 ok(id
!= 0, "did not get id from SetTimer.\n");
11733 id2
= SetTimer(NULL
, id
, 200, callback_count
);
11734 ok(id2
== id
, "did not get same id from SetTimer when replacing (%Ii expected %Ii).\n", id2
, id
);
11736 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11737 ok(count
== 0, "did not get zero count as expected (%i).\n", count
);
11739 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11740 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
11741 KillTimer(NULL
, id
);
11743 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
11744 ok(count
== 1, "killing replaced timer did not work (%i).\n", count
);
11746 /* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
11747 * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
11751 id
= SetTimer(NULL
, 0, 0, callback_count
);
11752 ok(id
!= 0, "did not get id from SetTimer.\n");
11753 while (count
< TIMER_COUNT
&& GetMessageA(&msg
, NULL
, 0, 0))
11754 DispatchMessageA(&msg
);
11755 ok(abs(timer_duration
-TIMER_DURATION_EXPECTED
) < TIMER_DURATION_TOLERANCE
/* xp */
11756 || broken(abs(timer_duration
- TIMER_DURATION_ALT
) < TIMER_DURATION_TOLERANCE
) /* most common */,
11757 "did not get expected median timeout (%d != ~%d).\n",
11758 timer_duration
, TIMER_DURATION_EXPECTED
);
11759 KillTimer(NULL
, id
);
11760 /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
11762 if (pSetCoalescableTimer
)
11765 id
= pSetCoalescableTimer(NULL
, 0, 0, callback_count
, 0);
11766 ok(id
!= 0, "SetCoalescableTimer failed with %lu.\n", GetLastError());
11767 start
= GetTickCount();
11768 while (GetTickCount()-start
< 100 && GetMessageA(&msg
, NULL
, 0, 0))
11769 DispatchMessageA(&msg
);
11770 ok(count
> 1, "expected count > 1, got %d.\n", count
);
11771 KillTimer(NULL
, id
);
11774 win_skip("SetCoalescableTimer not available.\n");
11776 /* Check what happens when we're running out of timers */
11777 for (i
= 0; i
< ARRAY_SIZE(ids
); i
++)
11779 SetLastError(0xdeadbeef);
11780 ids
[i
] = SetTimer(NULL
, 0, USER_TIMER_MAXIMUM
, tfunc
);
11781 if (!ids
[i
]) break;
11783 ok(i
!= ARRAY_SIZE(ids
), "all timers were created successfully\n");
11784 ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES
|| broken(GetLastError()==0xdeadbeef),
11785 "GetLastError() = %ld\n", GetLastError());
11786 while (i
> 0) KillTimer(NULL
, ids
[--i
]);
11789 static void test_timers_exception(DWORD code
)
11795 id
= SetTimer(NULL
, 0, 1000, callback_exception
);
11796 ok(id
!= 0, "did not get id from SetTimer.\n");
11798 memset(&msg
, 0, sizeof(msg
));
11799 msg
.message
= WM_TIMER
;
11801 msg
.lParam
= (LPARAM
)callback_exception
;
11804 DispatchMessageA(&msg
);
11805 ok(count
== 1, "did not get one count as expected (%i).\n", count
);
11807 KillTimer(NULL
, id
);
11810 static void test_timers_exceptions(void)
11812 test_timers_exception(EXCEPTION_ACCESS_VIOLATION
);
11813 test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT
);
11814 test_timers_exception(EXCEPTION_BREAKPOINT
);
11815 test_timers_exception(EXCEPTION_SINGLE_STEP
);
11816 test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED
);
11817 test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND
);
11818 test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO
);
11819 test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT
);
11820 test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION
);
11821 test_timers_exception(0xE000BEEF); /* customer exception */
11824 /* Various win events with arbitrary parameters */
11825 static const struct message WmWinEventsSeq
[] = {
11826 { EVENT_SYSTEM_SOUND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
11827 { EVENT_SYSTEM_ALERT
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
11828 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
11829 { EVENT_SYSTEM_MENUSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
11830 { EVENT_SYSTEM_MENUEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
11831 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
11832 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
11833 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
11834 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
11835 /* our win event hook ignores OBJID_CURSOR events */
11836 /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/
11837 { EVENT_SYSTEM_MOVESIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 10 },
11838 { EVENT_SYSTEM_CONTEXTHELPSTART
, winevent_hook
|wparam
|lparam
, OBJID_SOUND
, 11 },
11839 { EVENT_SYSTEM_CONTEXTHELPEND
, winevent_hook
|wparam
|lparam
, OBJID_QUERYCLASSNAMEIDX
, 12 },
11840 { EVENT_SYSTEM_DRAGDROPSTART
, winevent_hook
|wparam
|lparam
, OBJID_NATIVEOM
, 13 },
11841 { EVENT_SYSTEM_DRAGDROPEND
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 0 },
11842 { EVENT_SYSTEM_DIALOGSTART
, winevent_hook
|wparam
|lparam
, OBJID_SYSMENU
, 1 },
11843 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
, OBJID_TITLEBAR
, 2 },
11844 { EVENT_SYSTEM_SCROLLINGSTART
, winevent_hook
|wparam
|lparam
, OBJID_MENU
, 3 },
11845 { EVENT_SYSTEM_SCROLLINGEND
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 4 },
11846 { EVENT_SYSTEM_SWITCHSTART
, winevent_hook
|wparam
|lparam
, OBJID_VSCROLL
, 5 },
11847 { EVENT_SYSTEM_SWITCHEND
, winevent_hook
|wparam
|lparam
, OBJID_HSCROLL
, 6 },
11848 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, OBJID_SIZEGRIP
, 7 },
11849 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 8 },
11852 static const struct message WmWinEventCaretSeq
[] = {
11853 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
11854 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
11855 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 2 */
11856 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1 */
11859 static const struct message WmWinEventCaretSeq_2
[] = {
11860 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
11861 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
11862 { EVENT_OBJECT_NAMECHANGE
, winevent_hook
|wparam
|lparam
, OBJID_CARET
, 0 }, /* hook 1/2 */
11865 static const struct message WmWinEventAlertSeq
[] = {
11866 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 0 },
11869 static const struct message WmWinEventAlertSeq_2
[] = {
11870 /* create window in the thread proc */
11871 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, OBJID_WINDOW
, 2 },
11872 /* our test event */
11873 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, OBJID_ALERT
, 2 },
11876 static const struct message WmGlobalHookSeq_1
[] = {
11877 /* create window in the thread proc */
11878 { HCBT_CREATEWND
, hook
|lparam
, 0, 2 },
11879 /* our test events */
11880 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 },
11881 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 },
11884 static const struct message WmGlobalHookSeq_2
[] = {
11885 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 0 }, /* old local hook */
11886 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_NEXTWINDOW
, 2 }, /* new global hook */
11887 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 0 }, /* old local hook */
11888 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_PREVWINDOW
, 2 }, /* new global hook */
11892 static const struct message WmMouseLLHookSeq
[] = {
11893 { WM_MOUSEMOVE
, hook
},
11894 { WM_LBUTTONUP
, hook
},
11895 { WM_MOUSEMOVE
, hook
},
11899 static void CALLBACK
win_event_global_hook_proc(HWINEVENTHOOK hevent
,
11909 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
11911 if (!lstrcmpiA(buf
, "TestWindowClass") ||
11912 !lstrcmpiA(buf
, "static"))
11914 struct recvd_message msg
;
11917 msg
.message
= event
;
11918 msg
.flags
= winevent_hook
|wparam
|lparam
;
11919 msg
.wParam
= object_id
;
11920 msg
.lParam
= (thread_id
== GetCurrentThreadId()) ? child_id
: (child_id
+ 2);
11921 msg
.descr
= "WEH_2";
11927 static HHOOK hCBT_global_hook
;
11928 static DWORD cbt_global_hook_thread_id
;
11930 static LRESULT CALLBACK
cbt_global_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
11935 if (nCode
== HCBT_SYSCOMMAND
)
11937 struct recvd_message msg
;
11940 msg
.message
= nCode
;
11941 msg
.flags
= hook
|wparam
|lparam
;
11942 msg
.wParam
= wParam
;
11943 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
11944 msg
.descr
= "CBT_2";
11947 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11949 /* WH_MOUSE_LL hook */
11950 if (nCode
== HC_ACTION
)
11952 MSLLHOOKSTRUCT
*mhll
= (MSLLHOOKSTRUCT
*)lParam
;
11954 /* we can't test for real mouse events */
11955 if (mhll
->flags
& LLMHF_INJECTED
)
11957 struct recvd_message msg
;
11959 memset (&msg
, 0, sizeof (msg
));
11960 msg
.message
= wParam
;
11962 msg
.descr
= "CBT_2";
11965 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11968 /* Log also SetFocus(0) calls */
11969 hwnd
= wParam
? (HWND
)wParam
: (HWND
)lParam
;
11971 if (GetClassNameA(hwnd
, buf
, sizeof(buf
)))
11973 if (!lstrcmpiA(buf
, "TestWindowClass") ||
11974 !lstrcmpiA(buf
, "static"))
11976 struct recvd_message msg
;
11979 msg
.message
= nCode
;
11980 msg
.flags
= hook
|wparam
|lparam
;
11981 msg
.wParam
= wParam
;
11982 msg
.lParam
= (cbt_global_hook_thread_id
== GetCurrentThreadId()) ? 1 : 2;
11983 msg
.descr
= "CBT_2";
11987 return CallNextHookEx(hCBT_global_hook
, nCode
, wParam
, lParam
);
11990 static DWORD WINAPI
win_event_global_thread_proc(void *param
)
11994 HANDLE hevent
= *(HANDLE
*)param
;
11996 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
11997 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
11998 if (winetest_debug
> 1) trace("created thread window %p\n", hwnd
);
12000 *(HWND
*)param
= hwnd
;
12003 /* this event should be received only by our new hook proc,
12004 * an old one does not expect an event from another thread.
12006 pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, hwnd
, OBJID_ALERT
, 0);
12009 while (GetMessageA(&msg
, 0, 0, 0))
12011 TranslateMessage(&msg
);
12012 DispatchMessageA(&msg
);
12017 static DWORD WINAPI
cbt_global_hook_thread_proc(void *param
)
12021 HANDLE hevent
= *(HANDLE
*)param
;
12024 /* these events should be received only by our new hook proc,
12025 * an old one does not expect an event from another thread.
12028 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
12029 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
12030 if (winetest_debug
> 1) trace("created thread window %p\n", hwnd
);
12032 *(HWND
*)param
= hwnd
;
12034 /* Windows doesn't like when a thread plays games with the focus,
12035 that leads to all kinds of misbehaviours and failures to activate
12036 a window. So, better keep next lines commented out.
12040 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
12041 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
12045 while (GetMessageA(&msg
, 0, 0, 0))
12047 TranslateMessage(&msg
);
12048 DispatchMessageA(&msg
);
12053 static DWORD WINAPI
mouse_ll_global_thread_proc(void *param
)
12057 HANDLE hevent
= *(HANDLE
*)param
;
12059 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
12060 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
12061 if (winetest_debug
> 1) trace("created thread window %p\n", hwnd
);
12063 *(HWND
*)param
= hwnd
;
12067 /* Windows doesn't like when a thread plays games with the focus,
12068 * that leads to all kinds of misbehaviours and failures to activate
12069 * a window. So, better don't generate a mouse click message below.
12071 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12072 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
12073 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12076 while (GetMessageA(&msg
, 0, 0, 0))
12078 TranslateMessage(&msg
);
12079 DispatchMessageA(&msg
);
12084 static void test_winevents(void)
12090 HANDLE hthread
, hevent
;
12092 HWINEVENTHOOK hhook
;
12093 const struct message
*events
= WmWinEventsSeq
;
12095 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
12096 WS_OVERLAPPEDWINDOW
,
12097 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
12099 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
12101 /****** start of global hook test *************/
12102 hCBT_global_hook
= SetWindowsHookExA(WH_CBT
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
12103 if (!hCBT_global_hook
)
12105 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12106 skip( "cannot set global hook\n" );
12110 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12111 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12114 hthread
= CreateThread(NULL
, 0, cbt_global_hook_thread_proc
, &hwnd2
, 0, &tid
);
12115 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12117 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12119 ok_sequence(WmGlobalHookSeq_1
, "global hook 1", FALSE
);
12122 /* this one should be received only by old hook proc */
12123 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_NEXTWINDOW
, 0);
12124 /* this one should be received only by old hook proc */
12125 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_PREVWINDOW
, 0);
12127 ok_sequence(WmGlobalHookSeq_2
, "global hook 2", FALSE
);
12129 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
12130 ok( ret
, "UnhookWindowsHookEx error %ld\n", GetLastError());
12132 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12133 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12134 CloseHandle(hthread
);
12135 CloseHandle(hevent
);
12136 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12137 /****** end of global hook test *************/
12139 if (!pSetWinEventHook
|| !pNotifyWinEvent
|| !pUnhookWinEvent
)
12141 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12149 /* this test doesn't pass under Win9x */
12150 /* win2k ignores events with hwnd == 0 */
12151 SetLastError(0xdeadbeef);
12152 pNotifyWinEvent(events
[0].message
, 0, events
[0].wParam
, events
[0].lParam
);
12153 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| /* Win2k */
12154 GetLastError() == 0xdeadbeef, /* Win9x */
12155 "unexpected error %ld\n", GetLastError());
12156 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
12159 for (i
= 0; i
< ARRAY_SIZE(WmWinEventsSeq
); i
++)
12160 pNotifyWinEvent(events
[i
].message
, hwnd
, events
[i
].wParam
, events
[i
].lParam
);
12162 ok_sequence(WmWinEventsSeq
, "notify winevents", FALSE
);
12164 /****** start of event filtering test *************/
12165 hhook
= pSetWinEventHook(
12166 EVENT_OBJECT_SHOW
, /* 0x8002 */
12167 EVENT_OBJECT_LOCATIONCHANGE
, /* 0x800B */
12168 GetModuleHandleA(0), win_event_global_hook_proc
,
12169 GetCurrentProcessId(), 0,
12170 WINEVENT_INCONTEXT
);
12171 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12173 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12174 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12177 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
12178 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12180 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12182 ok_sequence(WmWinEventAlertSeq
, "alert winevent", FALSE
);
12185 /* this one should be received only by old hook proc */
12186 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
12187 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
12188 /* this one should be received only by old hook proc */
12189 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
12191 ok_sequence(WmWinEventCaretSeq
, "caret winevent", FALSE
);
12193 ret
= pUnhookWinEvent(hhook
);
12194 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12196 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12197 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12198 CloseHandle(hthread
);
12199 CloseHandle(hevent
);
12200 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12201 /****** end of event filtering test *************/
12203 /****** start of out of context event test *************/
12204 hhook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0,
12205 win_event_global_hook_proc
, GetCurrentProcessId(), 0,
12206 WINEVENT_OUTOFCONTEXT
);
12207 ok(hhook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12209 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12210 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12215 hthread
= CreateThread(NULL
, 0, win_event_global_thread_proc
, &hwnd2
, 0, &tid
);
12216 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12218 ok(WaitForSingleObject(hevent
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12220 ok_sequence(WmEmptySeq
, "empty notify winevents", FALSE
);
12221 /* process pending winevent messages */
12222 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
12223 ok_sequence(WmWinEventAlertSeq_2
, "alert winevent for out of context proc", FALSE
);
12226 /* this one should be received only by old hook proc */
12227 pNotifyWinEvent(EVENT_OBJECT_CREATE
, hwnd
, OBJID_CARET
, 0); /* 0x8000 */
12228 pNotifyWinEvent(EVENT_OBJECT_SHOW
, hwnd
, OBJID_CARET
, 0); /* 0x8002 */
12229 /* this one should be received only by old hook proc */
12230 pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE
, hwnd
, OBJID_CARET
, 0); /* 0x800C */
12232 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for incontext proc", FALSE
);
12233 /* process pending winevent messages */
12234 ok(!PeekMessageA(&msg
, 0, 0, 0, PM_NOREMOVE
), "msg queue should be empty\n");
12235 ok_sequence(WmWinEventCaretSeq_2
, "caret winevent for out of context proc", FALSE
);
12237 ret
= pUnhookWinEvent(hhook
);
12238 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12240 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12241 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12242 CloseHandle(hthread
);
12243 CloseHandle(hevent
);
12244 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12245 /****** end of out of context event test *************/
12247 /****** start of MOUSE_LL hook test *************/
12248 hCBT_global_hook
= SetWindowsHookExA(WH_MOUSE_LL
, cbt_global_hook_proc
, GetModuleHandleA(0), 0);
12249 /* WH_MOUSE_LL is not supported on Win9x platforms */
12250 if (!hCBT_global_hook
)
12252 win_skip("Skipping WH_MOUSE_LL test on this platform\n");
12253 goto skip_mouse_ll_hook_test
;
12256 hevent
= CreateEventA(NULL
, 0, 0, NULL
);
12257 ok(!!hevent
, "Failed to create event, error %lu.\n", GetLastError());
12260 hthread
= CreateThread(NULL
, 0, mouse_ll_global_thread_proc
, &hwnd2
, 0, &tid
);
12261 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
12263 while (WaitForSingleObject(hevent
, 100) == WAIT_TIMEOUT
)
12264 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
12266 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook other thread", FALSE
);
12269 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
12270 mouse_event(MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0);
12271 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
12273 ok_sequence(WmMouseLLHookSeq
, "MOUSE_LL hook same thread", FALSE
);
12275 ret
= UnhookWindowsHookEx(hCBT_global_hook
);
12276 ok( ret
, "UnhookWindowsHookEx error %ld\n", GetLastError());
12278 PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
12279 ok(WaitForSingleObject(hthread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
12280 CloseHandle(hthread
);
12281 CloseHandle(hevent
);
12282 ok(!IsWindow(hwnd2
), "window should be destroyed on thread exit\n");
12283 /****** end of MOUSE_LL hook test *************/
12284 skip_mouse_ll_hook_test
:
12286 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12289 static char *get_test_dll_path(void)
12291 static const char *dll_name
= "testdll.dll";
12292 static char path
[MAX_PATH
];
12298 GetTempPathA(ARRAY_SIZE(path
), path
);
12299 strcat(path
, dll_name
);
12301 file
= CreateFileA(path
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
12302 ok(file
!= INVALID_HANDLE_VALUE
, "Failed to create file %s: %lu.\n", debugstr_a(path
), GetLastError());
12304 res
= FindResourceA(NULL
, dll_name
, "TESTDLL");
12305 ok(!!res
, "Failed to load resource: %lu\n", GetLastError());
12306 ptr
= LockResource(LoadResource(GetModuleHandleA(NULL
), res
));
12307 WriteFile(file
, ptr
, SizeofResource(GetModuleHandleA(NULL
), res
), &written
, NULL
);
12308 ok(written
== SizeofResource(GetModuleHandleA(NULL
), res
), "Failed to write resource\n");
12314 static void test_set_hook(void)
12316 LRESULT (CALLBACK
*p_dummy_hook_proc
)(int code
, WPARAM wp
, LPARAM lp
);
12317 HMODULE test_dll_module
;
12318 char *test_dll_path
;
12322 HWINEVENTHOOK hwinevent_hook
;
12325 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, GetModuleHandleA(0), GetCurrentThreadId());
12326 ok(hhook
!= 0, "local hook does not require hModule set to 0\n");
12327 UnhookWindowsHookEx(hhook
);
12329 SetLastError(0xdeadbeef);
12330 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, 0);
12331 ok(!hhook
, "global hook requires hModule != 0\n");
12332 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
12334 SetLastError(0xdeadbeef);
12335 hhook
= SetWindowsHookExA(WH_JOURNALRECORD
, cbt_hook_proc
, 0, 0);
12336 ok(!hhook
, "global hook requires hModule != 0\n");
12337 ok(GetLastError() == ERROR_ACCESS_DENIED
, "unexpected error %ld\n", GetLastError());
12339 SetLastError(0xdeadbeef);
12340 hhook
= SetWindowsHookExA(WH_CBT
, 0, GetModuleHandleA(0), GetCurrentThreadId());
12341 ok(!hhook
, "SetWinEventHook with invalid proc should fail\n");
12342 ok(GetLastError() == ERROR_INVALID_FILTER_PROC
, "unexpected error %ld\n", GetLastError());
12344 SetLastError(0xdeadbeef);
12345 ok(!UnhookWindowsHookEx((HHOOK
)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
12346 ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE
, "unexpected error %ld\n", GetLastError());
12348 test_dll_path
= get_test_dll_path();
12349 test_dll_module
= LoadLibraryA(test_dll_path
);
12350 p_dummy_hook_proc
= (void *)GetProcAddress(test_dll_module
, "dummy_hook_proc");
12351 for (i
= WH_MIN
; i
<= WH_MAX
; i
++)
12353 winetest_push_context("ID %d", i
);
12355 /* Test that setting hooks should succeed for hook procs in a library. But for WH_JOURNALRECORD
12356 * and WH_JOURNALPLAYBACK, ERROR_ACCESS_DENIED is returned, even with administrator rights */
12357 SetLastError(0xdeadbeef);
12358 hhook
= SetWindowsHookExA(i
, p_dummy_hook_proc
, test_dll_module
, 0);
12359 error
= GetLastError();
12360 if (i
== WH_JOURNALRECORD
|| i
== WH_JOURNALPLAYBACK
)
12362 ok(!hhook
, "SetWinEventHook succeeded.\n");
12363 ok(error
== ERROR_ACCESS_DENIED
, "Got unexpected error %ld.\n", GetLastError());
12367 ok(!!hhook
, "SetWinEventHook failed.\n");
12368 ok(error
== NO_ERROR
, "Got unexpected error %ld.\n", GetLastError());
12371 UnhookWindowsHookEx(hhook
);
12373 /* Test settings global hooks with a thread ID */
12374 SetLastError(0xdeadbeef);
12375 hhook
= SetWindowsHookExA(i
, p_dummy_hook_proc
, test_dll_module
, GetCurrentThreadId());
12376 error
= GetLastError();
12377 if (i
== WH_JOURNALRECORD
|| i
== WH_JOURNALPLAYBACK
|| i
== WH_SYSMSGFILTER
12378 || i
== WH_KEYBOARD_LL
|| i
== WH_MOUSE_LL
)
12380 ok(!hhook
, "SetWinEventHook succeeded.\n");
12381 ok(error
== ERROR_GLOBAL_ONLY_HOOK
, "Got unexpected error %ld.\n", GetLastError());
12385 ok(!!hhook
, "SetWinEventHook failed.\n");
12386 ok(error
== NO_ERROR
, "Got unexpected error %ld.\n", GetLastError());
12389 UnhookWindowsHookEx(hhook
);
12391 winetest_pop_context();
12393 FreeLibrary(test_dll_module
);
12394 ret
= DeleteFileA(test_dll_path
);
12395 ok(ret
, "Failed to remove the test dll, error %ld.\n", GetLastError());
12397 if (!pSetWinEventHook
|| !pUnhookWinEvent
) return;
12399 /* even process local incontext hooks require hmodule */
12400 SetLastError(0xdeadbeef);
12401 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12402 GetCurrentProcessId(), 0, WINEVENT_INCONTEXT
);
12403 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
12404 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
12406 /* even thread local incontext hooks require hmodule */
12407 SetLastError(0xdeadbeef);
12408 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12409 GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT
);
12410 ok(!hwinevent_hook
, "WINEVENT_INCONTEXT requires hModule != 0\n");
12411 ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD
, "unexpected error %ld\n", GetLastError());
12413 SetLastError(0xdeadbeef);
12414 hwinevent_hook
= pSetWinEventHook(1, 0, 0, win_event_proc
,
12415 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
12416 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
12417 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
12419 SetLastError(0xdeadbeef);
12420 hwinevent_hook
= pSetWinEventHook(-1, 1, 0, win_event_proc
,
12421 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
12422 ok(!hwinevent_hook
, "SetWinEventHook with invalid event range should fail\n");
12423 ok(GetLastError() == ERROR_INVALID_HOOK_FILTER
, "unexpected error %ld\n", GetLastError());
12425 SetLastError(0xdeadbeef);
12426 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12427 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT
);
12428 ok(!hwinevent_hook
, "SetWinEventHook with invalid tid should fail\n");
12430 ok(GetLastError() == ERROR_INVALID_THREAD_ID
, "unexpected error %ld\n", GetLastError());
12432 SetLastError(0xdeadbeef);
12433 hwinevent_hook
= pSetWinEventHook(0, 0, 0, win_event_proc
,
12434 GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT
);
12435 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12436 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
12437 ret
= pUnhookWinEvent(hwinevent_hook
);
12438 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12441 /* This call succeeds under win2k SP4, but fails under Wine.
12442 Does win2k test/use passed process id? */
12443 SetLastError(0xdeadbeef);
12444 hwinevent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
, 0, win_event_proc
,
12445 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT
);
12446 ok(hwinevent_hook
!= 0, "SetWinEventHook error %ld\n", GetLastError());
12447 ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
12448 ret
= pUnhookWinEvent(hwinevent_hook
);
12449 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
12452 SetLastError(0xdeadbeef);
12453 ok(!pUnhookWinEvent((HWINEVENTHOOK
)0xdeadbeef), "UnhookWinEvent succeeded\n");
12454 ok(GetLastError() == ERROR_INVALID_HANDLE
, "unexpected error %ld\n", GetLastError());
12457 static HWND hook_hwnd
;
12458 static HHOOK recursive_hook
;
12459 static int hook_depth
, max_hook_depth
;
12460 static BOOL skip_WH_KEYBOARD_hook
, skip_WH_MOUSE_hook
;
12462 static void simulate_click(BOOL left
, int x
, int y
)
12468 GetCursorPos(&old_pt
);
12469 SetCursorPos(x
, y
);
12470 memset(input
, 0, sizeof(input
));
12471 input
[0].type
= INPUT_MOUSE
;
12472 input
[0].mi
.dx
= x
;
12473 input
[0].mi
.dy
= y
;
12474 input
[0].mi
.dwFlags
= left
? MOUSEEVENTF_LEFTDOWN
: MOUSEEVENTF_RIGHTDOWN
;
12475 input
[1].type
= INPUT_MOUSE
;
12476 input
[1].mi
.dx
= x
;
12477 input
[1].mi
.dy
= y
;
12478 input
[1].mi
.dwFlags
= left
? MOUSEEVENTF_LEFTUP
: MOUSEEVENTF_RIGHTUP
;
12479 events_no
= SendInput(2, input
, sizeof(input
[0]));
12480 ok(events_no
== 2, "SendInput returned %d\n", events_no
);
12481 SetCursorPos(old_pt
.x
, old_pt
.y
);
12484 static LRESULT WINAPI
rec_get_message_hook(int code
, WPARAM w
, LPARAM l
)
12491 if(hook_depth
> max_hook_depth
)
12492 max_hook_depth
= hook_depth
;
12494 b
= PeekMessageW(&msg
, hook_hwnd
, 0, 0, PM_NOREMOVE
);
12495 ok(b
, "PeekMessage failed\n");
12497 res
= CallNextHookEx(recursive_hook
, code
, w
, l
);
12503 static LRESULT CALLBACK
keyboard_recursive_hook_proc(int code
, WPARAM wp
, LPARAM lp
)
12508 return CallNextHookEx(0, code
, wp
, lp
);
12510 if (skip_WH_KEYBOARD_hook
)
12514 max_hook_depth
= max(max_hook_depth
, hook_depth
);
12515 PeekMessageW(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
);
12517 return CallNextHookEx(0, code
, wp
, lp
);
12520 static LRESULT CALLBACK
mouse_recursive_hook_proc(int code
, WPARAM wp
, LPARAM lp
)
12525 return CallNextHookEx(0, code
, wp
, lp
);
12527 if (skip_WH_MOUSE_hook
)
12531 max_hook_depth
= max(max_hook_depth
, hook_depth
);
12532 PeekMessageW(&msg
, NULL
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
12534 return CallNextHookEx(0, code
, wp
, lp
);
12537 static LRESULT CALLBACK
keyboard_recursive_cbt_hook_proc(int code
, WPARAM wp
, LPARAM lp
)
12542 return CallNextHookEx(0, code
, wp
, lp
);
12544 if (code
== HCBT_KEYSKIPPED
)
12547 max_hook_depth
= max(max_hook_depth
, hook_depth
);
12548 PeekMessageW(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
);
12552 return CallNextHookEx(0, code
, wp
, lp
);
12555 static LRESULT CALLBACK
mouse_recursive_cbt_hook_proc(int code
, WPARAM wp
, LPARAM lp
)
12560 return CallNextHookEx(0, code
, wp
, lp
);
12562 if (code
== HCBT_CLICKSKIPPED
)
12565 max_hook_depth
= max(max_hook_depth
, hook_depth
);
12566 PeekMessageW(&msg
, NULL
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
12570 return CallNextHookEx(0, code
, wp
, lp
);
12573 static void test_recursive_hook(void)
12575 HHOOK hook
, cbt_hook
;
12580 hook_hwnd
= CreateWindowExA(WS_EX_TOPMOST
, "Static", NULL
, WS_POPUP
| WS_VISIBLE
, 0, 0, 200, 60,
12581 NULL
, NULL
, NULL
, NULL
);
12582 ok(hook_hwnd
!= NULL
, "CreateWindow failed\n");
12584 recursive_hook
= SetWindowsHookExW(WH_GETMESSAGE
, rec_get_message_hook
, NULL
, GetCurrentThreadId());
12585 ok(recursive_hook
!= NULL
, "SetWindowsHookEx failed\n");
12587 PostMessageW(hook_hwnd
, WM_USER
, 0, 0);
12588 PostMessageW(hook_hwnd
, WM_USER
+1, 0, 0);
12591 GetMessageW(&msg
, hook_hwnd
, 0, 0);
12592 ok(15 <= max_hook_depth
&& max_hook_depth
< 45, "max_hook_depth = %d\n", max_hook_depth
);
12593 if (winetest_debug
> 1) trace("max_hook_depth = %d\n", max_hook_depth
);
12595 b
= UnhookWindowsHookEx(recursive_hook
);
12596 ok(b
, "UnhokWindowsHookEx failed\n");
12598 /* Test possible recursive hook conditions */
12599 b
= SetForegroundWindow(hook_hwnd
);
12600 ok(b
, "SetForegroundWindow failed, error %ld.\n", GetLastError());
12602 /* Test a possible recursive WH_KEYBOARD hook condition */
12603 max_hook_depth
= 0;
12604 hook
= SetWindowsHookExA(WH_KEYBOARD
, keyboard_recursive_hook_proc
, NULL
, GetCurrentThreadId());
12605 ok(!!hook
, "SetWindowsHookExA failed, error %ld.\n", GetLastError());
12608 input
.type
= INPUT_KEYBOARD
;
12609 input
.ki
.wVk
= VK_F3
;
12610 SendInput(1, &input
, sizeof(INPUT
));
12613 /* Expect the WH_KEYBOARD hook not gets called recursively */
12614 ok(max_hook_depth
== 1, "Got expected %d.\n", max_hook_depth
);
12616 /* Test a possible recursive WH_CBT HCBT_KEYSKIPPED hook condition */
12617 max_hook_depth
= 0;
12618 skip_WH_KEYBOARD_hook
= 1;
12619 cbt_hook
= SetWindowsHookExA(WH_CBT
, keyboard_recursive_cbt_hook_proc
, NULL
, GetCurrentThreadId());
12620 ok(!!cbt_hook
, "SetWindowsHookExA failed, error %ld.\n", GetLastError());
12623 input
.type
= INPUT_KEYBOARD
;
12624 input
.ki
.wVk
= VK_F3
;
12625 SendInput(1, &input
, sizeof(INPUT
));
12626 while (PeekMessageA(&msg
, hook_hwnd
, WM_KEYFIRST
, WM_KEYLAST
, 0)) DispatchMessageA(&msg
);
12628 /* Expect the WH_CBT HCBT_KEYSKIPPED hook not gets called recursively */
12629 ok(max_hook_depth
== 1, "Got expected %d.\n", max_hook_depth
);
12631 UnhookWindowsHookEx(cbt_hook
);
12632 UnhookWindowsHookEx(hook
);
12634 /* Test a recursive WH_MOUSE hook condition */
12635 SetCapture(hook_hwnd
);
12637 max_hook_depth
= 0;
12638 hook
= SetWindowsHookExA(WH_MOUSE
, mouse_recursive_hook_proc
, NULL
, GetCurrentThreadId());
12639 ok(!!hook
, "SetWindowsHookExA failed, error %ld.\n", GetLastError());
12642 simulate_click(FALSE
, 50, 50);
12645 /* Expect the WH_MOUSE hook gets called recursively */
12646 ok(max_hook_depth
> 10, "Got expected %d.\n", max_hook_depth
);
12648 /* Test a possible recursive WH_CBT HCBT_CLICKSKIPPED hook condition */
12649 max_hook_depth
= 0;
12650 skip_WH_MOUSE_hook
= 1;
12651 cbt_hook
= SetWindowsHookExA(WH_CBT
, mouse_recursive_cbt_hook_proc
, NULL
, GetCurrentThreadId());
12652 ok(!!cbt_hook
, "SetWindowsHookExA failed, error %ld.\n", GetLastError());
12655 simulate_click(FALSE
, 50, 50);
12658 /* Expect the WH_CBT HCBT_CLICKSKIPPED hook not gets called recursively */
12659 ok(max_hook_depth
<= 10, "Got expected %d.\n", max_hook_depth
);
12661 UnhookWindowsHookEx(cbt_hook
);
12662 UnhookWindowsHookEx(hook
);
12664 DestroyWindow(hook_hwnd
);
12667 static int max_msg_depth
;
12669 static LRESULT WINAPI
recursive_messages_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
12671 static int msg_depth
;
12674 if (message
== WM_SETCURSOR
&& max_msg_depth
< 15)
12677 max_msg_depth
= max(max_msg_depth
, msg_depth
);
12678 PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
);
12681 return DefWindowProcA(hwnd
, message
, wp
, lp
);
12684 static void test_recursive_messages(void)
12686 WNDCLASSA cls
= {0};
12689 cls
.lpfnWndProc
= recursive_messages_proc
;
12690 cls
.hInstance
= GetModuleHandleA(0);
12691 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
12692 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
12693 cls
.lpszClassName
= "TestRecursiveMsgClass";
12694 register_class(&cls
);
12696 hwnd
= CreateWindowExA(WS_EX_TOPMOST
, "TestRecursiveMsgClass", NULL
, WS_POPUP
| WS_DISABLED
| WS_VISIBLE
, 0, 0,
12697 100, 100, NULL
, NULL
, NULL
, NULL
);
12698 ok(hwnd
!= NULL
, "CreateWindowExA failed, error %ld.\n", GetLastError());
12699 SetForegroundWindow(hwnd
);
12703 simulate_click(FALSE
, 50, 50);
12706 /* Expect recursive_messages_proc() gets called recursively for WM_SETCURSOR */
12707 ok(max_msg_depth
== 15, "Got expected %d.\n", max_msg_depth
);
12709 DestroyWindow(hwnd
);
12710 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
12713 static const struct message ScrollWindowPaint1
[] = {
12714 { WM_PAINT
, sent
},
12715 { WM_ERASEBKGND
, sent
|beginpaint
},
12716 { WM_GETTEXTLENGTH
, sent
|optional
},
12717 { WM_PAINT
, sent
|optional
},
12718 { WM_NCPAINT
, sent
|beginpaint
|optional
},
12719 { WM_GETTEXT
, sent
|beginpaint
|optional
},
12720 { WM_GETTEXT
, sent
|beginpaint
|optional
},
12721 { WM_GETTEXT
, sent
|beginpaint
|optional
},
12722 { WM_GETTEXT
, sent
|beginpaint
|defwinproc
|optional
},
12723 { WM_ERASEBKGND
, sent
|beginpaint
|optional
},
12727 static const struct message ScrollWindowPaint2
[] = {
12728 { WM_PAINT
, sent
},
12732 static void test_scrollwindowex(void)
12735 RECT rect
={0,0,130,130};
12737 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test Scroll",
12738 WS_VISIBLE
|WS_OVERLAPPEDWINDOW
,
12739 100, 100, 200, 200, 0, 0, 0, NULL
);
12740 ok (hwnd
!= 0, "Failed to create overlapped window\n");
12741 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
12742 WS_VISIBLE
|WS_CAPTION
|WS_CHILD
,
12743 10, 10, 150, 150, hwnd
, 0, 0, NULL
);
12744 ok (hchild
!= 0, "Failed to create child\n");
12745 UpdateWindow(hwnd
);
12749 /* scroll without the child window */
12750 if (winetest_debug
> 1) trace("start scroll\n");
12751 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
12752 SW_ERASE
|SW_INVALIDATE
);
12753 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
12754 if (winetest_debug
> 1) trace("end scroll\n");
12757 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
12761 /* Now without the SW_ERASE flag */
12762 if (winetest_debug
> 1) trace("start scroll\n");
12763 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
, SW_INVALIDATE
);
12764 ok_sequence(WmEmptySeq
, "ScrollWindowEx", FALSE
);
12765 if (winetest_debug
> 1) trace("end scroll\n");
12768 ok_sequence(ScrollWindowPaint2
, "ScrollWindowEx", FALSE
);
12772 /* now scroll the child window as well */
12773 if (winetest_debug
> 1) trace("start scroll\n");
12774 ScrollWindowEx( hwnd
, 10, 10, &rect
, NULL
, NULL
, NULL
,
12775 SW_SCROLLCHILDREN
|SW_ERASE
|SW_INVALIDATE
);
12776 /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
12777 /* windows sometimes a WM_MOVE */
12778 ok_sequence(WmEmptySeq
, "ScrollWindowEx", TRUE
);
12779 if (winetest_debug
> 1) trace("end scroll\n");
12782 ok_sequence(ScrollWindowPaint1
, "ScrollWindowEx", FALSE
);
12786 /* now scroll with ScrollWindow() */
12787 if (winetest_debug
> 1) trace("start scroll with ScrollWindow\n");
12788 ScrollWindow( hwnd
, 5, 5, NULL
, NULL
);
12789 if (winetest_debug
> 1) trace("end scroll\n");
12792 ok_sequence(ScrollWindowPaint1
, "ScrollWindow", FALSE
);
12794 ok(DestroyWindow(hchild
), "failed to destroy window\n");
12795 ok(DestroyWindow(hwnd
), "failed to destroy window\n");
12799 static const struct message destroy_window_with_children
[] = {
12800 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* popup */
12801 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_PARENT_ID
}, /* parent */
12802 { 0x0090, sent
|optional
},
12803 { HCBT_DESTROYWND
, hook
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12804 { 0x0090, sent
|optional
},
12805 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* popup */
12806 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12807 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12808 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_POPUP_ID
}, /* popup */
12809 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 }, /* parent */
12810 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
12811 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
12812 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
12813 { WM_DESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
12814 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 2 }, /* child2 */
12815 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 3 }, /* child3 */
12816 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_CHILD_ID
+ 1 }, /* child1 */
12817 { WM_NCDESTROY
, sent
|wparam
|lparam
, 0, WND_PARENT_ID
}, /* parent */
12821 static void test_DestroyWindow(void)
12824 HWND parent
, child1
, child2
, child3
, child4
, test
;
12825 UINT_PTR child_id
= WND_CHILD_ID
+ 1;
12827 parent
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12828 100, 100, 200, 200, 0, 0, 0, NULL
);
12829 ok(!!parent
, "Failed to create window, error %lu.\n", GetLastError());
12830 child1
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
12831 0, 0, 50, 50, parent
, (HMENU
)child_id
++, 0, NULL
);
12832 ok(!!child1
, "Failed to create window, error %lu.\n", GetLastError());
12833 child2
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
12834 0, 0, 50, 50, GetDesktopWindow(), (HMENU
)child_id
++, 0, NULL
);
12835 ok(!!child2
, "Failed to create window, error %lu.\n", GetLastError());
12836 child3
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
12837 0, 0, 50, 50, child1
, (HMENU
)child_id
++, 0, NULL
);
12838 ok(!!child3
, "Failed to create window, error %lu.\n", GetLastError());
12839 child4
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
,
12840 0, 0, 50, 50, parent
, 0, 0, NULL
);
12841 ok(!!child4
, "Failed to create window, error %lu.\n", GetLastError());
12843 /* test owner/parent of child2 */
12844 test
= GetParent(child2
);
12845 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12846 ok(!IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
12847 test
= GetAncestor(child2
, GA_PARENT
);
12848 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12849 test
= GetWindow(child2
, GW_OWNER
);
12850 ok(!test
, "wrong owner %p\n", test
);
12852 test
= SetParent(child2
, parent
);
12853 ok(test
== GetDesktopWindow(), "wrong old parent %p\n", test
);
12855 /* test owner/parent of the parent */
12856 test
= GetParent(parent
);
12857 ok(!test
, "wrong parent %p\n", test
);
12858 ok(!IsChild(GetDesktopWindow(), parent
), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent
);
12859 test
= GetAncestor(parent
, GA_PARENT
);
12860 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12861 test
= GetWindow(parent
, GW_OWNER
);
12862 ok(!test
, "wrong owner %p\n", test
);
12864 /* test owner/parent of child1 */
12865 test
= GetParent(child1
);
12866 ok(test
== parent
, "wrong parent %p\n", test
);
12867 ok(IsChild(parent
, child1
), "wrong parent/child %p/%p\n", parent
, child1
);
12868 test
= GetAncestor(child1
, GA_PARENT
);
12869 ok(test
== parent
, "wrong parent %p\n", test
);
12870 test
= GetWindow(child1
, GW_OWNER
);
12871 ok(!test
, "wrong owner %p\n", test
);
12873 /* test owner/parent of child2 */
12874 test
= GetParent(child2
);
12875 ok(test
== parent
, "wrong parent %p\n", test
);
12876 ok(IsChild(parent
, child2
), "wrong parent/child %p/%p\n", parent
, child2
);
12877 test
= GetAncestor(child2
, GA_PARENT
);
12878 ok(test
== parent
, "wrong parent %p\n", test
);
12879 test
= GetWindow(child2
, GW_OWNER
);
12880 ok(!test
, "wrong owner %p\n", test
);
12882 /* test owner/parent of child3 */
12883 test
= GetParent(child3
);
12884 ok(test
== child1
, "wrong parent %p\n", test
);
12885 ok(IsChild(parent
, child3
), "wrong parent/child %p/%p\n", parent
, child3
);
12886 test
= GetAncestor(child3
, GA_PARENT
);
12887 ok(test
== child1
, "wrong parent %p\n", test
);
12888 test
= GetWindow(child3
, GW_OWNER
);
12889 ok(!test
, "wrong owner %p\n", test
);
12891 /* test owner/parent of child4 */
12892 test
= GetParent(child4
);
12893 ok(test
== parent
, "wrong parent %p\n", test
);
12894 ok(!IsChild(parent
, child4
), "wrong parent/child %p/%p\n", parent
, child4
);
12895 test
= GetAncestor(child4
, GA_PARENT
);
12896 ok(test
== GetDesktopWindow(), "wrong parent %p\n", test
);
12897 test
= GetWindow(child4
, GW_OWNER
);
12898 ok(test
== parent
, "wrong owner %p\n", test
);
12902 if (winetest_debug
> 1) trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
12903 parent
, child1
, child2
, child3
, child4
);
12905 SetCapture(child4
);
12906 test
= GetCapture();
12907 ok(test
== child4
, "wrong capture window %p\n", test
);
12909 test_DestroyWindow_flag
= TRUE
;
12910 ret
= DestroyWindow(parent
);
12911 ok( ret
, "DestroyWindow() error %ld\n", GetLastError());
12912 test_DestroyWindow_flag
= FALSE
;
12913 ok_sequence(destroy_window_with_children
, "destroy window with children", FALSE
);
12915 ok(!IsWindow(parent
), "parent still exists\n");
12916 ok(!IsWindow(child1
), "child1 still exists\n");
12917 ok(!IsWindow(child2
), "child2 still exists\n");
12918 ok(!IsWindow(child3
), "child3 still exists\n");
12919 ok(!IsWindow(child4
), "child4 still exists\n");
12921 test
= GetCapture();
12922 ok(!test
, "wrong capture window %p\n", test
);
12926 static const struct message WmDispatchPaint
[] = {
12927 { WM_NCPAINT
, sent
},
12928 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12929 { WM_GETTEXT
, sent
|defwinproc
|optional
},
12930 { WM_ERASEBKGND
, sent
},
12934 static LRESULT WINAPI
DispatchMessageCheckProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
12936 if (message
== WM_PAINT
) return 0;
12937 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
12940 static void test_DispatchMessage(void)
12945 HWND hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
12946 100, 100, 200, 200, 0, 0, 0, NULL
);
12947 ShowWindow( hwnd
, SW_SHOW
);
12948 UpdateWindow( hwnd
);
12951 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)DispatchMessageCheckProc
);
12953 SetRect( &rect
, -5, -5, 5, 5 );
12954 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
12956 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
12958 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
12962 DispatchMessageA( &msg
);
12963 /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */
12964 if (!count
) ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
12965 else ok_sequence( WmEmptySeq
, "WmEmpty", FALSE
);
12966 if (++count
> 10) break;
12969 ok( msg
.message
== WM_PAINT
&& count
> 10, "WM_PAINT messages stopped\n" );
12971 if (winetest_debug
> 1) trace("now without DispatchMessage\n");
12973 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
12975 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
12977 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
12980 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
12982 /* this will send WM_NCCPAINT just like DispatchMessage does */
12983 GetUpdateRgn( hwnd
, hrgn
, TRUE
);
12984 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
12985 DeleteObject( hrgn
);
12986 GetClientRect( hwnd
, &rect
);
12987 ValidateRect( hwnd
, &rect
); /* this will stop WM_PAINTs */
12988 ok( !count
, "Got multiple WM_PAINTs\n" );
12989 if (++count
> 10) break;
12994 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
|RDW_FRAME
);
12996 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
))
12998 if (msg
.message
!= WM_PAINT
) DispatchMessageA( &msg
);
13004 hdc
= BeginPaint( hwnd
, NULL
);
13005 ok( !hdc
, "got valid hdc %p from BeginPaint\n", hdc
);
13006 ok( !EndPaint( hwnd
, NULL
), "EndPaint succeeded\n" );
13007 ok_sequence( WmDispatchPaint
, "WmDispatchPaint", FALSE
);
13008 ok( !count
, "Got multiple WM_PAINTs\n" );
13009 if (++count
> 10) break;
13012 DestroyWindow(hwnd
);
13016 static const struct message WmUser
[] = {
13021 struct sendmsg_info
13029 static DWORD CALLBACK
send_msg_thread( LPVOID arg
)
13031 struct sendmsg_info
*info
= arg
;
13032 SetLastError( 0xdeadbeef );
13033 SetEvent( info
->ready
);
13034 info
->ret
= SendMessageTimeoutA( info
->hwnd
, WM_USER
, 0, 0, 0, info
->timeout
, NULL
);
13035 if (!info
->ret
) ok( GetLastError() == ERROR_TIMEOUT
||
13036 broken(GetLastError() == 0), /* win9x */
13037 "unexpected error %ld\n", GetLastError());
13041 static void wait_for_thread( HANDLE thread
)
13043 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_SENDMESSAGE
) != WAIT_OBJECT_0
)
13046 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13050 static LRESULT WINAPI
send_msg_delay_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13052 if (message
== WM_USER
) Sleep(200);
13053 return MsgCheckProcA( hwnd
, message
, wParam
, lParam
);
13056 static void test_SendMessageTimeout(void)
13059 struct sendmsg_info info
;
13063 info
.ready
= CreateEventA( NULL
, 0, 0, NULL
);
13064 info
.hwnd
= CreateWindowA( "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
13065 100, 100, 200, 200, 0, 0, 0, NULL
);
13069 info
.timeout
= 1000;
13070 info
.ret
= 0xdeadbeef;
13071 ResetEvent( info
.ready
);
13072 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
13073 WaitForSingleObject( info
.ready
, INFINITE
);
13074 wait_for_thread( thread
);
13075 CloseHandle( thread
);
13076 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
13077 ok_sequence( WmUser
, "WmUser", FALSE
);
13080 info
.ret
= 0xdeadbeef;
13081 ResetEvent( info
.ready
);
13082 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
13083 WaitForSingleObject( info
.ready
, INFINITE
);
13084 Sleep(100); /* SendMessageTimeout should time out here */
13085 wait_for_thread( thread
);
13086 CloseHandle( thread
);
13087 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
13088 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
13090 /* 0 means infinite timeout (but not on win9x) */
13092 info
.ret
= 0xdeadbeef;
13093 ResetEvent( info
.ready
);
13094 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
13095 WaitForSingleObject( info
.ready
, INFINITE
);
13097 wait_for_thread( thread
);
13098 CloseHandle( thread
);
13099 is_win9x
= !info
.ret
;
13100 if (is_win9x
) ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
13101 else ok_sequence( WmUser
, "WmUser", FALSE
);
13103 /* timeout is treated as signed despite the prototype (but not on win9x) */
13104 info
.timeout
= 0x7fffffff;
13105 info
.ret
= 0xdeadbeef;
13106 ResetEvent( info
.ready
);
13107 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
13108 WaitForSingleObject( info
.ready
, INFINITE
);
13110 wait_for_thread( thread
);
13111 CloseHandle( thread
);
13112 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
13113 ok_sequence( WmUser
, "WmUser", FALSE
);
13115 info
.timeout
= 0x80000000;
13116 info
.ret
= 0xdeadbeef;
13117 ResetEvent( info
.ready
);
13118 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
13119 WaitForSingleObject( info
.ready
, INFINITE
);
13121 wait_for_thread( thread
);
13122 CloseHandle( thread
);
13125 ok( info
.ret
== 1, "SendMessageTimeout failed\n" );
13126 ok_sequence( WmUser
, "WmUser", FALSE
);
13130 ok( info
.ret
== 0, "SendMessageTimeout succeeded\n" );
13131 ok_sequence( WmEmptySeq
, "WmEmptySeq", FALSE
);
13134 /* now check for timeout during message processing */
13135 SetWindowLongPtrA( info
.hwnd
, GWLP_WNDPROC
, (LONG_PTR
)send_msg_delay_proc
);
13136 info
.timeout
= 100;
13137 info
.ret
= 0xdeadbeef;
13138 ResetEvent( info
.ready
);
13139 thread
= CreateThread( NULL
, 0, send_msg_thread
, &info
, 0, &tid
);
13140 WaitForSingleObject( info
.ready
, INFINITE
);
13141 wait_for_thread( thread
);
13142 CloseHandle( thread
);
13143 /* we should time out but still get the message */
13144 ok( info
.ret
== 0, "SendMessageTimeout failed\n" );
13145 ok_sequence( WmUser
, "WmUser", FALSE
);
13147 DestroyWindow( info
.hwnd
);
13148 CloseHandle( info
.ready
);
13152 /****************** edit message test *************************/
13153 #define ID_EDIT 0x1234
13154 static const struct message sl_edit_setfocus
[] =
13156 { HCBT_SETFOCUS
, hook
},
13157 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
13158 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13159 { EM_GETPASSWORDCHAR
, sent
|optional
}, /* Sent on some Win10 machines */
13160 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13161 { WM_SETFOCUS
, sent
|wparam
, 0 },
13162 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
13163 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 15 },
13164 { WM_CTLCOLOREDIT
, sent
|parent
},
13165 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13166 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13167 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13168 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
13171 static const struct message sl_edit_invisible
[] =
13173 { HCBT_SETFOCUS
, hook
},
13174 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
13175 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13176 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Sent for IME. */
13177 { WM_KILLFOCUS
, sent
|parent
},
13178 { EM_GETPASSWORDCHAR
, sent
|optional
}, /* Sent on some Win10 machines */
13179 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13180 { WM_SETFOCUS
, sent
},
13181 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13182 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13183 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
13186 static const struct message ml_edit_setfocus
[] =
13188 { HCBT_SETFOCUS
, hook
},
13189 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
13190 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13191 { EM_GETPASSWORDCHAR
, sent
|optional
}, /* Sent on some Win10 machines */
13192 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13193 { WM_SETFOCUS
, sent
|wparam
, 0 },
13194 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
13195 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13196 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13197 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13198 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
13199 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
13202 static const struct message sl_edit_killfocus
[] =
13204 { HCBT_SETFOCUS
, hook
},
13205 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
13206 { WM_KILLFOCUS
, sent
|wparam
, 0 },
13207 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13208 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13209 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_KILLFOCUS
) },
13210 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
13211 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
13214 static const struct message sl_edit_lbutton_dblclk
[] =
13216 { WM_LBUTTONDBLCLK
, sent
},
13217 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
13220 static const struct message sl_edit_lbutton_down
[] =
13222 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
13223 { HCBT_SETFOCUS
, hook
},
13224 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13225 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13226 { EM_GETPASSWORDCHAR
, sent
|defwinproc
|optional
}, /* Sent on some Win10 machines */
13227 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13228 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
13229 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
13230 { WM_CTLCOLOREDIT
, sent
|parent
},
13231 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13232 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13233 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
13234 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13235 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
13236 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
13237 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13238 { WM_CTLCOLOREDIT
, sent
|parent
|optional
},
13239 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13240 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CARET
, 0 },
13241 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13244 static const struct message ml_edit_lbutton_down
[] =
13246 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, 0 },
13247 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
13248 { HCBT_SETFOCUS
, hook
},
13249 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
13250 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
13251 { EM_GETPASSWORDCHAR
, sent
|defwinproc
|optional
}, /* Sent on some Win10 machines */
13252 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
13253 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
13254 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
13255 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
13256 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13257 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13258 { WM_COMMAND
, sent
|parent
|wparam
, MAKEWPARAM(ID_EDIT
, EN_SETFOCUS
) },
13261 static const struct message sl_edit_lbutton_up
[] =
13263 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
13264 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13265 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
13266 { WM_CAPTURECHANGED
, sent
|defwinproc
},
13267 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
13270 static const struct message ml_edit_lbutton_up
[] =
13272 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
13273 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
13274 { WM_CAPTURECHANGED
, sent
|defwinproc
},
13278 static WNDPROC old_edit_proc
;
13280 static LRESULT CALLBACK
edit_hook_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13282 static LONG defwndproc_counter
= 0;
13284 struct recvd_message msg
;
13286 if (ignore_message( message
)) return 0;
13289 msg
.message
= message
;
13290 msg
.flags
= sent
|wparam
|lparam
;
13291 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
13292 msg
.wParam
= wParam
;
13293 msg
.lParam
= lParam
;
13294 msg
.descr
= "edit";
13297 defwndproc_counter
++;
13298 ret
= CallWindowProcA(old_edit_proc
, hwnd
, message
, wParam
, lParam
);
13299 defwndproc_counter
--;
13304 static const struct message edit_wm_ime_composition_seq
[] =
13306 {WM_IME_STARTCOMPOSITION
, sent
},
13307 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13308 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'W'},
13309 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'i'},
13310 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'n'},
13311 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'e'},
13312 {WM_IME_ENDCOMPOSITION
, sent
},
13313 {WM_CHAR
, sent
| wparam
, 'W'},
13314 {WM_CHAR
, sent
| wparam
, 'i'},
13315 {WM_CHAR
, sent
| wparam
, 'n'},
13316 {WM_CHAR
, sent
| wparam
, 'e'},
13320 static const struct message edit_wm_ime_composition_korean_seq
[] =
13322 {WM_IME_ENDCOMPOSITION
, sent
},
13323 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13324 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'W'},
13325 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'i'},
13326 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'n'},
13327 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'e'},
13328 {WM_CHAR
, sent
| wparam
, 'W'},
13329 {WM_CHAR
, sent
| wparam
, 'i'},
13330 {WM_CHAR
, sent
| wparam
, 'n'},
13331 {WM_CHAR
, sent
| wparam
, 'e'},
13335 static const struct message edit_wm_ime_char_seq
[] =
13337 {WM_IME_CHAR
, sent
| wparam
, '0'},
13338 {WM_CHAR
, sent
| wparam
, '0'},
13342 static const struct message edit_eimes_getcompstratonce_seq
[] =
13344 {WM_IME_STARTCOMPOSITION
, sent
},
13345 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13346 {WM_IME_ENDCOMPOSITION
, sent
},
13350 static const struct message edit_eimes_getcompstratonce_korean_seq
[] =
13352 {WM_IME_ENDCOMPOSITION
, sent
},
13353 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
13357 static LRESULT CALLBACK
edit_ime_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
13359 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
13360 static LONG defwndproc_counter
= 0;
13361 struct recvd_message msg
= {0};
13364 msg
.message
= message
;
13365 msg
.flags
= sent
| wparam
;
13366 if (defwndproc_counter
)
13367 msg
.flags
|= defwinproc
;
13368 msg
.wParam
= wParam
;
13370 if (message
< 0xc000 &&
13371 message
!= WM_GETTEXTLENGTH
&&
13372 message
!= WM_GETTEXT
&&
13373 message
!= WM_GETFONT
&&
13374 message
!= WM_GETICON
&&
13375 message
!= WM_IME_SETCONTEXT
&&
13376 message
!= WM_IME_NOTIFY
&&
13377 message
!= WM_CTLCOLOREDIT
&&
13378 message
!= WM_PAINT
&&
13379 message
!= WM_ERASEBKGND
&&
13380 message
!= WM_NCHITTEST
&&
13381 message
!= WM_SETCURSOR
&&
13382 message
!= WM_MOUSEMOVE
&&
13383 message
!= WM_MOUSEACTIVATE
&&
13384 message
!= WM_KEYUP
&&
13385 (message
< EM_GETSEL
|| message
> EM_GETIMESTATUS
))
13390 defwndproc_counter
++;
13391 if (IsWindowUnicode(hwnd
))
13392 ret
= CallWindowProcW(oldproc
, hwnd
, message
, wParam
, lParam
);
13394 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
13395 defwndproc_counter
--;
13400 static DWORD WINAPI
test_edit_ime_messages(void *unused_arg
)
13402 static const HKL korean_hkl
= (HKL
)0x04120412;
13411 hkl
= GetKeyboardLayout(0);
13413 hwnd
= CreateWindowA(WC_EDITA
, "Test", WS_POPUP
| WS_VISIBLE
, 10, 10, 300, 300, NULL
, NULL
,
13415 ok(hwnd
!= NULL
, "CreateWindowA failed.\n");
13417 /* Test EM_{GET|SET}IMESTATUS */
13418 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13419 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13421 /* Note that EM_SETIMESTATUS always return 1, which is contrary to what MSDN says about
13422 * returning the previous LPARAM value */
13423 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
13424 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13425 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13426 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
13428 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_CANCELCOMPSTRINFOCUS
);
13429 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13430 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13431 ok(lr
== EIMES_CANCELCOMPSTRINFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
13433 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_COMPLETECOMPSTRKILLFOCUS
);
13434 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13435 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13436 ok(lr
== EIMES_COMPLETECOMPSTRKILLFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
13438 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
13439 | EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
);
13440 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13441 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13442 ok(lr
== (EIMES_GETCOMPSTRATONCE
| EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
),
13443 "Got unexpected lr %#Ix.\n", lr
);
13445 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13446 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13447 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13448 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13450 /* Invalid EM_{GET|SET}IMESTATUS status types and flags */
13451 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, 0, 0);
13452 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13454 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, 0);
13455 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13457 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, 0, EIMES_GETCOMPSTRATONCE
);
13458 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13459 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13460 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13462 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, EIMES_GETCOMPSTRATONCE
);
13463 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13464 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13465 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13467 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0xFFFFFFFF);
13468 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13469 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13470 ok(lr
== 0xFFFF, "Got unexpected lr %#Ix.\n", lr
);
13472 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13473 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13474 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13475 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
13477 /* Test IME messages when EIMES_GETCOMPSTRATONCE is not set */
13478 old_proc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)edit_ime_subclass_proc
);
13479 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)old_proc
);
13481 himc
= ImmGetContext(hwnd
);
13482 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
13483 ok(ret
, "ImmSetCompositionStringA failed.\n");
13485 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
13486 ok(ret
, "ImmNotifyIME failed.\n");
13487 /* Note that the following message loop is necessary to get the WM_CHAR messages because they
13488 * are posted. Same for the later message loops in this function. */
13489 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13490 if (hkl
== korean_hkl
)
13491 ok_sequence(edit_wm_ime_composition_korean_seq
,
13492 "korean WM_IME_COMPOSITION", TRUE
);
13494 ok_sequence(edit_wm_ime_composition_seq
, "WM_IME_COMPOSITION", TRUE
);
13496 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR */
13498 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
13499 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13500 ok_sequence(edit_wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
13502 /* Test IME messages when EIMES_GETCOMPSTRATONCE is set */
13503 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
13504 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
13505 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
13506 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
13508 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
13509 ok(ret
, "ImmSetCompositionStringA failed.\n");
13511 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
13512 ok(ret
, "ImmNotifyIME failed.\n");
13513 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13514 if (hkl
== korean_hkl
)
13515 ok_sequence(edit_eimes_getcompstratonce_korean_seq
,
13516 "korean WM_IME_COMPOSITION with EIMES_GETCOMPSTRATONCE", TRUE
);
13518 ok_sequence(edit_eimes_getcompstratonce_seq
,
13519 "WM_IME_COMPOSITION with EIMES_GETCOMPSTRATONCE", TRUE
);
13521 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR with EIMES_GETCOMPSTRATONCE */
13523 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
13524 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
13525 ok_sequence(edit_wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
13527 ImmReleaseContext(hwnd
, himc
);
13528 DestroyWindow(hwnd
);
13532 static void subclass_edit(void)
13537 ret
= GetClassInfoA(0, "edit", &cls
);
13538 ok(ret
, "Failed to get class info, error %lu.\n", GetLastError());
13540 old_edit_proc
= cls
.lpfnWndProc
;
13542 cls
.hInstance
= GetModuleHandleA(NULL
);
13543 cls
.lpfnWndProc
= edit_hook_proc
;
13544 cls
.lpszClassName
= "my_edit_class";
13545 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
13546 register_class(&cls
);
13549 static void test_edit_messages(void)
13556 log_all_parent_messages
++;
13558 parent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
13559 100, 100, 200, 200, 0, 0, 0, NULL
);
13560 ok (parent
!= 0, "Failed to create parent window\n");
13562 /* test single line edit */
13563 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
,
13564 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
13565 ok(hwnd
!= 0, "Failed to create edit window\n");
13567 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
13568 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
), "wrong dlg_code %08lx\n", dlg_code
);
13572 ok_sequence(sl_edit_invisible
, "SetFocus(hwnd) on an invisible edit", FALSE
);
13574 ShowWindow(hwnd
, SW_SHOW
);
13575 UpdateWindow(hwnd
);
13580 ok_sequence(sl_edit_setfocus
, "SetFocus(hwnd) on an edit", FALSE
);
13583 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on an edit", FALSE
);
13589 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
13590 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on an edit", FALSE
);
13596 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
13597 ok_sequence(sl_edit_lbutton_down
, "WM_LBUTTONDOWN on an edit", FALSE
);
13599 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
13600 ok_sequence(sl_edit_lbutton_up
, "WM_LBUTTONUP on an edit", FALSE
);
13602 DestroyWindow(hwnd
);
13604 /* test multiline edit */
13605 hwnd
= CreateWindowExA(0, "my_edit_class", "test", WS_CHILD
| ES_MULTILINE
,
13606 0, 0, 80, 20, parent
, (HMENU
)ID_EDIT
, 0, NULL
);
13607 ok(hwnd
!= 0, "Failed to create edit window\n");
13609 dlg_code
= SendMessageA(hwnd
, WM_GETDLGCODE
, 0, 0);
13610 ok(dlg_code
== (DLGC_WANTCHARS
|DLGC_HASSETSEL
|DLGC_WANTARROWS
|DLGC_WANTALLKEYS
),
13611 "wrong dlg_code %08lx\n", dlg_code
);
13613 ShowWindow(hwnd
, SW_SHOW
);
13614 UpdateWindow(hwnd
);
13619 ok_sequence(ml_edit_setfocus
, "SetFocus(hwnd) on multiline edit", FALSE
);
13622 ok_sequence(sl_edit_killfocus
, "SetFocus(0) on multiline edit", FALSE
);
13628 SendMessageA(hwnd
, WM_LBUTTONDBLCLK
, 0, 0);
13629 ok_sequence(sl_edit_lbutton_dblclk
, "WM_LBUTTONDBLCLK on multiline edit", FALSE
);
13635 SendMessageA(hwnd
, WM_LBUTTONDOWN
, 0, 0);
13636 ok_sequence(ml_edit_lbutton_down
, "WM_LBUTTONDOWN on multiline edit", FALSE
);
13638 SendMessageA(hwnd
, WM_LBUTTONUP
, 0, 0);
13639 ok_sequence(ml_edit_lbutton_up
, "WM_LBUTTONUP on multiline edit", FALSE
);
13641 DestroyWindow(hwnd
);
13642 DestroyWindow(parent
);
13644 log_all_parent_messages
--;
13646 /* Test IME messages in another thread because IME is disabled in the current thread */
13647 thread
= CreateThread(NULL
, 0, test_edit_ime_messages
, NULL
, 0, NULL
);
13648 WaitForSingleObject(thread
, INFINITE
);
13649 CloseHandle(thread
);
13652 /**************************** End of Edit test ******************************/
13654 static const struct message WmKeyDownSkippedSeq
[] =
13656 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 1 }, /* XP */
13659 static const struct message WmKeyDownWasDownSkippedSeq
[] =
13661 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0x40000001 }, /* XP */
13664 static const struct message WmKeyUpSkippedSeq
[] =
13666 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
13669 static const struct message WmUserKeyUpSkippedSeq
[] =
13672 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'N', 0xc0000001 }, /* XP */
13677 #define EV_SENDMSG 1
13680 struct peekmsg_info
13683 HANDLE hevent
[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
13686 static DWORD CALLBACK
send_msg_thread_2(void *param
)
13689 struct peekmsg_info
*info
= param
;
13691 if (winetest_debug
> 1) trace("thread: looping\n");
13692 SetEvent(info
->hevent
[EV_ACK
]);
13696 ret
= WaitForMultipleObjects(2, info
->hevent
, FALSE
, INFINITE
);
13700 case WAIT_OBJECT_0
+ EV_STOP
:
13701 if (winetest_debug
> 1) trace("thread: exiting\n");
13704 case WAIT_OBJECT_0
+ EV_SENDMSG
:
13705 if (winetest_debug
> 1) trace("thread: sending message\n");
13706 ret
= SendNotifyMessageA(info
->hwnd
, WM_USER
, 0, 0);
13707 ok(ret
, "SendNotifyMessageA failed error %lu\n", GetLastError());
13708 SetEvent(info
->hevent
[EV_ACK
]);
13712 ok(0, "Unexpected return %#lx.\n", ret
);
13719 static void test_PeekMessage(void)
13723 DWORD tid
, qstatus
;
13724 UINT qs_all_input
= QS_ALLINPUT
;
13725 UINT qs_input
= QS_INPUT
;
13726 BOOL ret
, broken_flags
= FALSE
;
13727 struct peekmsg_info info
;
13729 info
.hwnd
= CreateWindowA("TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
13730 100, 100, 200, 200, 0, 0, 0, NULL
);
13731 ok(!!info
.hwnd
, "Failed to create window, error %lu.\n", GetLastError());
13732 ShowWindow(info
.hwnd
, SW_SHOW
);
13733 UpdateWindow(info
.hwnd
);
13734 SetFocus(info
.hwnd
);
13736 info
.hevent
[EV_STOP
] = CreateEventA(NULL
, 0, 0, NULL
);
13737 info
.hevent
[EV_SENDMSG
] = CreateEventA(NULL
, 0, 0, NULL
);
13738 info
.hevent
[EV_ACK
] = CreateEventA(NULL
, 0, 0, NULL
);
13740 hthread
= CreateThread(NULL
, 0, send_msg_thread_2
, &info
, 0, &tid
);
13741 WaitForSingleObject(info
.hevent
[EV_ACK
], 10000);
13746 SetLastError(0xdeadbeef);
13747 qstatus
= GetQueueStatus(qs_all_input
);
13748 if (GetLastError() == ERROR_INVALID_FLAGS
)
13750 trace("QS_RAWINPUT not supported on this platform\n");
13751 qs_all_input
&= ~QS_RAWINPUT
;
13752 qs_input
&= ~QS_RAWINPUT
;
13754 SetLastError(0xdeadbeef);
13755 qstatus
= GetQueueStatus(qs_all_input
);
13756 if (GetLastError() == ERROR_INVALID_FLAGS
)
13757 broken_flags
= TRUE
;
13758 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_INVALID_FLAGS
) /* win7 */,
13759 "wrong error %ld\n", GetLastError());
13761 if (qstatus
& QS_POSTMESSAGE
)
13763 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) /* nothing */ ;
13764 qstatus
= GetQueueStatus(qs_all_input
);
13766 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
13768 if (winetest_debug
> 1) trace("signalling to send message\n");
13769 SetEvent(info
.hevent
[EV_SENDMSG
]);
13770 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13772 /* pass invalid QS_xxxx flags */
13773 SetLastError(0xdeadbeef);
13774 qstatus
= GetQueueStatus(0xffffffff);
13775 ok(qstatus
== 0 || broken(qstatus
) /* win9x */, "GetQueueStatus should fail: %08lx\n", qstatus
);
13778 ok(GetLastError() == ERROR_INVALID_FLAGS
, "wrong error %ld\n", GetLastError());
13779 SetLastError(0xdeadbeef);
13780 qstatus
= GetQueueStatus(qs_all_input
);
13781 ok(GetLastError() == 0xdeadbeef || broken(broken_flags
&& GetLastError() == ERROR_INVALID_FLAGS
),
13782 "wrong error %ld\n", GetLastError());
13784 qstatus
&= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */
13785 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
) ||
13786 broken(broken_flags
&& qstatus
== 0),
13787 "wrong qstatus %08lx\n", qstatus
);
13790 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
13792 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13794 ok_sequence(WmUser
, "WmUser", FALSE
);
13796 qstatus
= GetQueueStatus(qs_all_input
);
13797 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
13799 keybd_event('N', 0, 0, 0);
13800 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
13801 qstatus
= GetQueueStatus(qs_all_input
);
13802 if (!(qstatus
& MAKELONG(QS_KEY
, QS_KEY
)))
13804 skip( "queuing key events not supported\n" );
13807 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
) ||
13808 /* keybd_event seems to trigger a sent message on NT4 */
13809 qstatus
== MAKELONG(QS_KEY
|QS_SENDMESSAGE
, QS_KEY
|QS_SENDMESSAGE
),
13810 "wrong qstatus %08lx\n", qstatus
);
13812 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13813 qstatus
= GetQueueStatus(qs_all_input
);
13814 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
) ||
13815 qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
13816 "wrong qstatus %08lx\n", qstatus
);
13818 InvalidateRect(info
.hwnd
, NULL
, FALSE
);
13819 qstatus
= GetQueueStatus(qs_all_input
);
13820 ok(qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
) ||
13821 qstatus
== MAKELONG(QS_PAINT
, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
|QS_SENDMESSAGE
),
13822 "wrong qstatus %08lx\n", qstatus
);
13824 if (winetest_debug
> 1) trace("signalling to send message\n");
13825 SetEvent(info
.hevent
[EV_SENDMSG
]);
13826 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13828 qstatus
= GetQueueStatus(qs_all_input
);
13829 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13830 "wrong qstatus %08lx\n", qstatus
);
13833 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (qs_input
<< 16));
13834 if (ret
&& msg
.message
== WM_CHAR
)
13836 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
13840 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13842 if (!sequence_cnt
) /* nt4 doesn't fetch anything with PM_QS_* flags */
13844 win_skip( "PM_QS_* flags not supported in PeekMessage\n" );
13847 ok_sequence(WmUser
, "WmUser", FALSE
);
13849 qstatus
= GetQueueStatus(qs_all_input
);
13850 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13851 "wrong qstatus %08lx\n", qstatus
);
13853 if (winetest_debug
> 1) trace("signalling to send message\n");
13854 SetEvent(info
.hevent
[EV_SENDMSG
]);
13855 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13857 qstatus
= GetQueueStatus(qs_all_input
);
13858 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13859 "wrong qstatus %08lx\n", qstatus
);
13862 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
13864 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13866 ok_sequence(WmUser
, "WmUser", FALSE
);
13868 qstatus
= GetQueueStatus(qs_all_input
);
13869 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_POSTMESSAGE
|QS_KEY
),
13870 "wrong qstatus %08lx\n", qstatus
);
13873 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
13874 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13875 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13876 ret
, msg
.message
, msg
.wParam
);
13877 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13879 qstatus
= GetQueueStatus(qs_all_input
);
13880 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
13881 "wrong qstatus %08lx\n", qstatus
);
13884 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_POSTMESSAGE
);
13886 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13888 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13890 qstatus
= GetQueueStatus(qs_all_input
);
13891 ok(qstatus
== MAKELONG(0, QS_PAINT
|QS_KEY
),
13892 "wrong qstatus %08lx\n", qstatus
);
13895 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
13896 ok(ret
&& msg
.message
== WM_PAINT
,
13897 "got %d and %04x instead of TRUE and WM_PAINT\n", ret
, msg
.message
);
13898 DispatchMessageA(&msg
);
13899 ok_sequence(WmPaint
, "WmPaint", FALSE
);
13901 qstatus
= GetQueueStatus(qs_all_input
);
13902 ok(qstatus
== MAKELONG(0, QS_KEY
),
13903 "wrong qstatus %08lx\n", qstatus
);
13906 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_PAINT
);
13908 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13910 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13912 qstatus
= GetQueueStatus(qs_all_input
);
13913 ok(qstatus
== MAKELONG(0, QS_KEY
),
13914 "wrong qstatus %08lx\n", qstatus
);
13916 if (winetest_debug
> 1) trace("signalling to send message\n");
13917 SetEvent(info
.hevent
[EV_SENDMSG
]);
13918 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13920 qstatus
= GetQueueStatus(qs_all_input
);
13921 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_KEY
),
13922 "wrong qstatus %08lx\n", qstatus
);
13924 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13926 qstatus
= GetQueueStatus(qs_all_input
);
13927 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
13928 "wrong qstatus %08lx\n", qstatus
);
13931 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
13932 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
13933 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
13934 ret
, msg
.message
, msg
.wParam
);
13935 ok_sequence(WmUser
, "WmUser", FALSE
);
13937 qstatus
= GetQueueStatus(qs_all_input
);
13938 ok(qstatus
== MAKELONG(0, QS_KEY
),
13939 "wrong qstatus %08lx\n", qstatus
);
13942 ret
= PeekMessageA(&msg
, 0, WM_CHAR
, WM_CHAR
, PM_REMOVE
);
13944 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13946 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
13948 qstatus
= GetQueueStatus(qs_all_input
);
13949 ok(qstatus
== MAKELONG(0, QS_KEY
),
13950 "wrong qstatus %08lx\n", qstatus
);
13952 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
13954 qstatus
= GetQueueStatus(qs_all_input
);
13955 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
),
13956 "wrong qstatus %08lx\n", qstatus
);
13958 if (winetest_debug
> 1) trace("signalling to send message\n");
13959 SetEvent(info
.hevent
[EV_SENDMSG
]);
13960 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
13962 qstatus
= GetQueueStatus(qs_all_input
);
13963 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
13964 "wrong qstatus %08lx\n", qstatus
);
13967 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_KEY
<< 16));
13969 "PeekMessageA should have returned FALSE instead of msg %04x\n",
13971 ok_sequence(WmUser
, "WmUser", FALSE
);
13973 qstatus
= GetQueueStatus(qs_all_input
);
13974 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
13975 "wrong qstatus %08lx\n", qstatus
);
13978 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
13979 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
13980 else /* workaround for a missing QS_RAWINPUT support */
13981 ret
= PeekMessageA(&msg
, 0, WM_KEYDOWN
, WM_KEYDOWN
, PM_REMOVE
);
13982 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
13983 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
13984 ret
, msg
.message
, msg
.wParam
);
13985 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
13987 qstatus
= GetQueueStatus(qs_all_input
);
13988 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
|QS_KEY
),
13989 "wrong qstatus %08lx\n", qstatus
);
13992 if (qs_all_input
& QS_RAWINPUT
) /* use QS_RAWINPUT only if supported */
13993 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| (QS_RAWINPUT
<< 16));
13994 else /* workaround for a missing QS_RAWINPUT support */
13995 ret
= PeekMessageA(&msg
, 0, WM_KEYUP
, WM_KEYUP
, PM_REMOVE
);
13996 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
13997 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYUP wParam 'N'\n",
13998 ret
, msg
.message
, msg
.wParam
);
13999 ok_sequence(WmKeyUpSkippedSeq
, "WmKeyUpSkippedSeq", FALSE
);
14001 qstatus
= GetQueueStatus(qs_all_input
);
14002 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
14003 "wrong qstatus %08lx\n", qstatus
);
14006 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
14008 "PeekMessageA should have returned FALSE instead of msg %04x\n",
14010 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
14012 qstatus
= GetQueueStatus(qs_all_input
);
14013 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
14014 "wrong qstatus %08lx\n", qstatus
);
14017 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
14018 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
14019 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
14020 ret
, msg
.message
, msg
.wParam
);
14021 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
14023 qstatus
= GetQueueStatus(qs_all_input
);
14025 "wrong qstatus %08lx\n", qstatus
);
14028 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
14030 "PeekMessageA should have returned FALSE instead of msg %04x\n",
14032 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
14034 qstatus
= GetQueueStatus(qs_all_input
);
14036 "wrong qstatus %08lx\n", qstatus
);
14038 /* test whether presence of the quit flag in the queue affects
14041 PostQuitMessage(0x1234abcd);
14043 qstatus
= GetQueueStatus(qs_all_input
);
14044 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
14045 "wrong qstatus %08lx\n", qstatus
);
14047 PostMessageA(info
.hwnd
, WM_USER
, 0, 0);
14049 qstatus
= GetQueueStatus(qs_all_input
);
14050 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
),
14051 "wrong qstatus %08lx\n", qstatus
);
14054 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
14055 ok(ret
&& msg
.message
== WM_USER
,
14056 "got %d and %04x instead of TRUE and WM_USER\n", ret
, msg
.message
);
14057 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
14059 qstatus
= GetQueueStatus(qs_all_input
);
14060 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
14061 "wrong qstatus %08lx\n", qstatus
);
14064 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
14065 ok(ret
&& msg
.message
== WM_QUIT
,
14066 "got %d and %04x instead of TRUE and WM_QUIT\n", ret
, msg
.message
);
14067 ok(msg
.wParam
== 0x1234abcd, "got wParam %08Ix instead of 0x1234abcd\n", msg
.wParam
);
14068 ok(msg
.lParam
== 0, "got lParam %08Ix instead of 0\n", msg
.lParam
);
14069 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
14071 qstatus
= GetQueueStatus(qs_all_input
);
14073 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
),
14074 "wrong qstatus %08lx\n", qstatus
);
14078 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
14080 "PeekMessageA should have returned FALSE instead of msg %04x\n",
14082 ok_sequence(WmEmptySeq
, "WmEmptySeq", FALSE
);
14084 qstatus
= GetQueueStatus(qs_all_input
);
14086 "wrong qstatus %08lx\n", qstatus
);
14088 /* some GetMessage tests */
14090 keybd_event('N', 0, 0, 0);
14091 qstatus
= GetQueueStatus(qs_all_input
);
14092 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
14094 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
14095 qstatus
= GetQueueStatus(qs_all_input
);
14096 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
14100 ret
= GetMessageA( &msg
, 0, 0, 0 );
14101 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
14102 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
14103 ret
, msg
.message
, msg
.wParam
);
14104 qstatus
= GetQueueStatus(qs_all_input
);
14105 ok(qstatus
== MAKELONG(0, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
14110 ret
= GetMessageA( &msg
, 0, 0, 0 );
14111 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
14112 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
14113 ret
, msg
.message
, msg
.wParam
);
14114 ok_sequence(WmKeyDownSkippedSeq
, "WmKeyDownSkippedSeq", FALSE
);
14115 qstatus
= GetQueueStatus(qs_all_input
);
14116 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
14119 keybd_event('N', 0, 0, 0);
14120 qstatus
= GetQueueStatus(qs_all_input
);
14121 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
14123 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
14124 qstatus
= GetQueueStatus(qs_all_input
);
14125 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
14127 if (qstatus
& (QS_KEY
<< 16))
14129 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
14130 ok(ret
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== 'N',
14131 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
14132 ret
, msg
.message
, msg
.wParam
);
14133 ok_sequence(WmKeyDownWasDownSkippedSeq
, "WmKeyDownWasDownSkippedSeq", FALSE
);
14134 qstatus
= GetQueueStatus(qs_all_input
);
14135 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08lx\n", qstatus
);
14140 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
14141 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
14142 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
14143 ret
, msg
.message
, msg
.wParam
);
14144 qstatus
= GetQueueStatus(qs_all_input
);
14145 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
14148 keybd_event('N', 0, KEYEVENTF_KEYUP
, 0);
14149 qstatus
= GetQueueStatus(qs_all_input
);
14150 ok(qstatus
== MAKELONG(QS_KEY
, QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
14152 PostMessageA(info
.hwnd
, WM_CHAR
, 'z', 0);
14153 qstatus
= GetQueueStatus(qs_all_input
);
14154 ok(qstatus
== MAKELONG(QS_POSTMESSAGE
, QS_POSTMESSAGE
|QS_KEY
), "wrong qstatus %08lx\n", qstatus
);
14156 if (winetest_debug
> 1) trace("signalling to send message\n");
14157 SetEvent(info
.hevent
[EV_SENDMSG
]);
14158 WaitForSingleObject(info
.hevent
[EV_ACK
], INFINITE
);
14159 qstatus
= GetQueueStatus(qs_all_input
);
14160 ok(qstatus
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
|QS_KEY
),
14161 "wrong qstatus %08lx\n", qstatus
);
14163 if (qstatus
& (QS_KEY
<< 16))
14165 ret
= GetMessageA( &msg
, 0, WM_KEYDOWN
, WM_KEYUP
);
14166 ok(ret
&& msg
.message
== WM_KEYUP
&& msg
.wParam
== 'N',
14167 "got %d and %04x wParam %08Ix instead of TRUE and WM_KEYDOWN wParam 'N'\n",
14168 ret
, msg
.message
, msg
.wParam
);
14169 ok_sequence(WmUserKeyUpSkippedSeq
, "WmUserKeyUpSkippedSeq", FALSE
);
14170 qstatus
= GetQueueStatus(qs_all_input
);
14171 ok(qstatus
== MAKELONG(0, QS_POSTMESSAGE
), "wrong qstatus %08lx\n", qstatus
);
14176 ret
= GetMessageA( &msg
, 0, WM_CHAR
, WM_CHAR
);
14177 ok(ret
&& msg
.message
== WM_CHAR
&& msg
.wParam
== 'z',
14178 "got %d and %04x wParam %08Ix instead of TRUE and WM_CHAR wParam 'z'\n",
14179 ret
, msg
.message
, msg
.wParam
);
14180 qstatus
= GetQueueStatus(qs_all_input
);
14181 ok(qstatus
== 0, "wrong qstatus %08lx\n", qstatus
);
14184 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
14185 ret
= PeekMessageA(&msg
, (HWND
)-1, 0, 0, PM_NOREMOVE
);
14186 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
14187 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
14188 ret
= GetMessageA(&msg
, (HWND
)-1, 0, 0);
14189 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
14190 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
14192 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
14193 ret
= PeekMessageA(&msg
, (HWND
)1, 0, 0, PM_NOREMOVE
);
14194 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
14195 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
14196 ret
= GetMessageA(&msg
, (HWND
)1, 0, 0);
14197 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
14198 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
14200 PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
14201 ret
= PeekMessageA(&msg
, (HWND
)0xffff, 0, 0, PM_NOREMOVE
);
14202 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
14203 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
14204 ret
= GetMessageA(&msg
, (HWND
)0xffff, 0, 0);
14205 ok(ret
== TRUE
, "wrong ret %d\n", ret
);
14206 ok(msg
.message
== WM_USER
, "wrong message %u\n", msg
.message
);
14209 if (winetest_debug
> 1) trace("signalling to exit\n");
14210 SetEvent(info
.hevent
[EV_STOP
]);
14212 WaitForSingleObject(hthread
, INFINITE
);
14214 CloseHandle(hthread
);
14215 CloseHandle(info
.hevent
[0]);
14216 CloseHandle(info
.hevent
[1]);
14217 CloseHandle(info
.hevent
[2]);
14219 DestroyWindow(info
.hwnd
);
14222 static void wait_move_event(HWND hwnd
, int x
, int y
)
14225 DWORD timeout
= GetTickCount() + 500;
14229 while ((delay
= timeout
- GetTickCount()) > 0)
14231 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
14232 if (ret
&& msg
.pt
.x
> x
&& msg
.pt
.y
> y
) break;
14233 if (!ret
) MsgWaitForMultipleObjects( 0, NULL
, FALSE
, delay
, QS_ALLINPUT
);
14234 else Sleep( delay
);
14239 static void test_PeekMessage2(void)
14245 DWORD time1
, time2
, time3
;
14246 int x1
, y1
, x2
, y2
, x3
, y3
;
14249 time1
= time2
= time3
= 0;
14250 x1
= y1
= x2
= y2
= x3
= y3
= 0;
14252 /* Initialise window and make sure it is ready for events */
14253 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW
,
14254 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
14255 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
14256 if (winetest_debug
> 1) trace("Window for test_PeekMessage2 %p\n", hwnd
);
14257 ShowWindow(hwnd
, SW_SHOW
);
14258 UpdateWindow(hwnd
);
14260 GetCursorPos(&pos
);
14261 SetCursorPos(100, 100);
14262 mouse_event(MOUSEEVENTF_MOVE
, -STEP
, -STEP
, 0, 0);
14265 /* Do initial mousemove, wait until we can see it
14266 and then do our test peek with PM_NOREMOVE. */
14267 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
14268 wait_move_event(hwnd
, 100-STEP
, 100-STEP
);
14270 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
14273 skip( "queuing mouse events not supported\n" );
14278 if (winetest_debug
> 1) trace("1st move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
14279 message
= msg
.message
;
14283 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
14286 /* Allow time to advance a bit, and then simulate the user moving their
14287 * mouse around. After that we peek again with PM_NOREMOVE.
14288 * Although the previous mousemove message was never removed, the
14289 * mousemove we now peek should reflect the recent mouse movements
14290 * because the input queue will merge the move events. */
14292 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
14293 wait_move_event(hwnd
, x1
, y1
);
14295 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
14296 ok(ret
, "no message available\n");
14298 if (winetest_debug
> 1) trace("2nd move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
14299 message
= msg
.message
;
14303 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
14304 ok(time2
> time1
, "message time not advanced: %lx %lx\n", time1
, time2
);
14305 ok(x2
!= x1
&& y2
!= y1
, "coords not changed: (%d %d) (%d %d)\n", x1
, y1
, x2
, y2
);
14308 /* Have another go, to drive the point home */
14310 mouse_event(MOUSEEVENTF_MOVE
, STEP
, STEP
, 0, 0);
14311 wait_move_event(hwnd
, x2
, y2
);
14313 ret
= PeekMessageA(&msg
, hwnd
, WM_MOUSEMOVE
, WM_MOUSEMOVE
, PM_NOREMOVE
);
14314 ok(ret
, "no message available\n");
14316 if (winetest_debug
> 1) trace("3rd move event: %04x %lx %ld %ld\n", msg
.message
, msg
.time
, msg
.pt
.x
, msg
.pt
.y
);
14317 message
= msg
.message
;
14321 ok(message
== WM_MOUSEMOVE
, "message not WM_MOUSEMOVE, %04x instead\n", message
);
14322 ok(time3
> time2
, "message time not advanced: %lx %lx\n", time2
, time3
);
14323 ok(x3
!= x2
&& y3
!= y2
, "coords not changed: (%d %d) (%d %d)\n", x2
, y2
, x3
, y3
);
14327 DestroyWindow(hwnd
);
14328 SetCursorPos(pos
.x
, pos
.y
);
14332 static void test_PeekMessage3(void)
14334 HWND parent_hwnd
, hwnd
;
14338 parent_hwnd
= CreateWindowA("SimpleWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW
,
14339 10, 10, 800, 800, NULL
, NULL
, NULL
, NULL
);
14340 ok(parent_hwnd
!= NULL
, "expected parent_hwnd != NULL\n");
14342 hwnd
= CreateWindowA("TestWindowClass", "PeekMessage3", WS_CHILD
, 0, 0, 1, 1,
14343 parent_hwnd
, NULL
, NULL
, NULL
);
14344 ok(hwnd
!= NULL
, "expected hwnd != NULL\n");
14348 /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
14349 * were already seen. */
14351 SetTimer(hwnd
, 1, 100, NULL
);
14352 while (!PeekMessageA(&msg
, hwnd
, 0, 0, PM_NOREMOVE
));
14353 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14354 PostMessageA(hwnd
, WM_USER
, 0, 0);
14355 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, PM_NOREMOVE
);
14357 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14358 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14360 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14361 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14363 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14364 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14365 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14367 SetTimer(hwnd
, 1, 100, NULL
);
14368 while (!PeekMessageA(&msg
, hwnd
, 0, 0, PM_NOREMOVE
));
14369 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14370 PostMessageA(hwnd
, WM_USER
, 0, 0);
14371 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, PM_REMOVE
);
14373 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14374 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, PM_REMOVE
);
14376 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14377 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14378 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14380 /* It doesn't matter if a message range is specified or not. */
14382 SetTimer(hwnd
, 1, 100, NULL
);
14383 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14384 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14385 PostMessageA(hwnd
, WM_USER
, 0, 0);
14386 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14388 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14389 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14391 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14392 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14393 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14395 /* But not if the post messages were added before the PeekMessage() call. */
14397 PostMessageA(hwnd
, WM_USER
, 0, 0);
14398 SetTimer(hwnd
, 1, 100, NULL
);
14399 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14400 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14401 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14402 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14403 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14404 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14405 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14406 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14408 /* More complicated test with multiple messages. */
14410 PostMessageA(hwnd
, WM_USER
, 0, 0);
14411 SetTimer(hwnd
, 1, 100, NULL
);
14412 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14413 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14414 PostMessageA(hwnd
, WM_USER
+ 1, 0, 0);
14415 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14416 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14417 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14419 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14420 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14422 ok(ret
&& msg
.message
== WM_USER
+ 1, "msg.message = %u instead of WM_USER + 1\n", msg
.message
);
14423 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14424 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14426 /* Also works for posted messages, but the situation is a bit different,
14427 * because both messages are in the same queue. */
14429 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
14430 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14431 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14432 PostMessageA(hwnd
, WM_USER
, 0, 0);
14433 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14434 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14435 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14436 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14437 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14438 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14440 PostMessageA(hwnd
, WM_USER
, 0, 0);
14441 PostMessageA(hwnd
, WM_TIMER
, 0, 0);
14442 while (!PeekMessageA(&msg
, hwnd
, WM_TIMER
, WM_TIMER
, PM_NOREMOVE
));
14443 ok(msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14444 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14445 ok(ret
&& msg
.message
== WM_USER
, "msg.message = %u instead of WM_USER\n", msg
.message
);
14446 ret
= GetMessageA(&msg
, hwnd
, 0, 0);
14447 ok(ret
&& msg
.message
== WM_TIMER
, "msg.message = %u instead of WM_TIMER\n", msg
.message
);
14448 ret
= PeekMessageA(&msg
, hwnd
, 0, 0, 0);
14449 ok(!ret
, "expected PeekMessage to return FALSE, got %u\n", ret
);
14451 DestroyWindow(parent_hwnd
);
14455 static INT_PTR CALLBACK
wm_quit_dlg_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
14457 struct recvd_message msg
;
14459 if (ignore_message( message
)) return 0;
14462 msg
.message
= message
;
14463 msg
.flags
= sent
|wparam
|lparam
;
14466 msg
.descr
= "dialog";
14471 case WM_INITDIALOG
:
14472 PostMessageA(hwnd
, WM_QUIT
, 0x1234, 0x5678);
14473 PostMessageA(hwnd
, WM_USER
, 0xdead, 0xbeef);
14476 case WM_GETDLGCODE
:
14480 EndDialog(hwnd
, 0);
14487 static const struct message WmQuitDialogSeq
[] = {
14488 { HCBT_CREATEWND
, hook
},
14489 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14490 { WM_SETFONT
, sent
},
14491 { WM_INITDIALOG
, sent
},
14492 { WM_CHANGEUISTATE
, sent
|optional
},
14493 { EVENT_SYSTEM_DIALOGEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
14494 { HCBT_DESTROYWND
, hook
},
14495 { 0x0090, sent
|optional
}, /* Vista */
14496 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
14497 { WM_DESTROY
, sent
},
14498 { WM_NCDESTROY
, sent
},
14502 static const struct message WmStopQuitSeq
[] = {
14503 { WM_DWMNCRENDERINGCHANGED
, posted
|optional
},
14504 { WM_CLOSE
, posted
},
14505 { WM_QUIT
, posted
|wparam
|lparam
, 0x1234, 0 },
14509 static void test_quit_message(void)
14514 /* test using PostQuitMessage */
14516 PostQuitMessage(0xbeef);
14519 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_QS_SENDMESSAGE
);
14520 ok(!ret
, "got %x message\n", msg
.message
);
14522 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
14523 ok(ret
, "PeekMessage failed with error %ld\n", GetLastError());
14524 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14525 ok(msg
.wParam
== 0xbeef, "wParam was 0x%Ix instead of 0xbeef\n", msg
.wParam
);
14527 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
14528 ok(ret
, "PostMessage failed with error %ld\n", GetLastError());
14530 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14531 ok(ret
> 0, "GetMessage failed with error %ld\n", GetLastError());
14532 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
14534 /* note: WM_QUIT message received after WM_USER message */
14535 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14536 ok(!ret
, "GetMessage return %d with error %ld instead of FALSE\n", ret
, GetLastError());
14537 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14538 ok(msg
.wParam
== 0xbeef, "wParam was 0x%Ix instead of 0xbeef\n", msg
.wParam
);
14540 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
14541 ok( !ret
|| msg
.message
!= WM_QUIT
, "Received WM_QUIT again\n" );
14543 /* now test with PostThreadMessage - different behaviour! */
14544 PostThreadMessageA(GetCurrentThreadId(), WM_QUIT
, 0xdead, 0);
14546 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
14547 ok(ret
, "PeekMessage failed with error %ld\n", GetLastError());
14548 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14549 ok(msg
.wParam
== 0xdead, "wParam was 0x%Ix instead of 0xdead\n", msg
.wParam
);
14551 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_USER
, 0, 0);
14552 ok(ret
, "PostMessage failed with error %ld\n", GetLastError());
14554 /* note: we receive the WM_QUIT message first this time */
14555 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14556 ok(!ret
, "GetMessage return %d with error %ld instead of FALSE\n", ret
, GetLastError());
14557 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14558 ok(msg
.wParam
== 0xdead, "wParam was 0x%Ix instead of 0xdead\n", msg
.wParam
);
14560 ret
= GetMessageA(&msg
, NULL
, 0, 0);
14561 ok(ret
> 0, "GetMessage failed with error %ld\n", GetLastError());
14562 ok(msg
.message
== WM_USER
, "Received message 0x%04x instead of WM_USER\n", msg
.message
);
14566 ret
= DialogBoxParamA(GetModuleHandleA(NULL
), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc
, 0);
14567 ok(ret
== 1, "expected 1, got %d\n", ret
);
14568 ok_sequence(WmQuitDialogSeq
, "WmQuitDialogSeq", FALSE
);
14569 memset(&msg
, 0xab, sizeof(msg
));
14570 ret
= PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
);
14571 ok(ret
, "PeekMessage failed\n");
14572 ok(msg
.message
== WM_QUIT
, "Received message 0x%04x instead of WM_QUIT\n", msg
.message
);
14573 ok(msg
.wParam
== 0x1234, "wParam was 0x%Ix instead of 0x1234\n", msg
.wParam
);
14574 ok(msg
.lParam
== 0, "lParam was 0x%Ix instead of 0\n", msg
.lParam
);
14576 /* Check what happens to a WM_QUIT message posted to a window that gets
14579 CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW
,
14580 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
14582 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14584 struct recvd_message rmsg
;
14585 rmsg
.hwnd
= msg
.hwnd
;
14586 rmsg
.message
= msg
.message
;
14587 rmsg
.flags
= posted
|wparam
|lparam
;
14588 rmsg
.wParam
= msg
.wParam
;
14589 rmsg
.lParam
= msg
.lParam
;
14590 rmsg
.descr
= "stop/quit";
14591 if (msg
.message
== WM_QUIT
)
14592 /* The hwnd can only be checked here */
14593 ok(!msg
.hwnd
, "The WM_QUIT hwnd was %p instead of NULL\n", msg
.hwnd
);
14594 add_message(&rmsg
);
14595 DispatchMessageA(&msg
);
14597 ok_sequence(WmStopQuitSeq
, "WmStopQuitSeq", FALSE
);
14600 static const struct message WmNotifySeq
[] = {
14601 { WM_NOTIFY
, sent
|wparam
|lparam
, 0x1234, 0xdeadbeef },
14605 static void test_notify_message(void)
14611 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
14612 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0, NULL
, NULL
, 0);
14613 ok(hwnd
!= 0, "Failed to create window\n");
14617 ret
= SendNotifyMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14618 ok(ret
== TRUE
, "SendNotifyMessageA failed with error %lu\n", GetLastError());
14619 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14621 ret
= SendNotifyMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14622 ok(ret
== TRUE
, "SendNotifyMessageW failed with error %lu\n", GetLastError());
14623 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14625 ret
= SendMessageCallbackA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
14626 ok(ret
== TRUE
, "SendMessageCallbackA failed with error %lu\n", GetLastError());
14627 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14629 ret
= SendMessageCallbackW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef, NULL
, 0);
14630 ok(ret
== TRUE
, "SendMessageCallbackW failed with error %lu\n", GetLastError());
14631 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14633 ret
= PostMessageA(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14634 ok(ret
== TRUE
, "PostMessageA failed with error %lu\n", GetLastError());
14636 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14638 ret
= PostMessageW(hwnd
, WM_NOTIFY
, 0x1234, 0xdeadbeef);
14639 ok(ret
== TRUE
, "PostMessageW failed with error %lu\n", GetLastError());
14641 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14643 ret
= PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
14644 ok(ret
== TRUE
, "PostThreadMessageA failed with error %lu\n", GetLastError());
14645 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14648 DispatchMessageA(&msg
);
14650 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14652 ret
= PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY
, 0x1234, 0xdeadbeef);
14653 ok(ret
== TRUE
, "PostThreadMessageW failed with error %lu\n", GetLastError());
14654 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14657 DispatchMessageA(&msg
);
14659 ok_sequence(WmNotifySeq
, "WmNotifySeq", FALSE
);
14661 DestroyWindow(hwnd
);
14664 static const struct message WmMouseHoverSeq
[] = {
14665 { WM_GETMINMAXINFO
, sent
|optional
}, /* sometimes seen on w1064v1809 */
14666 { WM_MOUSEACTIVATE
, sent
|optional
}, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */
14667 { WM_MOUSEACTIVATE
, sent
|optional
},
14668 { WM_TIMER
, sent
|optional
}, /* XP sends it */
14669 { WM_SYSTIMER
, sent
},
14670 { WM_MOUSEHOVER
, sent
|wparam
, 0 },
14674 static void pump_msg_loop_timeout(DWORD timeout
, BOOL inject_mouse_move
)
14677 DWORD start_ticks
, end_ticks
;
14679 start_ticks
= GetTickCount();
14680 /* add some deviation (50%) to cover not expected delays */
14681 start_ticks
+= timeout
/ 2;
14685 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
14687 /* Timer proc messages are not dispatched to the window proc,
14688 * and therefore not logged.
14690 if ((msg
.message
== WM_TIMER
|| msg
.message
== WM_SYSTIMER
) && msg
.hwnd
)
14692 struct recvd_message s_msg
;
14694 s_msg
.hwnd
= msg
.hwnd
;
14695 s_msg
.message
= msg
.message
;
14696 s_msg
.flags
= sent
|wparam
|lparam
;
14697 s_msg
.wParam
= msg
.wParam
;
14698 s_msg
.lParam
= msg
.lParam
;
14699 s_msg
.descr
= "msg_loop";
14700 add_message(&s_msg
);
14702 DispatchMessageA(&msg
);
14705 end_ticks
= GetTickCount();
14707 /* inject WM_MOUSEMOVE to see how it changes tracking */
14708 if (inject_mouse_move
&& start_ticks
+ timeout
/ 2 >= end_ticks
)
14710 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
14711 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
14713 inject_mouse_move
= FALSE
;
14715 } while (start_ticks
+ timeout
>= end_ticks
);
14718 static void test_TrackMouseEvent(void)
14720 TRACKMOUSEEVENT tme
;
14723 RECT rc_parent
, rc_child
;
14724 UINT default_hover_time
, hover_width
= 0, hover_height
= 0;
14726 #define track_hover(track_hwnd, track_hover_time) \
14727 tme.cbSize = sizeof(tme); \
14728 tme.dwFlags = TME_HOVER; \
14729 tme.hwndTrack = track_hwnd; \
14730 tme.dwHoverTime = track_hover_time; \
14731 SetLastError(0xdeadbeef); \
14732 ret = pTrackMouseEvent(&tme); \
14733 ok(ret, "TrackMouseEvent(TME_HOVER) error %ld\n", GetLastError())
14735 #define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \
14736 tme.cbSize = sizeof(tme); \
14737 tme.dwFlags = TME_QUERY; \
14738 tme.hwndTrack = (HWND)0xdeadbeef; \
14739 tme.dwHoverTime = 0xdeadbeef; \
14740 SetLastError(0xdeadbeef); \
14741 ret = pTrackMouseEvent(&tme); \
14742 ok(ret, "TrackMouseEvent(TME_QUERY) error %ld\n", GetLastError());\
14743 ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %lu\n", tme.cbSize); \
14744 ok(tme.dwFlags == (expected_track_flags), \
14745 "wrong tme.dwFlags %08lx, expected %08x\n", tme.dwFlags, (expected_track_flags)); \
14746 ok(tme.hwndTrack == (expected_track_hwnd), \
14747 "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \
14748 ok(tme.dwHoverTime == (expected_hover_time), \
14749 "wrong tme.dwHoverTime %lu, expected %u\n", tme.dwHoverTime, (expected_hover_time))
14751 #define track_hover_cancel(track_hwnd) \
14752 tme.cbSize = sizeof(tme); \
14753 tme.dwFlags = TME_HOVER | TME_CANCEL; \
14754 tme.hwndTrack = track_hwnd; \
14755 tme.dwHoverTime = 0xdeadbeef; \
14756 SetLastError(0xdeadbeef); \
14757 ret = pTrackMouseEvent(&tme); \
14758 ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %ld\n", GetLastError())
14760 default_hover_time
= 0xdeadbeef;
14761 SetLastError(0xdeadbeef);
14762 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &default_hover_time
, 0);
14763 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
14764 "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %lu\n", GetLastError());
14765 if (!ret
) default_hover_time
= 400;
14766 if (winetest_debug
> 1) trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time
);
14768 SetLastError(0xdeadbeef);
14769 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hover_width
, 0);
14770 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
14771 "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %lu\n", GetLastError());
14772 if (!ret
) hover_width
= 4;
14773 SetLastError(0xdeadbeef);
14774 ret
= SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hover_height
, 0);
14775 ok(ret
|| broken(GetLastError() == 0xdeadbeef), /* win9x */
14776 "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %lu\n", GetLastError());
14777 if (!ret
) hover_height
= 4;
14778 if (winetest_debug
> 1) trace("hover rect is %u x %d\n", hover_width
, hover_height
);
14780 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
,
14781 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
14782 CW_USEDEFAULT
, CW_USEDEFAULT
, 300, 300, 0,
14784 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
14786 hchild
= CreateWindowExA(0, "TestWindowClass", NULL
,
14787 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
14788 50, 50, 200, 200, hwnd
,
14790 ok(!!hchild
, "Failed to create window, error %lu.\n", GetLastError());
14792 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
14797 tme
.dwFlags
= TME_QUERY
;
14798 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14799 tme
.dwHoverTime
= 0xdeadbeef;
14800 SetLastError(0xdeadbeef);
14801 ret
= pTrackMouseEvent(&tme
);
14802 ok(!ret
, "TrackMouseEvent should fail\n");
14803 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef),
14804 "not expected error %lu\n", GetLastError());
14806 tme
.cbSize
= sizeof(tme
);
14807 tme
.dwFlags
= TME_HOVER
;
14808 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14809 tme
.dwHoverTime
= 0xdeadbeef;
14810 SetLastError(0xdeadbeef);
14811 ret
= pTrackMouseEvent(&tme
);
14812 ok(!ret
, "TrackMouseEvent should fail\n");
14813 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14814 "not expected error %lu\n", GetLastError());
14816 tme
.cbSize
= sizeof(tme
);
14817 tme
.dwFlags
= TME_HOVER
| TME_CANCEL
;
14818 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14819 tme
.dwHoverTime
= 0xdeadbeef;
14820 SetLastError(0xdeadbeef);
14821 ret
= pTrackMouseEvent(&tme
);
14822 ok(!ret
, "TrackMouseEvent should fail\n");
14823 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
14824 "not expected error %lu\n", GetLastError());
14826 GetWindowRect(hwnd
, &rc_parent
);
14827 GetWindowRect(hchild
, &rc_child
);
14828 SetCursorPos(rc_child
.left
- 10, rc_child
.top
- 10);
14830 /* Process messages so that the system updates its internal current
14831 * window and hittest, otherwise TrackMouseEvent calls don't have any
14837 track_query(0, NULL
, 0);
14838 track_hover(hchild
, 0);
14839 track_query(0, NULL
, 0);
14844 track_hover(hwnd
, 0);
14845 tme
.cbSize
= sizeof(tme
);
14846 tme
.dwFlags
= TME_QUERY
;
14847 tme
.hwndTrack
= (HWND
)0xdeadbeef;
14848 tme
.dwHoverTime
= 0xdeadbeef;
14849 SetLastError(0xdeadbeef);
14850 ret
= pTrackMouseEvent(&tme
);
14851 ok(ret
, "TrackMouseEvent(TME_QUERY) error %ld\n", GetLastError());
14852 ok(tme
.cbSize
== sizeof(tme
), "wrong tme.cbSize %lu\n", tme
.cbSize
);
14855 skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" );
14856 DestroyWindow( hwnd
);
14859 ok(tme
.dwFlags
== TME_HOVER
, "wrong tme.dwFlags %08lx, expected TME_HOVER\n", tme
.dwFlags
);
14860 ok(tme
.hwndTrack
== hwnd
, "wrong tme.hwndTrack %p, expected %p\n", tme
.hwndTrack
, hwnd
);
14861 ok(tme
.dwHoverTime
== default_hover_time
, "wrong tme.dwHoverTime %lu, expected %u\n",
14862 tme
.dwHoverTime
, default_hover_time
);
14864 pump_msg_loop_timeout(default_hover_time
, FALSE
);
14865 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
14867 track_query(0, NULL
, 0);
14869 track_hover(hwnd
, HOVER_DEFAULT
);
14870 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14872 Sleep(default_hover_time
/ 2);
14873 mouse_event(MOUSEEVENTF_MOVE
, -1, 0, 0, 0);
14874 mouse_event(MOUSEEVENTF_MOVE
, 1, 0, 0, 0);
14876 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14878 pump_msg_loop_timeout(default_hover_time
, FALSE
);
14879 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
14881 track_query(0, NULL
, 0);
14883 track_hover(hwnd
, HOVER_DEFAULT
);
14884 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14886 pump_msg_loop_timeout(default_hover_time
, TRUE
);
14887 ok_sequence(WmMouseHoverSeq
, "WmMouseHoverSeq", FALSE
);
14889 track_query(0, NULL
, 0);
14891 track_hover(hwnd
, HOVER_DEFAULT
);
14892 track_query(TME_HOVER
, hwnd
, default_hover_time
);
14893 track_hover_cancel(hwnd
);
14895 DestroyWindow(hwnd
);
14899 #undef track_hover_cancel
14903 static const struct message WmSetWindowRgn
[] = {
14904 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
14905 |SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
, 0 },
14906 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
14907 { WM_NCPAINT
, sent
|optional
}, /* wparam != 1 */
14908 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14909 { WM_ERASEBKGND
, sent
|optional
},
14910 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
14911 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14915 static const struct message WmSetWindowRgn_no_redraw
[] = {
14916 { WM_WINDOWPOSCHANGING
, sent
|wparam
|lparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
14917 |SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
, 0 },
14918 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
14919 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
},
14920 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14924 static const struct message WmSetWindowRgn_clear
[] = {
14925 { WM_WINDOWPOSCHANGING
, sent
/*|wparam|lparam*/, SWP_NOACTIVATE
|SWP_FRAMECHANGED
14926 |SWP_NOSIZE
|SWP_NOMOVE
/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */
14927 /* Some newer Windows versions set window coordinates instead of zeros in WINDOWPOS structure */},
14928 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
14929 { WM_NCPAINT
, sent
|optional
},
14930 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14931 { WM_ERASEBKGND
, sent
},
14932 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
14933 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
14934 { WM_NCPAINT
, sent
|optional
},
14935 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14936 { WM_ERASEBKGND
, sent
|optional
},
14937 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
14938 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
14939 { WM_WINDOWPOSCHANGING
, sent
|optional
},
14940 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
14941 { WM_NCPAINT
, sent
|optional
},
14942 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14943 { WM_ERASEBKGND
, sent
|optional
},
14944 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOSIZE
|SWP_NOMOVE
},
14945 { WM_NCCALCSIZE
, sent
|optional
|wparam
, 1 },
14946 { WM_NCPAINT
, sent
|optional
},
14947 { WM_GETTEXT
, sent
|defwinproc
|optional
},
14948 { WM_ERASEBKGND
, sent
|optional
},
14949 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
14950 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Not always sent. */
14954 static void test_SetWindowRgn(void)
14957 HWND hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
14958 100, 100, 200, 200, 0, 0, 0, NULL
);
14959 ok( hwnd
!= 0, "Failed to create overlapped window\n" );
14961 ShowWindow( hwnd
, SW_SHOW
);
14962 UpdateWindow( hwnd
);
14966 if (winetest_debug
> 1) trace("testing SetWindowRgn\n");
14967 hrgn
= CreateRectRgn( 0, 0, 150, 150 );
14968 SetWindowRgn( hwnd
, hrgn
, TRUE
);
14969 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn", FALSE
);
14971 hrgn
= CreateRectRgn( 30, 30, 160, 160 );
14972 SetWindowRgn( hwnd
, hrgn
, FALSE
);
14973 ok_sequence( WmSetWindowRgn_no_redraw
, "WmSetWindowRgn_no_redraw", FALSE
);
14975 hrgn
= CreateRectRgn( 0, 0, 180, 180 );
14976 SetWindowRgn( hwnd
, hrgn
, TRUE
);
14977 ok_sequence( WmSetWindowRgn
, "WmSetWindowRgn2", FALSE
);
14979 SetWindowRgn( hwnd
, 0, TRUE
);
14980 ok_sequence( WmSetWindowRgn_clear
, "WmSetWindowRgn_clear", FALSE
);
14982 DestroyWindow( hwnd
);
14985 /*************************** ShowWindow() test ******************************/
14986 static const struct message WmShowNormal
[] = {
14987 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
14988 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
14989 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
14990 { HCBT_ACTIVATE
, hook
},
14991 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
14992 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
14993 { HCBT_SETFOCUS
, hook
},
14994 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
14995 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
14996 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends it, but Win8+ doesn't. */
14999 static const struct message WmShow
[] = {
15000 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15001 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15002 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15003 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15004 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15005 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15006 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15007 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|wine_only
, OBJID_CLIENT
, 0 },
15008 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15011 static const struct message WmShowNoActivate_1
[] = {
15012 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
15013 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15014 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15015 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15016 { WM_MOVE
, sent
|defwinproc
|optional
},
15017 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
15018 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15019 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15022 static const struct message WmShowNoActivate_2
[] = {
15023 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWNOACTIVATE
},
15024 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
15025 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15026 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15027 { HCBT_ACTIVATE
, hook
|optional
},
15028 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
15029 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15030 { WM_WINDOWPOSCHANGED
, sent
|optional
}, /* Sometimes sent on Win8+. */
15031 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15032 { HCBT_SETFOCUS
, hook
|optional
},
15033 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 }, /* Win7 sends this. */
15034 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
15035 { WM_MOVE
, sent
|defwinproc
},
15036 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
15037 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15038 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15039 { HCBT_SETFOCUS
, hook
|optional
},
15040 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
15041 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15042 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
15043 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15044 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
15045 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15046 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15047 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|wine_only
, OBJID_CLIENT
, 0 },
15048 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15051 static const struct message WmShowNA_1
[] = {
15052 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15053 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15054 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15055 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15058 static const struct message WmShowNA_2
[] = {
15059 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15060 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15061 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15064 static const struct message WmRestore_1
[] = {
15065 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
15066 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15067 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15068 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15069 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15070 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15071 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15072 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15073 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|wine_only
, OBJID_CLIENT
, 0 },
15074 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15075 { WM_MOVE
, sent
|defwinproc
},
15076 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_RESTORED
},
15077 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15078 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15079 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15080 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
15081 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15084 static const struct message WmRestore_2
[] = {
15085 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
15086 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15087 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15088 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15089 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15090 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15091 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15092 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|wine_only
, OBJID_CLIENT
, 0 },
15093 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15096 static const struct message WmRestore_3
[] = {
15097 { HCBT_MINMAX
, hook
|lparam
, 0, SW_RESTORE
},
15098 { WM_GETMINMAXINFO
, sent
},
15099 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15100 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15101 { HCBT_ACTIVATE
, hook
|optional
}, /* win2003 doesn't send it */
15102 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15103 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2003 doesn't send it */
15104 { WM_WINDOWPOSCHANGED
, sent
|optional
}, /* Win8+ sometimes sends this. */
15105 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 doesn't send it */
15106 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
15107 { WM_WINDOWPOSCHANGED
, sent
|optional
},
15108 { WM_MOVE
, sent
|defwinproc
},
15109 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
15110 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15111 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15112 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15113 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
15114 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|wine_only
, OBJID_CLIENT
, 0 },
15117 static const struct message WmRestore_4
[] = {
15118 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_RESTORE
},
15119 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15120 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15121 { WM_MOVE
, sent
|defwinproc
|optional
},
15122 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
15123 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15124 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15127 static const struct message WmRestore_5
[] = {
15128 { HCBT_MINMAX
, hook
|lparam
|optional
, 0, SW_SHOWNORMAL
},
15129 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15130 { HCBT_ACTIVATE
, hook
|optional
},
15131 { HCBT_SETFOCUS
, hook
|optional
},
15132 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15133 { WM_MOVE
, sent
|defwinproc
|optional
},
15134 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_RESTORED
},
15135 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15136 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15139 static const struct message WmHide_1
[] = {
15140 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15141 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
, 0, SWP_NOACTIVATE
},
15142 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15143 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
, 0, SWP_NOACTIVATE
},
15144 { HCBT_ACTIVATE
, hook
|optional
},
15145 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 sends it */
15146 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15149 static const struct message WmHide_2
[] = {
15150 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15151 { WM_WINDOWPOSCHANGING
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
15152 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15153 { WM_WINDOWPOSCHANGED
, sent
/*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */
15154 { HCBT_ACTIVATE
, hook
|optional
},
15157 static const struct message WmHide_3
[] = {
15158 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
15159 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
15160 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15161 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15162 { HCBT_SETFOCUS
, hook
|optional
},
15163 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15166 static const struct message WmShowMinimized_1
[] = {
15167 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
15168 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15169 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15170 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15171 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15172 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15173 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15174 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|wine_only
, OBJID_CLIENT
, 0 },
15175 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15176 { WM_MOVE
, sent
|defwinproc
},
15177 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
15178 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15179 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15180 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
15183 static const struct message WmMinimize_1
[] = {
15184 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
15185 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15186 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15187 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15188 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15189 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15190 { WM_MOVE
, sent
|defwinproc
},
15191 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
15192 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15193 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15194 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
15197 static const struct message WmMinimize_2
[] = {
15198 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
15199 { HCBT_SETFOCUS
, hook
|optional
},
15200 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
15201 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15202 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
15203 { WM_MOVE
, sent
|defwinproc
},
15204 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
15205 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15206 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15207 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
15210 static const struct message WmMinimize_3
[] = {
15211 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
15212 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
, 0, SWP_NOACTIVATE
},
15213 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15214 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15215 { HCBT_ACTIVATE
, hook
|optional
},
15216 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sometimes sent on Win8/10. */
15217 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15218 { WM_WINDOWPOSCHANGED
, sent
|optional
},
15219 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sometimes sent on Win7. */
15220 { WM_WINDOWPOSCHANGED
, sent
|optional
},
15221 { WM_MOVE
, sent
|defwinproc
},
15222 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
, SIZE_MINIMIZED
, 0 },
15223 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15224 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15225 { EVENT_SYSTEM_MINIMIZESTART
, winevent_hook
|wparam
|lparam
, 0, 0 },
15228 static const struct message WmShowMinNoActivate
[] = {
15229 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
15230 { WM_WINDOWPOSCHANGING
, sent
},
15231 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15232 { WM_WINDOWPOSCHANGED
, sent
},
15233 { WM_MOVE
, sent
|defwinproc
|optional
},
15234 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
15237 static const struct message WmMinMax_1
[] = {
15238 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINIMIZED
},
15241 static const struct message WmMinMax_2
[] = {
15242 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
15243 { WM_GETMINMAXINFO
, sent
|optional
},
15244 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
},
15245 { HCBT_ACTIVATE
, hook
|optional
},
15246 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15247 { HCBT_SETFOCUS
, hook
|optional
},
15248 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15249 { WM_MOVE
, sent
|defwinproc
|optional
},
15250 { WM_SIZE
, sent
|wparam
|defwinproc
|optional
, SIZE_MAXIMIZED
},
15251 { HCBT_SETFOCUS
, hook
|optional
},
15254 static const struct message WmMinMax_3
[] = {
15255 { HCBT_MINMAX
, hook
|lparam
, 0, SW_MINIMIZE
},
15256 { HCBT_SETFOCUS
, hook
|optional
},
15257 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_SHOWWINDOW
|SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15258 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOACTIVATE
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15259 { WM_MOVE
, sent
|defwinproc
|optional
},
15260 { WM_SIZE
, sent
|wparam
|lparam
|defwinproc
|optional
, SIZE_MINIMIZED
, 0 },
15263 static const struct message WmMinMax_4
[] = {
15264 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMINNOACTIVE
},
15267 static const struct message WmShowMaximized_1
[] = {
15268 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
15269 { WM_GETMINMAXINFO
, sent
},
15270 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15271 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15272 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
15273 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15274 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|wine_only
, 0, 0 },
15275 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15276 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15277 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|wine_only
, OBJID_CLIENT
, 0 },
15278 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15279 { WM_MOVE
, sent
|defwinproc
},
15280 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
15281 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15282 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15283 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15284 { HCBT_SETFOCUS
, hook
|optional
}, /* win2003 sends it */
15285 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15288 static const struct message WmShowMaximized_2
[] = {
15289 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
15290 { WM_GETMINMAXINFO
, sent
},
15291 { WM_WINDOWPOSCHANGING
, sent
|optional
},
15292 { HCBT_ACTIVATE
, hook
|optional
},
15293 { WM_WINDOWPOSCHANGED
, sent
|optional
},
15294 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15295 { WM_MOVE
, sent
|optional
}, /* Win9x doesn't send it */
15296 { WM_SIZE
, sent
|wparam
|optional
, SIZE_MAXIMIZED
}, /* Win9x doesn't send it */
15297 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 sends this. */
15298 { WM_WINDOWPOSCHANGING
, sent
|optional
},
15299 { HCBT_SETFOCUS
, hook
|optional
},
15300 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15301 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
15302 { WM_MOVE
, sent
|defwinproc
},
15303 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
15304 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15305 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15306 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15307 { HCBT_SETFOCUS
, hook
|optional
},
15308 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
15311 static const struct message WmShowMaximized_3
[] = {
15312 { HCBT_MINMAX
, hook
|lparam
, 0, SW_SHOWMAXIMIZED
},
15313 { WM_GETMINMAXINFO
, sent
|optional
},
15314 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15315 { HCBT_ACTIVATE
, hook
|optional
}, /* win2000 doesn't send it */
15316 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
}, /* win2000 doesn't send it */
15317 { HCBT_SETFOCUS
, hook
|optional
}, /* win2000 doesn't send it */
15318 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_STATECHANGED
, 0, SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOSIZE
|SWP_NOMOVE
},
15319 { WM_MOVE
, sent
|defwinproc
|optional
},
15320 { WM_SIZE
, sent
|wparam
|defwinproc
, SIZE_MAXIMIZED
},
15321 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15322 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
15326 static void test_ShowWindow(void)
15328 /* ShowWindow commands in random order */
15329 static const struct
15331 INT cmd
; /* ShowWindow command */
15332 LPARAM ret
; /* ShowWindow return value */
15333 DWORD style
; /* window style after the command */
15334 const struct message
*msg
; /* message sequence the command produces */
15335 INT wp_cmd
, wp_flags
; /* window placement after the command */
15336 POINT wp_min
, wp_max
; /* window placement after the command */
15337 BOOL todo_msg
; /* message sequence doesn't match what Wine does */
15340 /* 1 */ { SW_SHOWNORMAL
, FALSE
, WS_VISIBLE
, WmShowNormal
,
15341 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15342 /* 2 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15343 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15344 /* 3 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
15345 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15346 /* 4 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15347 SW_SHOWNORMAL
, 0, {-1,-1}, {-1,-1}, FALSE
},
15348 /* 5 */ { SW_SHOWMINIMIZED
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinimized_1
,
15349 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15350 /* 6 */ { SW_SHOWMINIMIZED
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_1
,
15351 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15352 /* 7 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_1
,
15353 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15354 /* 8 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
15355 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15356 /* 9 */ { SW_SHOWMAXIMIZED
, FALSE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_1
,
15357 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15358 /* 10 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
15359 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15360 /* 11 */ { SW_HIDE
, TRUE
, WS_MAXIMIZE
, WmHide_1
,
15361 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15362 /* 12 */ { SW_HIDE
, FALSE
, WS_MAXIMIZE
, WmEmptySeq
,
15363 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15364 /* 13 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_1
,
15365 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15366 /* 14 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15367 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15368 /* 15 */ { SW_HIDE
, TRUE
, 0, WmHide_2
,
15369 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15370 /* 16 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15371 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15372 /* 17 */ { SW_SHOW
, FALSE
, WS_VISIBLE
, WmShow
,
15373 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15374 /* 18 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15375 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15376 /* 19 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
15377 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15378 /* 20 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
15379 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15380 /* 21 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15381 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15382 /* 22 */ { SW_SHOWMINNOACTIVE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowMinNoActivate
,
15383 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, TRUE
},
15384 /* 23 */ { SW_SHOWMINNOACTIVE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_4
,
15385 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15386 /* 24 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15387 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15388 /* 25 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
15389 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15390 /* 26 */ { SW_SHOWNA
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_1
,
15391 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15392 /* 27 */ { SW_SHOWNA
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmShowNA_2
,
15393 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15394 /* 28 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15395 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15396 /* 29 */ { SW_HIDE
, FALSE
, WS_MINIMIZE
, WmEmptySeq
,
15397 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15398 /* 30 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_1
,
15399 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15400 /* 31 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15401 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15402 /* 32 */ { SW_HIDE
, TRUE
, 0, WmHide_3
,
15403 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15404 /* 33 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15405 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15406 /* 34 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
, /* what does this mean?! */
15407 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15408 /* 35 */ { SW_NORMALNA
, FALSE
, 0, WmEmptySeq
,
15409 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15410 /* 36 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15411 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15412 /* 37 */ { SW_RESTORE
, FALSE
, WS_VISIBLE
, WmRestore_2
,
15413 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15414 /* 38 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15415 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15416 /* 39 */ { SW_SHOWNOACTIVATE
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15417 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15418 /* 40 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_2
,
15419 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15420 /* 41 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
15421 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15422 /* 42 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_2
,
15423 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15424 /* 43 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmMinMax_2
,
15425 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15426 /* 44 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_1
,
15427 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15428 /* 45 */ { SW_MINIMIZE
, TRUE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinMax_3
,
15429 SW_SHOWMINIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15430 /* 46 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmRestore_3
,
15431 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15432 /* 47 */ { SW_RESTORE
, TRUE
, WS_VISIBLE
, WmRestore_4
,
15433 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15434 /* 48 */ { SW_SHOWMAXIMIZED
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmShowMaximized_3
,
15435 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15436 /* 49 */ { SW_SHOW
, TRUE
, WS_VISIBLE
|WS_MAXIMIZE
, WmEmptySeq
,
15437 SW_SHOWMAXIMIZED
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15438 /* 50 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
15439 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15440 /* 51 */ { SW_SHOWNORMAL
, TRUE
, WS_VISIBLE
, WmRestore_5
,
15441 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15442 /* 52 */ { SW_HIDE
, TRUE
, 0, WmHide_1
,
15443 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15444 /* 53 */ { SW_HIDE
, FALSE
, 0, WmEmptySeq
,
15445 SW_SHOWNORMAL
, WPF_RESTORETOMAXIMIZED
, {-32000,-32000}, {-1,-1}, FALSE
},
15446 /* 54 */ { SW_MINIMIZE
, FALSE
, WS_VISIBLE
|WS_MINIMIZE
, WmMinimize_3
,
15447 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15448 /* 55 */ { SW_HIDE
, TRUE
, WS_MINIMIZE
, WmHide_2
,
15449 SW_SHOWMINIMIZED
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15450 /* 56 */ { SW_SHOWNOACTIVATE
, FALSE
, WS_VISIBLE
, WmShowNoActivate_2
,
15451 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
},
15452 /* 57 */ { SW_SHOW
, TRUE
, WS_VISIBLE
, WmEmptySeq
,
15453 SW_SHOWNORMAL
, 0, {-32000,-32000}, {-1,-1}, FALSE
}
15459 WINDOWPLACEMENT wp
;
15460 RECT win_rc
, work_rc
= {0, 0, 0, 0};
15465 #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS)
15466 hwnd
= CreateWindowExA(0, "ShowWindowClass", NULL
, WS_BASE
,
15469 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
15471 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
15472 ok(style
== 0, "expected style 0, got %08lx\n", style
);
15477 SetLastError(0xdeadbeef);
15478 hmon
= MonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
15479 ok(hmon
!= 0, "MonitorFromPoint error %lu\n", GetLastError());
15481 mi
.cbSize
= sizeof(mi
);
15482 SetLastError(0xdeadbeef);
15483 ret
= GetMonitorInfoA(hmon
, &mi
);
15484 ok(ret
, "GetMonitorInfo error %lu\n", GetLastError());
15485 if (winetest_debug
> 1) trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi
.rcMonitor
),
15486 wine_dbgstr_rect(&mi
.rcWork
));
15487 work_rc
= mi
.rcWork
;
15489 GetWindowRect(hwnd
, &win_rc
);
15490 OffsetRect(&win_rc
, -work_rc
.left
, -work_rc
.top
);
15492 wp
.length
= sizeof(wp
);
15493 SetLastError(0xdeadbeaf);
15494 ret
= GetWindowPlacement(hwnd
, &wp
);
15495 ok(ret
, "GetWindowPlacement error %lu\n", GetLastError());
15496 ok(wp
.flags
== 0, "expected 0, got %#x\n", wp
.flags
);
15497 ok(wp
.showCmd
== SW_SHOWNORMAL
, "expected SW_SHOWNORMAL, got %d\n", wp
.showCmd
);
15498 ok(wp
.ptMinPosition
.x
== -1 && wp
.ptMinPosition
.y
== -1,
15499 "expected -1,-1 got %ld,%ld\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
15500 ok(wp
.ptMaxPosition
.x
== -1 && wp
.ptMaxPosition
.y
== -1,
15501 "expected -1,-1 got %ld,%ld\n", wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
15502 todo_wine_if (work_rc
.left
|| work_rc
.top
) /* FIXME: remove once Wine is fixed */
15503 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n", wine_dbgstr_rect(&win_rc
),
15504 wine_dbgstr_rect(&wp
.rcNormalPosition
));
15506 for (i
= 0; i
< ARRAY_SIZE(sw
); i
++)
15508 static const char * const sw_cmd_name
[13] =
15510 "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED",
15511 "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE",
15512 "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE",
15513 "SW_NORMALNA" /* 0xCC */
15516 INT idx
; /* index into the above array of names */
15518 idx
= (sw
[i
].cmd
== SW_NORMALNA
) ? 12 : sw
[i
].cmd
;
15520 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
15521 if (winetest_debug
> 1) trace("%d: sending %s, current window style %08lx\n", i
+1, sw_cmd_name
[idx
], style
);
15522 ret
= ShowWindow(hwnd
, sw
[i
].cmd
);
15523 ok(!ret
== !sw
[i
].ret
, "%d: cmd %s: expected ret %Iu, got %Iu\n", i
+1, sw_cmd_name
[idx
], sw
[i
].ret
, ret
);
15524 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~WS_BASE
;
15525 ok(style
== sw
[i
].style
, "%d: expected style %08lx, got %08lx\n", i
+1, sw
[i
].style
, style
);
15527 sprintf(comment
, "%d: ShowWindow(%s)", i
+1, sw_cmd_name
[idx
]);
15528 ok_sequence(sw
[i
].msg
, comment
, sw
[i
].todo_msg
);
15530 wp
.length
= sizeof(wp
);
15531 SetLastError(0xdeadbeaf);
15532 ret
= GetWindowPlacement(hwnd
, &wp
);
15533 ok(ret
, "GetWindowPlacement error %lu\n", GetLastError());
15534 ok(wp
.flags
== sw
[i
].wp_flags
, "expected %#x, got %#x\n", sw
[i
].wp_flags
, wp
.flags
);
15535 ok(wp
.showCmd
== sw
[i
].wp_cmd
, "expected %d, got %d\n", sw
[i
].wp_cmd
, wp
.showCmd
);
15537 /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */
15538 if ((wp
.ptMinPosition
.x
+ work_rc
.left
== -32000 && wp
.ptMinPosition
.y
+ work_rc
.top
== -32000) ||
15539 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000))
15541 ok((wp
.ptMinPosition
.x
+ work_rc
.left
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
+ work_rc
.top
== sw
[i
].wp_min
.y
) ||
15542 (wp
.ptMinPosition
.x
+ work_rc
.left
== 3000 && wp
.ptMinPosition
.y
+ work_rc
.top
== 3000),
15543 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
15547 ok(wp
.ptMinPosition
.x
== sw
[i
].wp_min
.x
&& wp
.ptMinPosition
.y
== sw
[i
].wp_min
.y
,
15548 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_min
.x
, sw
[i
].wp_min
.y
, wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
);
15551 todo_wine_if(wp
.ptMaxPosition
.x
!= sw
[i
].wp_max
.x
|| wp
.ptMaxPosition
.y
!= sw
[i
].wp_max
.y
)
15552 ok(wp
.ptMaxPosition
.x
== sw
[i
].wp_max
.x
&& wp
.ptMaxPosition
.y
== sw
[i
].wp_max
.y
,
15553 "expected %ld,%ld got %ld,%ld\n", sw
[i
].wp_max
.x
, sw
[i
].wp_max
.y
, wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
);
15555 if (0) /* FIXME: Wine behaves completely different here */
15556 ok(EqualRect(&win_rc
, &wp
.rcNormalPosition
), "expected %s got %s\n",
15557 wine_dbgstr_rect(&win_rc
), wine_dbgstr_rect(&wp
.rcNormalPosition
));
15559 DestroyWindow(hwnd
);
15563 static INT_PTR WINAPI
test_dlg_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15565 struct recvd_message msg
;
15567 if (ignore_message( message
)) return 0;
15570 msg
.message
= message
;
15571 msg
.flags
= sent
|wparam
|lparam
;
15572 msg
.wParam
= wParam
;
15573 msg
.lParam
= lParam
;
15574 msg
.descr
= "dialog";
15577 /* calling DefDlgProc leads to a recursion under XP */
15581 case WM_INITDIALOG
:
15584 case WM_GETDLGCODE
:
15590 static WNDPROC orig_edit_proc
;
15591 static LRESULT WINAPI
dlg_creation_edit_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
15593 struct recvd_message msg
;
15595 if (ignore_message( message
)) return 0;
15598 msg
.message
= message
;
15599 msg
.flags
= sent
|wparam
|lparam
;
15602 msg
.descr
= "edit";
15605 return CallWindowProcW(orig_edit_proc
, hwnd
, message
, wp
, lp
);
15608 static INT_PTR WINAPI
test_dlg_proc2(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15610 struct recvd_message msg
;
15612 if (ignore_message( message
)) return 0;
15615 msg
.message
= message
;
15616 msg
.flags
= sent
|wparam
|lparam
|parent
;
15617 msg
.wParam
= wParam
;
15618 msg
.lParam
= lParam
;
15619 msg
.descr
= "dialog";
15622 if (message
== WM_INITDIALOG
)
15624 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
15625 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
15631 static INT_PTR WINAPI
test_dlg_proc3(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15633 ok( 0, "should not be called since DefDlgProc is not used\n" );
15637 static LRESULT WINAPI
test_dlg_proc4(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
15639 struct recvd_message msg
;
15641 if (!ignore_message( message
))
15644 msg
.message
= message
;
15645 msg
.flags
= sent
|wparam
|lparam
|parent
;
15646 msg
.wParam
= wParam
;
15647 msg
.lParam
= lParam
;
15648 msg
.descr
= "dialog";
15651 if (message
== WM_INITDIALOG
)
15653 orig_edit_proc
= (WNDPROC
)SetWindowLongPtrW(GetDlgItem(hwnd
, 200),
15654 GWLP_WNDPROC
, (LONG_PTR
)dlg_creation_edit_proc
);
15657 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
15660 static const struct message WmDefDlgSetFocus_1
[] = {
15661 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15662 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
15663 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
15664 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
15665 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
15666 { HCBT_SETFOCUS
, hook
},
15667 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 1 },
15668 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
15669 { EM_GETPASSWORDCHAR
, sent
|optional
}, /* Sent on some Win10 machines */
15670 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15671 { WM_SETFOCUS
, sent
|wparam
, 0 },
15672 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 10 },
15673 { WM_CTLCOLOREDIT
, sent
},
15674 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 11 },
15675 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
15676 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
15677 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
15678 { WM_COMMAND
, sent
|wparam
, MAKEWPARAM(1, EN_SETFOCUS
) },
15681 static const struct message WmDefDlgSetFocus_2
[] = {
15682 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15683 { WM_GETTEXTLENGTH
, sent
|wparam
|lparam
|optional
, 0, 0 }, /* XP */
15684 { WM_GETTEXT
, sent
|wparam
|optional
, 6 }, /* XP */
15685 { WM_GETTEXT
, sent
|wparam
|optional
, 12 }, /* XP */
15686 { EM_SETSEL
, sent
|wparam
, 0 }, /* XP sets lparam to text length, Win9x to -2 */
15687 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
15688 { WM_CTLCOLOREDIT
, sent
|optional
}, /* XP */
15689 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CARET
, 0 },
15692 /* Creation of a dialog */
15693 static const struct message WmCreateDialogParamSeq_0
[] = {
15694 { HCBT_CREATEWND
, hook
},
15695 { WM_NCCREATE
, sent
},
15696 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
15697 { WM_CREATE
, sent
},
15698 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15699 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
15701 { WM_SETFONT
, sent
},
15702 { WM_INITDIALOG
, sent
},
15703 { WM_CHANGEUISTATE
, sent
|optional
},
15706 /* Creation of a dialog */
15707 static const struct message WmCreateDialogParamSeq_1
[] = {
15708 { HCBT_CREATEWND
, hook
},
15709 { WM_NCCREATE
, sent
},
15710 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
15711 { WM_CREATE
, sent
},
15712 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15713 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
15715 { WM_SETFONT
, sent
},
15716 { WM_INITDIALOG
, sent
},
15717 { WM_GETDLGCODE
, sent
|wparam
|lparam
|msg_todo
, 0, 0 }, /* FIXME: Wine doesn't send it */
15718 { HCBT_SETFOCUS
, hook
},
15719 { HCBT_ACTIVATE
, hook
},
15720 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
15721 { WM_QUERYNEWPALETTE
, sent
|optional
},
15722 { WM_PALETTEISCHANGING
, sent
|optional
},
15723 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15724 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
|SWP_NOREDRAW
},
15725 { WM_GETTEXT
, sent
|optional
}, /* win7 */
15726 { WM_NCCALCSIZE
, sent
|optional
}, /* win7 */
15727 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* win7 */
15728 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
15729 { WM_NCACTIVATE
, sent
},
15730 { WM_ACTIVATE
, sent
|wparam
, 1 },
15731 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15732 { WM_SETFOCUS
, sent
},
15733 { WM_CHANGEUISTATE
, sent
|optional
},
15736 /* Creation of a dialog */
15737 static const struct message WmCreateDialogParamSeq_2
[] = {
15738 { HCBT_CREATEWND
, hook
},
15739 { WM_NCCREATE
, sent
},
15740 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
15741 { WM_CREATE
, sent
},
15742 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
15743 { WM_SIZE
, sent
|wparam
, SIZE_RESTORED
},
15745 { WM_CHANGEUISTATE
, sent
|optional
},
15749 static const struct message WmCreateDialogParamSeq_3
[] = {
15750 { HCBT_CREATEWND
, hook
},
15751 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15752 { WM_SETFONT
, sent
|parent
},
15753 { WM_INITDIALOG
, sent
|parent
},
15754 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15755 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
15756 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15757 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15758 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15759 { HCBT_ACTIVATE
, hook
},
15760 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15761 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
15762 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15763 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15764 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15765 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15766 { WM_NCCALCSIZE
, sent
|parent
|optional
, 0 },
15767 { WM_MOVE
, sent
|parent
|optional
},
15768 { WM_SIZE
, sent
|parent
|optional
},
15769 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15770 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
15771 { WM_NCACTIVATE
, sent
|parent
},
15772 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
15773 { EM_GETPASSWORDCHAR
, sent
|optional
}, /* Sent on some Win10 machines */
15774 { WM_SETFOCUS
, sent
},
15775 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
15776 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15777 { WM_USER
, sent
|parent
},
15778 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
15782 static const struct message WmCreateDialogParamSeq_4
[] = {
15783 { HCBT_CREATEWND
, hook
},
15784 { WM_NCCREATE
, sent
|parent
},
15785 { WM_NCCALCSIZE
, sent
|parent
|wparam
, 0 },
15786 { WM_CREATE
, sent
|parent
},
15787 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15788 { WM_SIZE
, sent
|parent
|wparam
, SIZE_RESTORED
},
15789 { WM_MOVE
, sent
|parent
},
15790 { WM_SETFONT
, sent
|parent
},
15791 { WM_INITDIALOG
, sent
|parent
},
15792 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15793 { EM_SETSEL
, sent
|wparam
|lparam
, 0, INT_MAX
},
15794 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15795 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15796 { EM_SETSEL
, sent
|wparam
|lparam
|optional
, 0, INT_MAX
},
15797 { HCBT_ACTIVATE
, hook
},
15798 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15799 { WM_QUERYNEWPALETTE
, sent
|parent
|optional
}, /* TODO: this message should not be sent */
15800 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15801 { WM_WINDOWPOSCHANGING
, sent
|parent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
15802 { WM_WINDOWPOSCHANGED
, sent
|parent
|wparam
|optional
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
15803 { WM_NCCALCSIZE
, sent
|parent
|optional
, 0 },
15804 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
15805 { WM_ACTIVATEAPP
, sent
|parent
|wparam
, 1 },
15806 { WM_NCACTIVATE
, sent
|parent
},
15807 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
15808 { HCBT_SETFOCUS
, hook
},
15809 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
15810 { WM_SETFOCUS
, sent
|parent
},
15811 { WM_KILLFOCUS
, sent
|parent
},
15812 { EM_GETPASSWORDCHAR
, sent
|optional
}, /* Sent on some Win10 machines */
15813 { WM_SETFOCUS
, sent
},
15814 { WM_COMMAND
, sent
|parent
|wparam
, MAKELONG(200, EN_SETFOCUS
) },
15815 { WM_GETDLGCODE
, sent
|wparam
|lparam
, 0, 0 },
15816 { WM_USER
, sent
|parent
},
15817 { WM_CHANGEUISTATE
, sent
|parent
|optional
},
15818 { WM_UPDATEUISTATE
, sent
|parent
|optional
},
15819 { WM_UPDATEUISTATE
, sent
|optional
},
15823 static void test_dialog_messages(void)
15826 HWND hdlg
, hedit1
, hedit2
, hfocus
, parent
, child
, child2
;
15829 #define set_selection(hctl, start, end) \
15830 ret = SendMessageA(hctl, EM_SETSEL, start, end); \
15831 ok(ret == 1, "EM_SETSEL returned %Id\n", ret);
15833 #define check_selection(hctl, start, end) \
15834 ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \
15835 ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
15839 hdlg
= CreateWindowExA(WS_EX_DLGMODALFRAME
, "TestDialogClass", NULL
,
15840 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
15841 0, 0, 100, 100, 0, 0, 0, NULL
);
15842 ok(hdlg
!= 0, "Failed to create custom dialog window\n");
15844 hedit1
= CreateWindowExA(0, "my_edit_class", NULL
,
15845 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
15846 0, 0, 80, 20, hdlg
, (HMENU
)1, 0, NULL
);
15847 ok(hedit1
!= 0, "Failed to create edit control\n");
15848 hedit2
= CreateWindowExA(0, "my_edit_class", NULL
,
15849 WS_CHILD
|WS_BORDER
|WS_VISIBLE
|WS_TABSTOP
,
15850 0, 40, 80, 20, hdlg
, (HMENU
)2, 0, NULL
);
15851 ok(hedit2
!= 0, "Failed to create edit control\n");
15853 SendMessageA(hedit1
, WM_SETTEXT
, 0, (LPARAM
)"hello");
15854 SendMessageA(hedit2
, WM_SETTEXT
, 0, (LPARAM
)"bye");
15856 hfocus
= GetFocus();
15857 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
15860 hfocus
= GetFocus();
15861 ok(hfocus
== hedit2
, "wrong focus %p\n", hfocus
);
15863 check_selection(hedit1
, 0, 0);
15864 check_selection(hedit2
, 0, 0);
15866 set_selection(hedit2
, 0, -1);
15867 check_selection(hedit2
, 0, 3);
15870 hfocus
= GetFocus();
15871 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
15874 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
15875 ok(ret
== 0, "WM_SETFOCUS returned %Id\n", ret
);
15876 ok_sequence(WmDefDlgSetFocus_1
, "DefDlgProc(WM_SETFOCUS) 1", FALSE
);
15878 hfocus
= GetFocus();
15879 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
15881 check_selection(hedit1
, 0, 5);
15882 check_selection(hedit2
, 0, 3);
15885 ret
= DefDlgProcA(hdlg
, WM_SETFOCUS
, 0, 0);
15886 ok(ret
== 0, "WM_SETFOCUS returned %Id\n", ret
);
15887 ok_sequence(WmDefDlgSetFocus_2
, "DefDlgProc(WM_SETFOCUS) 2", FALSE
);
15889 hfocus
= GetFocus();
15890 ok(hfocus
== hedit1
, "wrong focus %p\n", hfocus
);
15892 check_selection(hedit1
, 0, 5);
15893 check_selection(hedit2
, 0, 3);
15895 EndDialog(hdlg
, 0);
15896 DestroyWindow(hedit1
);
15897 DestroyWindow(hedit2
);
15898 DestroyWindow(hdlg
);
15901 #undef set_selection
15902 #undef check_selection
15904 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
15905 cls
.lpszClassName
= "MyDialogClass";
15906 cls
.hInstance
= GetModuleHandleA(NULL
);
15907 /* need a cast since a dlgproc is used as a wndproc */
15908 cls
.lpfnWndProc
= (WNDPROC
)test_dlg_proc
;
15909 register_class(&cls
);
15913 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 0);
15914 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15915 ok_sequence(WmCreateDialogParamSeq_0
, "CreateDialogParam_0", FALSE
);
15916 hfocus
= GetFocus();
15917 ok(hfocus
== 0, "wrong focus %p\n", hfocus
);
15918 EndDialog(hdlg
, 0);
15919 DestroyWindow(hdlg
);
15924 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc
, 1);
15925 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15926 ok_sequence(WmCreateDialogParamSeq_1
, "CreateDialogParam_1", FALSE
);
15927 hfocus
= GetFocus();
15928 ok(hfocus
== hdlg
, "wrong focus %p\n", hfocus
);
15929 EndDialog(hdlg
, 0);
15930 DestroyWindow(hdlg
);
15933 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL
, 0);
15934 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15935 ok_sequence(WmCreateDialogParamSeq_2
, "CreateDialogParam_2", FALSE
);
15936 EndDialog(hdlg
, 0);
15937 DestroyWindow(hdlg
);
15940 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2
, 0);
15941 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15942 ok_sequence(WmCreateDialogParamSeq_3
, "CreateDialogParam_3", TRUE
);
15943 EndDialog(hdlg
, 0);
15944 DestroyWindow(hdlg
);
15947 UnregisterClassA( cls
.lpszClassName
, cls
.hInstance
);
15948 cls
.lpfnWndProc
= test_dlg_proc4
;
15949 register_class(&cls
);
15950 hdlg
= CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3
, 0);
15951 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
15952 ok_sequence(WmCreateDialogParamSeq_4
, "CreateDialogParam_4", TRUE
);
15953 EndDialog(hdlg
, 0);
15954 DestroyWindow(hdlg
);
15957 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
15959 parent
= CreateWindowExA(0, "TestParentClass", "Test parent",
15960 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15961 100, 100, 200, 200, 0, 0, 0, NULL
);
15962 ok (parent
!= 0, "Failed to create parent window\n");
15964 /* This child has no parent set. We will later call SetParent on it,
15965 * so that it will have a parent set, but no WS_CHILD style. */
15966 child
= CreateWindowExA(0, "TestWindowClass", "Test child",
15967 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
15968 100, 100, 200, 200, 0, 0, 0, NULL
);
15969 ok (child
!= 0, "Failed to create child window\n");
15971 /* This is a regular child window. When used as an owner, the other
15972 * child window will be used. */
15973 child2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2",
15974 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CHILD
,
15975 100, 100, 200, 200, child
, 0, 0, NULL
);
15976 ok (child2
!= 0, "Failed to create child window\n");
15978 SetParent(child
, parent
);
15982 DialogBoxA( 0, "TEST_DIALOG", child2
, TestModalDlgProc2
);
15983 ok_sequence(WmModalDialogSeq_2
, "ModalDialog2", TRUE
);
15985 DestroyWindow(child2
);
15986 DestroyWindow(child
);
15987 DestroyWindow(parent
);
15991 static void test_enddialog_seq(HWND dialog
, HWND owner
)
15993 const struct message seq
[] = {
15994 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
15995 { WM_ENABLE
, sent
},
15996 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
15997 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
15998 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
15999 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
16000 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
16001 /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */
16002 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
16003 { WM_QUERYNEWPALETTE
, sent
|optional
},
16004 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
16005 { WM_GETTEXT
, sent
|optional
|defwinproc
},
16006 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, (LPARAM
)dialog
},
16007 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
16008 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
16009 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16010 { WM_SETFOCUS
, sent
|defwinproc
|wparam
, (WPARAM
)dialog
},
16015 EndDialog(dialog
, 0);
16016 ok_sequence(seq
, "EndDialog", FALSE
);
16019 static void test_enddialog_seq2(HWND dialog
, HWND owner
)
16021 const struct message seq
[] = {
16022 { EVENT_OBJECT_STATECHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
16023 { WM_ENABLE
, parent
|sent
},
16024 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
16025 { HCBT_ACTIVATE
, hook
|wparam
, (WPARAM
)owner
},
16026 { WM_NCACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
16027 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_INACTIVE
, (LPARAM
)owner
},
16028 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
16029 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
16030 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
, SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
16031 { HCBT_SETFOCUS
, hook
|wparam
, (WPARAM
)owner
},
16032 { WM_KILLFOCUS
, sent
|wparam
, (WPARAM
)owner
},
16033 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16034 { WM_SETFOCUS
, sent
|parent
|defwinproc
|wparam
, (WPARAM
)dialog
},
16039 EndDialog(dialog
, 0);
16040 ok_sequence(seq
, "EndDialog2", FALSE
);
16043 static void test_EndDialog(void)
16045 HWND hparent
, hother
, hactive
, hdlg
, hchild
;
16048 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
16049 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
16050 100, 100, 200, 200, 0, 0, 0, NULL
);
16051 ok (hparent
!= 0, "Failed to create parent window\n");
16053 hother
= CreateWindowExA(0, "TestParentClass", "Test parent 2",
16054 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16055 200, 100, 200, 200, 0, 0, 0, NULL
);
16056 ok (hother
!= 0, "Failed to create parent window\n");
16058 ok(GetClassInfoA(0, "#32770", &cls
), "GetClassInfo failed\n");
16059 cls
.lpszClassName
= "MyDialogClass";
16060 cls
.hInstance
= GetModuleHandleA(NULL
);
16061 cls
.lpfnWndProc
= (WNDPROC
)test_dlg_proc
;
16062 register_class(&cls
);
16065 SetForegroundWindow(hother
);
16066 hactive
= GetForegroundWindow();
16067 ok(hother
== hactive
, "Wrong window has focus (%p != %p)\n", hother
, hactive
);
16069 /* create a dialog where the parent is disabled, this parent should be
16070 * enabled and receive focus when dialog exits */
16071 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent
, test_dlg_proc
, 0);
16072 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
16073 SetForegroundWindow(hdlg
);
16074 hactive
= GetForegroundWindow();
16075 ok(hdlg
== hactive
, "Wrong window has focus (%p != %p)\n", hdlg
, hactive
);
16076 EndDialog(hdlg
, 0);
16077 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
16078 hactive
= GetForegroundWindow();
16079 ok(hparent
== hactive
, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
16080 DestroyWindow(hdlg
);
16083 /* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */
16084 EnableWindow(hparent
, FALSE
);
16085 hdlg
= CreateWindowExA(0, "TestDialogClass", NULL
,
16086 WS_VISIBLE
|WS_CAPTION
|WS_SYSMENU
|WS_DLGFRAME
,
16087 0, 0, 100, 100, hparent
, 0, 0, NULL
);
16088 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
16090 SetForegroundWindow(hother
);
16092 hactive
= GetForegroundWindow();
16093 ok(hactive
== hother
, "Wrong foreground (%p != %p)\n", hactive
, hother
);
16094 hactive
= GetActiveWindow();
16095 ok(hactive
== hother
, "Wrong active window (%p != %p)\n", hactive
, hother
);
16096 EndDialog(hdlg
, 0);
16097 ok(IsWindowEnabled(hparent
), "parent is not enabled\n");
16098 hactive
= GetForegroundWindow();
16099 ok(hother
== hactive
, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive
, hparent
, hdlg
, hother
);
16100 DestroyWindow(hdlg
);
16103 DestroyWindow( hparent
);
16105 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent",
16106 WS_POPUP
| WS_VISIBLE
| WS_DISABLED
,
16107 100, 100, 200, 200, 0, 0, 0, NULL
);
16108 ok (hparent
!= 0, "Failed to create parent window\n");
16110 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child",
16111 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_DISABLED
,
16112 0, 0, 0, 0, 0, 0, 0, NULL
);
16113 ok (hchild
!= 0, "Failed to create child window\n");
16115 SetParent(hchild
, hparent
);
16118 SetForegroundWindow(hother
);
16119 hactive
= GetForegroundWindow();
16120 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
16122 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
16123 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
16125 SetForegroundWindow(hdlg
);
16126 test_enddialog_seq(hdlg
, hchild
);
16128 hactive
= GetForegroundWindow();
16129 ok(hactive
== hchild
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
16131 DestroyWindow(hdlg
);
16133 /* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */
16134 SetWindowLongW(hchild
, GWL_STYLE
, GetWindowLongW(hchild
, GWL_STYLE
) | WS_CHILD
);
16136 SetForegroundWindow(hother
);
16137 hactive
= GetForegroundWindow();
16138 ok(hother
== hactive
, "Wrong foreground window (%p != %p)\n", hother
, hactive
);
16140 hdlg
= CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild
, test_dlg_proc
, 0);
16141 ok(IsWindow(hdlg
), "CreateDialogParam failed\n");
16143 SetForegroundWindow(hdlg
);
16144 test_enddialog_seq2(hdlg
, hparent
);
16146 hactive
= GetForegroundWindow();
16147 ok(hactive
== hparent
, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive
, hparent
, hdlg
, hother
, hchild
);
16148 DestroyWindow(hdlg
);
16149 DestroyWindow(hchild
);
16150 DestroyWindow(hparent
);
16151 DestroyWindow(hother
);
16154 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
16157 static void test_nullCallback(void)
16161 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
16162 100, 100, 200, 200, 0, 0, 0, NULL
);
16163 ok (hwnd
!= 0, "Failed to create overlapped window\n");
16165 SendMessageCallbackA(hwnd
,WM_NULL
,0,0,NULL
,0);
16167 DestroyWindow(hwnd
);
16170 /* SetActiveWindow( 0 ) hwnd visible */
16171 static const struct message SetActiveWindowSeq0
[] =
16173 { HCBT_ACTIVATE
, hook
|optional
},
16174 { WM_NCACTIVATE
, sent
|wparam
, 0 },
16175 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16176 { WM_ACTIVATE
, sent
|wparam
, 0 },
16177 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
16178 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
16179 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
16180 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
16181 { WM_KILLFOCUS
, sent
|optional
},
16182 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
16183 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
16184 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
16185 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16186 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
16187 { HCBT_SETFOCUS
, hook
|optional
},
16188 { WM_KILLFOCUS
, sent
|defwinproc
|optional
},
16189 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
16190 { WM_IME_SETCONTEXT
, sent
|defwinproc
|optional
},
16191 { WM_IME_SETCONTEXT
, sent
|optional
},
16192 { WM_IME_SETCONTEXT
, sent
|optional
},
16193 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
16194 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
16195 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
16196 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
16197 { WM_GETTEXT
, sent
|optional
},
16200 /* SetActiveWindow( hwnd ) hwnd visible */
16201 static const struct message SetActiveWindowSeq1
[] =
16203 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
16206 /* SetActiveWindow( popup ) hwnd visible, popup visible */
16207 static const struct message SetActiveWindowSeq2
[] =
16209 { HCBT_ACTIVATE
, hook
},
16210 { WM_NCACTIVATE
, sent
|wparam
, 0 },
16211 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16212 { WM_ACTIVATE
, sent
|wparam
, 0 },
16213 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
, 0, 0 },
16214 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
16215 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
16216 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
16217 { WM_NCPAINT
, sent
|optional
},
16218 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16219 { WM_ERASEBKGND
, sent
|optional
},
16220 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16221 { WM_NCACTIVATE
, sent
|wparam
, 1 },
16222 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16223 { WM_ACTIVATE
, sent
|wparam
, 1 },
16224 { HCBT_SETFOCUS
, hook
},
16225 { WM_KILLFOCUS
, sent
|defwinproc
},
16226 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
16227 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
16228 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
16229 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
16230 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16231 { WM_SETFOCUS
, sent
|defwinproc
},
16232 { WM_GETTEXT
, sent
|optional
},
16236 /* SetActiveWindow( hwnd ) hwnd not visible */
16237 static const struct message SetActiveWindowSeq3
[] =
16239 { HCBT_ACTIVATE
, hook
},
16240 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
16241 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
16242 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
16243 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
16244 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOACTIVATE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16245 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16246 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
16247 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
16248 { WM_NCACTIVATE
, sent
|wparam
, 1 },
16249 { WM_ACTIVATE
, sent
|wparam
, 1 },
16250 { HCBT_SETFOCUS
, hook
},
16251 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
16252 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
16253 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16254 { WM_SETFOCUS
, sent
|defwinproc
},
16257 /* SetActiveWindow( popup ) hwnd not visible, popup not visible */
16258 static const struct message SetActiveWindowSeq4
[] =
16260 { HCBT_ACTIVATE
, hook
},
16261 { WM_NCACTIVATE
, sent
|wparam
, 0 },
16262 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16263 { WM_ACTIVATE
, sent
|wparam
, 0 },
16264 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
16265 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|optional
, 0, 0 },
16266 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
16267 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
},
16268 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16269 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
16270 { WM_NCACTIVATE
, sent
|wparam
, 1 },
16271 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16272 { WM_ACTIVATE
, sent
|wparam
, 1 },
16273 { HCBT_SETFOCUS
, hook
},
16274 { WM_KILLFOCUS
, sent
|defwinproc
},
16275 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 0 },
16276 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
16277 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 1 },
16278 { WM_IME_NOTIFY
, sent
|wparam
|defwinproc
|optional
, 2 },
16279 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16280 { WM_SETFOCUS
, sent
|defwinproc
},
16285 static void test_SetActiveWindow(void)
16287 HWND hwnd
, popup
, ret
;
16289 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
16290 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16291 100, 100, 200, 200, 0, 0, 0, NULL
);
16293 popup
= CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow",
16294 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_POPUP
,
16295 100, 100, 200, 200, hwnd
, 0, 0, NULL
);
16297 ok(hwnd
!= 0, "Failed to create overlapped window\n");
16298 ok(popup
!= 0, "Failed to create popup window\n");
16299 SetForegroundWindow( popup
);
16302 if (winetest_debug
> 1) trace("SetActiveWindow(0)\n");
16303 ret
= SetActiveWindow(0);
16304 ok( ret
== popup
|| broken(ret
== 0) /* w1064v1809 */, "Failed to SetActiveWindow(0), ret:%p\n", ret
);
16305 if (ret
== popup
) ok_sequence(SetActiveWindowSeq0
, "SetActiveWindow(0)", FALSE
);
16308 if (winetest_debug
> 1) trace("SetActiveWindow(hwnd), hwnd visible\n");
16309 ret
= SetActiveWindow(hwnd
);
16310 if (ret
== hwnd
) ok_sequence(SetActiveWindowSeq1
, "SetActiveWindow(hwnd), hwnd visible", TRUE
);
16313 if (winetest_debug
> 1) trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
16314 ret
= SetActiveWindow(popup
);
16315 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup), popup visible\n");
16316 ok_sequence(SetActiveWindowSeq2
, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE
);
16319 ShowWindow(hwnd
, SW_HIDE
);
16320 ShowWindow(popup
, SW_HIDE
);
16323 if (winetest_debug
> 1) trace("SetActiveWindow(hwnd), hwnd not visible\n");
16324 ret
= SetActiveWindow(hwnd
);
16325 ok( ret
== NULL
, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret
);
16326 ok_sequence(SetActiveWindowSeq3
, "SetActiveWindow(hwnd), hwnd not visible", TRUE
);
16329 if (winetest_debug
> 1) trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n");
16330 ret
= SetActiveWindow(popup
);
16331 ok( ret
== hwnd
, "Failed to SetActiveWindow(popup)\n");
16332 ok_sequence(SetActiveWindowSeq4
, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE
);
16335 if (winetest_debug
> 1) trace("done\n");
16337 DestroyWindow(hwnd
);
16340 static const struct message SetForegroundWindowSeq
[] =
16342 { WM_NCACTIVATE
, sent
|wparam
, 0 },
16343 { WM_GETTEXT
, sent
|defwinproc
|optional
},
16344 { WM_ACTIVATE
, sent
|wparam
, 0 },
16345 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
16346 { WM_KILLFOCUS
, sent
},
16347 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
, 0 },
16348 { WM_IME_NOTIFY
, sent
|wparam
|optional
|defwinproc
, 1 },
16352 static void test_SetForegroundWindow(void)
16356 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow",
16357 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16358 100, 100, 200, 200, 0, 0, 0, NULL
);
16359 ok (hwnd
!= 0, "Failed to create overlapped window\n");
16360 SetForegroundWindow( hwnd
);
16363 if (winetest_debug
> 1) trace("SetForegroundWindow( 0 )\n");
16364 SetForegroundWindow( 0 );
16365 ok_sequence(WmEmptySeq
, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE
);
16366 if (winetest_debug
> 1) trace("SetForegroundWindow( GetDesktopWindow() )\n");
16367 SetForegroundWindow( GetDesktopWindow() );
16368 ok_sequence(SetForegroundWindowSeq
, "SetForegroundWindow( desktop ) away from "
16369 "foreground top level window", FALSE
);
16370 if (winetest_debug
> 1) trace("done\n");
16372 DestroyWindow(hwnd
);
16375 static DWORD
get_input_codepage( void )
16379 HKL hkl
= GetKeyboardLayout( 0 );
16381 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
,
16382 (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
16383 if (!ret
) cp
= CP_ACP
;
16387 static void test_dbcs_wm_char(void)
16390 WCHAR wch
, bad_wch
;
16398 struct message wmCharSeq
[2];
16400 DWORD cp
= get_input_codepage();
16402 if (!pGetCPInfoExA
)
16404 win_skip("GetCPInfoExA is not available\n");
16408 pGetCPInfoExA( cp
, 0, &cpinfo
);
16409 if (cpinfo
.MaxCharSize
!= 2)
16411 skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo
.CodePageName
);
16415 dbch
[0] = dbch
[1] = 0;
16417 bad_wch
= cpinfo
.UnicodeDefaultChar
;
16418 for (i
= 0; !wch
&& i
< MAX_LEADBYTES
&& cpinfo
.LeadByte
[i
]; i
+= 2)
16419 for (j
= cpinfo
.LeadByte
[i
]; !wch
&& j
<= cpinfo
.LeadByte
[i
+1]; j
++)
16420 for (k
= 128; k
<= 255; k
++)
16426 if (MultiByteToWideChar( cp
, 0, str
, 2, wstr
, 2 ) == 1 &&
16427 WideCharToMultiByte( cp
, 0, wstr
, 1, str
, 2, NULL
, NULL
) == 2 &&
16428 (BYTE
)str
[0] == j
&& (BYTE
)str
[1] == k
&&
16429 HIBYTE(wstr
[0]) && HIBYTE(wstr
[0]) != 0xff)
16440 skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" );
16443 if (winetest_debug
> 1) trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n",
16444 dbch
[0], dbch
[1], wch
, bad_wch
, cpinfo
.CodePageName
);
16446 hwnd
= CreateWindowExW(0, testWindowClassW
, NULL
,
16447 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
16448 hwnd2
= CreateWindowExW(0, testWindowClassW
, NULL
,
16449 WS_OVERLAPPEDWINDOW
, 100, 100, 200, 200, 0, 0, 0, NULL
);
16450 ok (hwnd
!= 0, "Failed to create overlapped window\n");
16451 ok (hwnd2
!= 0, "Failed to create overlapped window\n");
16455 memset( wmCharSeq
, 0, sizeof(wmCharSeq
) );
16456 wmCharSeq
[0].message
= WM_CHAR
;
16457 wmCharSeq
[0].flags
= sent
|wparam
;
16458 wmCharSeq
[0].wParam
= wch
;
16460 /* posted message */
16461 PostMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16462 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16463 ok( !ret
, "got message %x\n", msg
.message
);
16464 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16465 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16466 ok( ret
, "no message\n" );
16467 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16468 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
16469 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16470 ok( !ret
, "got message %x\n", msg
.message
);
16472 /* posted thread message */
16473 PostThreadMessageA( GetCurrentThreadId(), WM_CHAR
, dbch
[0], 0 );
16474 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16475 ok( !ret
, "got message %x\n", msg
.message
);
16476 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16477 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16478 ok( ret
, "no message\n" );
16479 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16480 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
16481 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16482 ok( !ret
, "got message %x\n", msg
.message
);
16486 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16487 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16488 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16489 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16490 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16491 ok( !ret
, "got message %x\n", msg
.message
);
16493 /* sent message with timeout */
16495 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
16496 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16497 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
16498 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16499 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16500 ok( !ret
, "got message %x\n", msg
.message
);
16502 /* sent message with timeout and callback */
16504 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[0], 0, SMTO_NORMAL
, 0, &res
);
16505 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16506 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
16507 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16508 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16509 ok( !ret
, "got message %x\n", msg
.message
);
16511 /* sent message with callback */
16513 SendNotifyMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16514 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16515 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[1], 0, NULL
, 0 );
16516 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16517 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16518 ok( !ret
, "got message %x\n", msg
.message
);
16520 /* direct window proc call */
16522 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
16523 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16524 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
16525 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16527 /* dispatch message */
16529 msg
.message
= WM_CHAR
;
16530 msg
.wParam
= dbch
[0];
16532 DispatchMessageA( &msg
);
16533 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16534 msg
.wParam
= dbch
[1];
16535 DispatchMessageA( &msg
);
16536 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16538 /* window handle is irrelevant */
16540 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
16541 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16542 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16543 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16544 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16545 ok( !ret
, "got message %x\n", msg
.message
);
16547 /* interleaved post and send */
16549 PostMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
16550 SendMessageA( hwnd2
, WM_CHAR
, dbch
[0], 0 );
16551 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16552 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16553 ok( !ret
, "got message %x\n", msg
.message
);
16554 PostMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16555 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16556 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16557 ok( ret
, "no message\n" );
16558 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16559 ok( msg
.wParam
== wch
, "bad wparam %Ix/%x\n", msg
.wParam
, wch
);
16560 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16561 ok( !ret
, "got message %x\n", msg
.message
);
16562 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16563 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16564 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16565 ok( !ret
, "got message %x\n", msg
.message
);
16567 /* interleaved sent message and winproc */
16569 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16570 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
16571 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16572 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16573 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16574 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
16575 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16577 /* interleaved winproc and dispatch */
16579 msg
.message
= WM_CHAR
;
16580 msg
.wParam
= dbch
[0];
16582 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[0], 0 );
16583 DispatchMessageA( &msg
);
16584 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16585 msg
.wParam
= dbch
[1];
16586 DispatchMessageA( &msg
);
16587 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16588 CallWindowProcA( (WNDPROC
)GetWindowLongPtrA( hwnd
, GWLP_WNDPROC
), hwnd
, WM_CHAR
, dbch
[1], 0 );
16589 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16591 /* interleaved sends */
16593 SendMessageA( hwnd
, WM_CHAR
, dbch
[0], 0 );
16594 SendMessageCallbackA( hwnd
, WM_CHAR
, dbch
[0], 0, NULL
, 0 );
16595 ok_sequence( WmEmptySeq
, "no messages", FALSE
);
16596 SendMessageTimeoutA( hwnd
, WM_CHAR
, dbch
[1], 0, SMTO_NORMAL
, 0, &res
);
16597 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16598 SendMessageA( hwnd
, WM_CHAR
, dbch
[1], 0 );
16599 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16603 SendMessageA( hwnd2
, WM_CHAR
, (dbch
[1] << 8) | dbch
[0], 0 );
16604 ok_sequence( wmCharSeq
, "Unicode WM_CHAR", FALSE
);
16605 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16606 ok( !ret
, "got message %x\n", msg
.message
);
16608 /* other char messages are not magic */
16609 PostMessageA( hwnd
, WM_SYSCHAR
, dbch
[0], 0 );
16610 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16611 ok( ret
, "no message\n" );
16612 ok( msg
.message
== WM_SYSCHAR
, "unexpected message %x\n", msg
.message
);
16613 ok( msg
.wParam
== bad_wch
, "bad wparam %Ix/%x\n", msg
.wParam
, bad_wch
);
16614 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16615 ok( !ret
, "got message %x\n", msg
.message
);
16616 PostMessageA( hwnd
, WM_DEADCHAR
, dbch
[0], 0 );
16617 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16618 ok( ret
, "no message\n" );
16619 ok( msg
.message
== WM_DEADCHAR
, "unexpected message %x\n", msg
.message
);
16620 ok( msg
.wParam
== bad_wch
, "bad wparam %Ix/%x\n", msg
.wParam
, bad_wch
);
16621 ret
= PeekMessageW( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16622 ok( !ret
, "got message %x\n", msg
.message
);
16624 /* test retrieving messages */
16626 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
16627 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16628 ok( ret
, "no message\n" );
16629 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16630 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16631 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16632 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16633 ok( ret
, "no message\n" );
16634 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16635 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16636 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16637 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16638 ok( !ret
, "got message %x\n", msg
.message
);
16640 /* message filters */
16641 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
16642 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16643 ok( ret
, "no message\n" );
16644 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16645 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16646 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16647 /* message id is filtered, hwnd is not */
16648 ret
= PeekMessageA( &msg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
);
16649 ok( !ret
, "no message\n" );
16650 ret
= PeekMessageA( &msg
, hwnd2
, 0, 0, PM_REMOVE
);
16651 ok( ret
, "no message\n" );
16652 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16653 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16654 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16655 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16656 ok( !ret
, "got message %x\n", msg
.message
);
16658 /* mixing GetMessage and PostMessage */
16659 PostMessageW( hwnd
, WM_CHAR
, wch
, 0xbeef );
16660 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
16661 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16662 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16663 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16664 ok( msg
.lParam
== 0xbeef, "bad lparam %Ix\n", msg
.lParam
);
16667 ok( time
- GetTickCount() <= 100, "bad time %lx\n", msg
.time
);
16668 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
16669 ok( ret
, "no message\n" );
16670 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16671 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16672 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16673 ok( msg
.lParam
== 0xbeef, "bad lparam %Ix\n", msg
.lParam
);
16674 ok( msg
.time
== time
, "bad time %lx/%lx\n", msg
.time
, time
);
16675 ok( msg
.pt
.x
== pt
.x
&& msg
.pt
.y
== pt
.y
, "bad point %lu,%lu/%lu,%lu\n", msg
.pt
.x
, msg
.pt
.y
, pt
.x
, pt
.y
);
16676 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16677 ok( !ret
, "got message %x\n", msg
.message
);
16679 /* without PM_REMOVE */
16680 PostMessageW( hwnd
, WM_CHAR
, wch
, 0 );
16681 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
16682 ok( ret
, "no message\n" );
16683 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16684 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16685 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16686 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
16687 ok( ret
, "no message\n" );
16688 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16689 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16690 ok( msg
.wParam
== dbch
[0], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16691 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
16692 ok( ret
, "no message\n" );
16693 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16694 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16695 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16696 ret
= PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
16697 ok( ret
, "no message\n" );
16698 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16699 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16700 ok( msg
.wParam
== dbch
[1], "bad wparam %Ix/%x\n", msg
.wParam
, dbch
[0] );
16701 ret
= PeekMessageA( &msg
, hwnd
, 0, 0, PM_REMOVE
);
16702 ok( !ret
, "got message %x\n", msg
.message
);
16704 DestroyWindow(hwnd
);
16705 DestroyWindow(hwnd2
);
16708 static void test_unicode_wm_char(void)
16712 struct message seq
[2];
16713 HKL hkl_orig
, hkl_greek
;
16715 LCID thread_locale
;
16717 hkl_orig
= GetKeyboardLayout( 0 );
16718 GetLocaleInfoW( LOWORD( hkl_orig
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
16721 skip( "Default codepage %ld\n", cp
);
16725 hkl_greek
= LoadKeyboardLayoutA( "00000408", 0 );
16726 if (!hkl_greek
|| hkl_greek
== hkl_orig
/* win2k */)
16728 skip( "Unable to load Greek keyboard layout\n" );
16732 hwnd
= CreateWindowExW( 0, testWindowClassW
, NULL
, WS_OVERLAPPEDWINDOW
,
16733 100, 100, 200, 200, 0, 0, 0, NULL
);
16736 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
16738 while (GetMessageW( &msg
, hwnd
, 0, 0 ))
16740 if (!ignore_message( msg
.message
)) break;
16743 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16744 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16745 ok( msg
.wParam
== 0x3b1, "bad wparam %Ix\n", msg
.wParam
);
16746 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
16748 DispatchMessageW( &msg
);
16750 memset( seq
, 0, sizeof(seq
) );
16751 seq
[0].message
= WM_CHAR
;
16752 seq
[0].flags
= sent
|wparam
;
16753 seq
[0].wParam
= 0x3b1;
16755 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
16759 /* greek alpha -> 'a' in cp1252 */
16760 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
16762 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
16763 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16764 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16765 ok( msg
.wParam
== 0x61, "bad wparam %Ix\n", msg
.wParam
);
16766 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
16768 DispatchMessageA( &msg
);
16770 seq
[0].wParam
= 0x61;
16771 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
16773 thread_locale
= GetThreadLocale();
16774 ActivateKeyboardLayout( hkl_greek
, 0 );
16775 ok( GetThreadLocale() == thread_locale
, "locale changed from %08lx to %08lx\n",
16776 thread_locale
, GetThreadLocale() );
16780 /* greek alpha -> 0xe1 in cp1253 */
16781 PostMessageW( hwnd
, WM_CHAR
, 0x3b1, 0 );
16783 ok( GetMessageA( &msg
, hwnd
, 0, 0 ), "no message\n" );
16784 ok( msg
.hwnd
== hwnd
, "unexpected hwnd %p\n", msg
.hwnd
);
16785 ok( msg
.message
== WM_CHAR
, "unexpected message %x\n", msg
.message
);
16786 ok( msg
.wParam
== 0xe1, "bad wparam %Ix\n", msg
.wParam
);
16787 ok( msg
.lParam
== 0, "bad lparam %Ix\n", msg
.lParam
);
16789 DispatchMessageA( &msg
);
16791 seq
[0].wParam
= 0x3b1;
16792 ok_sequence( seq
, "unicode WM_CHAR", FALSE
);
16794 DestroyWindow( hwnd
);
16795 ActivateKeyboardLayout( hkl_orig
, 0 );
16798 #define ID_LISTBOX 0x000f
16800 static const struct message wm_lb_setcursel_0
[] =
16802 { LB_SETCURSEL
, sent
|wparam
|lparam
, 0, 0 },
16803 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16804 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
16805 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16806 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16809 static const struct message wm_lb_setcursel_1
[] =
16811 { LB_SETCURSEL
, sent
|wparam
|lparam
, 1, 0 },
16812 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16813 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000020f2 },
16814 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16815 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000121f2 },
16816 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 2 },
16817 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 2 },
16820 static const struct message wm_lb_setcursel_2
[] =
16822 { LB_SETCURSEL
, sent
|wparam
|lparam
, 2, 0 },
16823 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16824 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000021f2 },
16825 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16826 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000122f2 },
16827 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 3 },
16828 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 3 },
16831 static const struct message wm_lb_click_0
[] =
16833 { WM_LBUTTONDOWN
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
16834 { HCBT_SETFOCUS
, hook
},
16835 { WM_KILLFOCUS
, sent
|parent
},
16836 { WM_IME_SETCONTEXT
, sent
|wparam
|optional
|parent
, 0 },
16837 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
16838 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
16839 { WM_SETFOCUS
, sent
|defwinproc
},
16841 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001142f2 },
16842 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SETFOCUS
) },
16843 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 3 },
16844 { WM_LBTRACKPOINT
, sent
|wparam
|lparam
|parent
, 0, MAKELPARAM(1,1) },
16845 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
16847 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000142f2 },
16848 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16849 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000022f2 },
16850 { WM_CTLCOLORLISTBOX
, sent
|parent
},
16851 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x000120f2 },
16852 { WM_DRAWITEM
, sent
|wparam
|lparam
|parent
, ID_LISTBOX
, 0x001140f2 },
16854 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16855 { EVENT_OBJECT_SELECTION
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16857 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
16858 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
16859 { WM_CAPTURECHANGED
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
16860 { WM_COMMAND
, sent
|wparam
|parent
, MAKEWPARAM(ID_LISTBOX
, LBN_SELCHANGE
) },
16863 static const struct message wm_lb_deletestring
[] =
16865 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
16866 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16867 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
16868 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16869 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16872 static const struct message wm_lb_deletestring_reset
[] =
16874 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
16875 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16876 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
|optional
, 0, 0 },
16877 { WM_DELETEITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
, 0 },
16878 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16879 { WM_DRAWITEM
, sent
|wparam
|parent
|optional
, ID_LISTBOX
},
16882 static const struct message wm_lb_addstring
[] =
16884 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
16885 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16886 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
16887 /* Child ID changes each test, don't test lparam. */
16888 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|msg_todo
, OBJID_CLIENT
, 0 },
16889 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
16890 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|msg_todo
, OBJID_CLIENT
, 0 },
16893 static const struct message wm_lb_addstring_ownerdraw
[] =
16895 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
16896 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
16897 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16898 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
16899 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
16900 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 2 },
16901 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
16902 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
16903 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 3 },
16906 static const struct message wm_lb_addstring_sort_ownerdraw
[] =
16908 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ed },
16909 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf0f2, 0xf30604ed },
16910 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
16911 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ee },
16912 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ee },
16913 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf1f2, 0xf30604ee },
16914 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 2 },
16915 { LB_ADDSTRING
, sent
|wparam
|lparam
, 0, 0xf30604ef },
16916 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ed, 0xf30604ef },
16917 { WM_COMPAREITEM
, sent
|wparam
|lparam
|parent
, 0xf30604ee, 0xf30604ef },
16918 { WM_MEASUREITEM
, sent
|wparam
|lparam
|parent
, 0xf2f2, 0xf30604ef },
16919 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 3 },
16922 static const struct message wm_lb_dblclick_0
[] =
16924 { WM_LBUTTONDBLCLK
, sent
|wparam
|lparam
, 0, MAKELPARAM(1,1) },
16925 { WM_LBUTTONUP
, sent
|wparam
|lparam
, 0, 0 },
16929 #define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
16931 static LRESULT (WINAPI
*listbox_orig_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
16933 static LRESULT WINAPI
listbox_hook_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
16935 static LONG defwndproc_counter
= 0;
16937 struct recvd_message msg
;
16939 /* do not log painting messages */
16940 if (message
!= WM_PAINT
&&
16941 message
!= WM_NCPAINT
&&
16942 message
!= WM_SYNCPAINT
&&
16943 message
!= WM_ERASEBKGND
&&
16944 message
!= WM_NCHITTEST
&&
16945 message
!= WM_GETTEXT
&&
16946 !ignore_message( message
))
16949 msg
.message
= message
;
16950 msg
.flags
= sent
|wparam
|lparam
;
16951 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
16953 if (message
== LB_ADDSTRING
)
16954 msg
.lParam
= lp
? hash_Ly((const char *)lp
) : 0;
16957 msg
.descr
= "listbox";
16961 defwndproc_counter
++;
16962 ret
= CallWindowProcA(listbox_orig_proc
, hwnd
, message
, wp
, lp
);
16963 defwndproc_counter
--;
16968 static void check_lb_state_dbg(HWND listbox
, int count
, int cur_sel
,
16969 int caret_index
, int top_index
, int line
)
16973 /* calling an orig proc helps to avoid unnecessary message logging */
16974 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCOUNT
, 0, 0);
16975 ok_(__FILE__
, line
)(ret
== count
, "expected count %d, got %Id\n", count
, ret
);
16976 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCURSEL
, 0, 0);
16977 ok_(__FILE__
, line
)(ret
== cur_sel
, "expected cur sel %d, got %Id\n", cur_sel
, ret
);
16978 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETCARETINDEX
, 0, 0);
16979 ok_(__FILE__
, line
)(ret
== caret_index
||
16980 broken(cur_sel
== -1 && caret_index
== 0 && ret
== -1), /* nt4 */
16981 "expected caret index %d, got %Id\n", caret_index
, ret
);
16982 ret
= CallWindowProcA(listbox_orig_proc
, listbox
, LB_GETTOPINDEX
, 0, 0);
16983 ok_(__FILE__
, line
)(ret
== top_index
, "expected top index %d, got %Id\n", top_index
, ret
);
16986 static void test_listbox_messages(void)
16988 HWND parent
, listbox
;
16991 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
16992 100, 100, 200, 200, 0, 0, 0, NULL
);
16993 /* with LBS_HASSTRINGS */
16994 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
16995 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
16996 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
16997 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
16999 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17003 log_all_parent_messages
++;
17005 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
17006 ok(ret
== 0, "expected 0, got %Id\n", ret
);
17007 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
17008 ok(ret
== 1, "expected 1, got %Id\n", ret
);
17009 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
17010 ok(ret
== 2, "expected 2, got %Id\n", ret
);
17012 ok_sequence(wm_lb_addstring_ownerdraw
, "LB_ADDSTRING", FALSE
);
17013 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
17017 if (winetest_debug
> 1) trace("selecting item 0\n");
17018 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
17019 ok(ret
== 0, "expected 0, got %Id\n", ret
);
17020 ok_sequence(wm_lb_setcursel_0
, "LB_SETCURSEL 0", FALSE
);
17021 check_lb_state(listbox
, 3, 0, 0, 0);
17024 if (winetest_debug
> 1) trace("selecting item 1\n");
17025 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 1, 0);
17026 ok(ret
== 1, "expected 1, got %Id\n", ret
);
17027 ok_sequence(wm_lb_setcursel_1
, "LB_SETCURSEL 1", FALSE
);
17028 check_lb_state(listbox
, 3, 1, 1, 0);
17030 if (winetest_debug
> 1) trace("selecting item 2\n");
17031 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
17032 ok(ret
== 2, "expected 2, got %Id\n", ret
);
17033 ok_sequence(wm_lb_setcursel_2
, "LB_SETCURSEL 2", FALSE
);
17034 check_lb_state(listbox
, 3, 2, 2, 0);
17036 if (winetest_debug
> 1) trace("clicking on item 0\n");
17037 ret
= SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(1, 1));
17038 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17039 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
17040 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17041 ok_sequence(wm_lb_click_0
, "WM_LBUTTONDOWN 0", FALSE
);
17042 check_lb_state(listbox
, 3, 0, 0, 0);
17045 if (winetest_debug
> 1) trace("deleting item 0\n");
17046 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
17047 ok(ret
== 2, "expected 2, got %Id\n", ret
);
17048 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
17049 check_lb_state(listbox
, 2, -1, 0, 0);
17052 if (winetest_debug
> 1) trace("deleting item 0\n");
17053 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
17054 ok(ret
== 1, "expected 1, got %Id\n", ret
);
17055 ok_sequence(wm_lb_deletestring
, "LB_DELETESTRING 0", FALSE
);
17056 check_lb_state(listbox
, 1, -1, 0, 0);
17059 if (winetest_debug
> 1) trace("deleting item 0\n");
17060 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
17061 ok(ret
== 0, "expected 0, got %Id\n", ret
);
17062 ok_sequence(wm_lb_deletestring_reset
, "LB_DELETESTRING 0", FALSE
);
17063 check_lb_state(listbox
, 0, -1, 0, 0);
17066 if (winetest_debug
> 1) trace("deleting item 0\n");
17067 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
17068 ok(ret
== LB_ERR
, "expected LB_ERR, got %Id\n", ret
);
17069 check_lb_state(listbox
, 0, -1, 0, 0);
17072 ret
= SendMessageA(listbox
, LB_DELETESTRING
, 0, 0);
17073 ok(ret
== LB_ERR
, "expected LB_ERR, got %Id\n", ret
);
17074 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17077 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
17078 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17079 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17082 if (winetest_debug
> 1) trace("clicking on item 0\n");
17083 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
17084 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17085 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
17086 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17087 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
17088 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17091 log_all_parent_messages
--;
17093 DestroyWindow(listbox
);
17095 /* with LBS_SORT and without LBS_HASSTRINGS */
17096 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
17097 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_SORT
| WS_VISIBLE
,
17098 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
17099 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
17101 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17105 log_all_parent_messages
++;
17107 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
17108 ok(ret
== 0, "expected 0, got %Id\n", ret
);
17109 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
17110 ok(ret
== 1, "expected 1, got %Id\n", ret
);
17111 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
17112 ok(ret
== 2, "expected 2, got %Id\n", ret
);
17114 ok_sequence(wm_lb_addstring_sort_ownerdraw
, "LB_ADDSTRING", FALSE
);
17115 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
17117 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
17118 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17119 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17120 SetFocus(listbox
); /* avoid focus messages */
17123 if (winetest_debug
> 1) trace("clicking on item 0\n");
17124 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
17125 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17126 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
17127 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17128 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
17129 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17132 log_all_parent_messages
--;
17134 DestroyWindow(listbox
);
17136 /* with LBS_HASSTRINGS */
17137 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
17138 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| WS_VISIBLE
,
17139 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
17140 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
17142 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17146 log_all_parent_messages
++;
17148 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
17149 ok(ret
== 0, "expected 0, got %Id\n", ret
);
17150 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
17151 ok(ret
== 1, "expected 1, got %Id\n", ret
);
17152 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
17153 ok(ret
== 2, "expected 2, got %Id\n", ret
);
17155 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
17156 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
17158 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
17159 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17160 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17161 SetFocus(listbox
); /* avoid focus messages */
17164 if (winetest_debug
> 1) trace("clicking on item 0\n");
17165 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
17166 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17167 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
17168 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17169 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
17170 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17173 log_all_parent_messages
--;
17175 DestroyWindow(listbox
);
17177 /* with LBS_HASSTRINGS and LBS_SORT */
17178 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, "ListBox", NULL
,
17179 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| LBS_SORT
| WS_VISIBLE
,
17180 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
17181 listbox_orig_proc
= (WNDPROC
)SetWindowLongPtrA(listbox
, GWLP_WNDPROC
, (ULONG_PTR
)listbox_hook_proc
);
17183 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17187 log_all_parent_messages
++;
17189 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
17190 ok(ret
== 0, "expected 0, got %Id\n", ret
);
17191 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
17192 ok(ret
== 0, "expected 0, got %Id\n", ret
);
17193 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
17194 ok(ret
== 1, "expected 1, got %Id\n", ret
);
17196 ok_sequence(wm_lb_addstring
, "LB_ADDSTRING", FALSE
);
17197 check_lb_state(listbox
, 3, LB_ERR
, 0, 0);
17199 ret
= SendMessageA(listbox
, LB_RESETCONTENT
, 0, 0);
17200 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17201 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17202 SetFocus(listbox
); /* avoid focus messages */
17205 if (winetest_debug
> 1) trace("clicking on item 0\n");
17206 ret
= SendMessageA(listbox
, WM_LBUTTONDBLCLK
, 0, MAKELPARAM(1, 1));
17207 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17208 ret
= SendMessageA(listbox
, WM_LBUTTONUP
, 0, 0);
17209 ok(ret
== LB_OKAY
, "expected LB_OKAY, got %Id\n", ret
);
17210 ok_sequence(wm_lb_dblclick_0
, "WM_LBUTTONDBLCLK 0", FALSE
);
17211 check_lb_state(listbox
, 0, LB_ERR
, 0, 0);
17214 log_all_parent_messages
--;
17216 DestroyWindow(listbox
);
17217 DestroyWindow(parent
);
17220 /*************************** Menu test ******************************/
17221 static const struct message wm_popup_menu_1
[] =
17223 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17224 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17225 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0x20000001 },
17226 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'E', 0x20000001 },
17227 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'e', 0x20000001 },
17228 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'e' },
17229 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17230 { WM_INITMENU
, sent
|lparam
, 0, 0 },
17231 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(1,MF_HILITE
|MF_POPUP
) },
17232 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 1 },
17233 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't create a window */
17234 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17235 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17236 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17237 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17238 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17239 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(200,MF_HILITE
) },
17240 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
17241 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'E', 0xf0000001 },
17242 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
17243 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001, 0, 0x40000000 },
17244 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_MENU
, 0 },
17245 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17246 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't create a window */
17247 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17248 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17249 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17250 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
17251 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17252 { WM_MENUCOMMAND
, sent
}, /* |wparam, 200 - Win9x */
17253 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
17254 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
17257 static const struct message wm_popup_menu_2
[] =
17259 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17260 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17261 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
17262 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
17263 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
17264 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
17265 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17266 { WM_INITMENU
, sent
|lparam
, 0, 0 },
17267 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
17268 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
17269 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
17270 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
17271 { HCBT_CREATEWND
, hook
},
17272 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17273 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17274 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17275 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17276 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17277 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
17278 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
17279 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
17280 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
17281 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
17282 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
17283 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
17284 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
17285 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17286 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17287 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17288 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17289 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17290 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
17291 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
17292 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
17293 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
17294 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_MENU
, 0 },
17295 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17296 { HCBT_DESTROYWND
, hook
},
17297 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17298 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17299 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17300 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17301 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
17302 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17303 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17304 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17305 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
17306 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17307 { WM_MENUCOMMAND
, sent
}, /* |wparam, 100 - Win9x */
17308 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
17309 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
17312 static const struct message wm_popup_menu_3
[] =
17314 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17315 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17316 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0x20000001 },
17317 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'F', 0x20000001 },
17318 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'f', 0x20000001 },
17319 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'f' },
17320 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17321 { WM_INITMENU
, sent
|lparam
, 0, 0 },
17322 { WM_MENUSELECT
, sent
|wparam
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) },
17323 { WM_INITMENUPOPUP
, sent
|lparam
, 0, 0 },
17324 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(0,MF_HILITE
|MF_POPUP
) }, /* Win9x */
17325 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x */
17326 { HCBT_CREATEWND
, hook
},
17327 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17328 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17329 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17330 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17331 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17332 { WM_MENUSELECT
, sent
}, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP
17333 |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */
17334 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
17335 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'F', 0xf0000001 },
17336 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xd0000001 },
17337 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0x10000001 },
17338 { WM_INITMENUPOPUP
, sent
|lparam
|optional
, 0, 0 }, /* Win9x doesn't send it */
17339 { HCBT_CREATEWND
, hook
|optional
}, /* Win9x doesn't send it */
17340 { EVENT_OBJECT_CREATE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17341 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17342 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
17343 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17344 { EVENT_SYSTEM_MENUPOPUPSTART
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17345 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(100,MF_HILITE
) },
17346 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 1 },
17347 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RIGHT
, 0xd0000001 },
17348 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0x10000001 },
17349 { EVENT_OBJECT_INVOKED
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_MENU
, 100 },
17350 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17351 { HCBT_DESTROYWND
, hook
},
17352 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17353 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17354 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17355 { EVENT_SYSTEM_MENUPOPUPEND
, winevent_hook
|wparam
|lparam
|msg_todo
, OBJID_CLIENT
, 0 },
17356 { HCBT_DESTROYWND
, hook
|optional
}, /* Win9x doesn't send it */
17357 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
17358 { EVENT_OBJECT_DESTROY
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17359 { WM_UNINITMENUPOPUP
, sent
|lparam
, 0, 0 },
17360 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
17361 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17362 { WM_COMMAND
, sent
|wparam
|lparam
, 100, 0 },
17363 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_RETURN
, 0xc0000001 },
17364 { WM_KEYUP
, sent
|wparam
|lparam
, VK_RETURN
, 0xc0000001 },
17368 static const struct message wm_single_menu_item
[] =
17370 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
17371 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
17372 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0x20000001 },
17373 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, 'Q', 0x20000001 },
17374 { WM_SYSCHAR
, sent
|wparam
|lparam
, 'q', 0x20000001 },
17375 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_KEYMENU
, 'q' },
17376 { WM_ENTERMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17377 { WM_INITMENU
, sent
|lparam
, 0, 0 },
17378 { WM_MENUSELECT
, sent
|wparam
|optional
, MAKEWPARAM(300,MF_HILITE
) },
17379 { WM_MENUSELECT
, sent
|wparam
|lparam
, MAKEWPARAM(0,0xffff), 0 },
17380 { WM_EXITMENULOOP
, sent
|wparam
|lparam
, 0, 0 },
17381 { WM_MENUCOMMAND
, sent
},
17382 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 'Q', 0xe0000001 },
17383 { WM_SYSKEYUP
, sent
|wparam
|lparam
, 'Q', 0xe0000001 },
17384 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
17385 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
17387 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 1 },
17388 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_ESCAPE
, 1 },
17389 { WM_CHAR
, sent
|wparam
|lparam
, VK_ESCAPE
, 0x00000001 },
17390 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_ESCAPE
, 0xc0000001 },
17391 { WM_KEYUP
, sent
|wparam
|lparam
, VK_ESCAPE
, 0xc0000001 },
17395 static LRESULT WINAPI
parent_menu_proc(HWND hwnd
, UINT message
, WPARAM wp
, LPARAM lp
)
17397 if (message
== WM_ENTERIDLE
||
17398 message
== WM_INITMENU
||
17399 message
== WM_INITMENUPOPUP
||
17400 message
== WM_MENUSELECT
||
17401 message
== WM_PARENTNOTIFY
||
17402 message
== WM_ENTERMENULOOP
||
17403 message
== WM_EXITMENULOOP
||
17404 message
== WM_UNINITMENUPOPUP
||
17405 message
== WM_KEYDOWN
||
17406 message
== WM_KEYUP
||
17407 message
== WM_CHAR
||
17408 message
== WM_SYSKEYDOWN
||
17409 message
== WM_SYSKEYUP
||
17410 message
== WM_SYSCHAR
||
17411 message
== WM_COMMAND
||
17412 message
== WM_MENUCOMMAND
)
17414 struct recvd_message msg
;
17417 msg
.message
= message
;
17418 msg
.flags
= sent
|wparam
|lparam
;
17421 msg
.descr
= "parent_menu_proc";
17425 return DefWindowProcA(hwnd
, message
, wp
, lp
);
17428 static void set_menu_style(HMENU hmenu
, DWORD style
)
17433 mi
.cbSize
= sizeof(mi
);
17434 mi
.fMask
= MIM_STYLE
;
17435 mi
.dwStyle
= style
;
17436 SetLastError(0xdeadbeef);
17437 ret
= SetMenuInfo(hmenu
, &mi
);
17438 ok(ret
, "SetMenuInfo error %lu\n", GetLastError());
17441 static DWORD
get_menu_style(HMENU hmenu
)
17446 mi
.cbSize
= sizeof(mi
);
17447 mi
.fMask
= MIM_STYLE
;
17449 SetLastError(0xdeadbeef);
17450 ret
= GetMenuInfo(hmenu
, &mi
);
17451 ok(ret
, "GetMenuInfo error %lu\n", GetLastError());
17456 static void test_menu_messages(void)
17460 HMENU hmenu
, hmenu_popup
;
17463 BOOL us_kbd
= (GetKeyboardLayout(0) == (HKL
)(ULONG_PTR
)0x04090409);
17466 cls
.lpfnWndProc
= parent_menu_proc
;
17467 cls
.cbClsExtra
= 0;
17468 cls
.cbWndExtra
= 0;
17469 cls
.hInstance
= GetModuleHandleA(0);
17471 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
17472 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
17473 cls
.lpszMenuName
= NULL
;
17474 cls
.lpszClassName
= "TestMenuClass";
17475 UnregisterClassA(cls
.lpszClassName
, cls
.hInstance
);
17476 register_class(&cls
);
17478 SetLastError(0xdeadbeef);
17479 hwnd
= CreateWindowExA(0, "TestMenuClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
17480 100, 100, 200, 200, 0, 0, 0, NULL
);
17481 ok(hwnd
!= 0, "LoadMenuA error %lu\n", GetLastError());
17483 SetLastError(0xdeadbeef);
17484 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
17485 ok(hmenu
!= 0, "LoadMenuA error %lu\n", GetLastError());
17487 SetMenu(hwnd
, hmenu
);
17488 SetForegroundWindow( hwnd
);
17491 set_menu_style(hmenu
, MNS_NOTIFYBYPOS
);
17492 style
= get_menu_style(hmenu
);
17493 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %lu\n", style
);
17495 hmenu_popup
= GetSubMenu(hmenu
, 0);
17496 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17497 style
= get_menu_style(hmenu_popup
);
17498 ok(style
== 0, "expected 0, got %lu\n", style
);
17500 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
17501 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17502 style
= get_menu_style(hmenu_popup
);
17503 ok(style
== 0, "expected 0, got %lu\n", style
);
17507 skip("skipping ascii VK events on non-us keyboard\n");
17512 if (winetest_debug
> 1) trace("testing a popup menu command\n");
17514 keybd_event(VK_MENU
, 0, 0, 0);
17515 keybd_event('E', 0, 0, 0);
17516 keybd_event('E', 0, KEYEVENTF_KEYUP
, 0);
17517 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17518 keybd_event(VK_RETURN
, 0, 0, 0);
17519 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
17520 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17522 TranslateMessage(&msg
);
17523 DispatchMessageA(&msg
);
17525 if (!sequence_cnt
) /* we didn't get any message */
17527 skip( "queuing key events not supported\n" );
17530 /* win98 queues only a WM_KEYUP and doesn't start menu tracking */
17531 if (sequence
[0].message
== WM_KEYUP
&& sequence
[0].wParam
== VK_MENU
)
17533 win_skip( "menu tracking through VK_MENU not supported\n" );
17536 ok_sequence(wm_popup_menu_1
, "popup menu command", FALSE
);
17538 /* Alt+F, Right, Enter */
17539 if (winetest_debug
> 1) trace("testing submenu of a popup menu command\n");
17541 keybd_event(VK_MENU
, 0, 0, 0);
17542 keybd_event('F', 0, 0, 0);
17543 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
17544 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17545 keybd_event(VK_RIGHT
, 0, 0, 0);
17546 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
17547 keybd_event(VK_RETURN
, 0, 0, 0);
17548 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
17549 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17551 TranslateMessage(&msg
);
17552 DispatchMessageA(&msg
);
17554 ok_sequence(wm_popup_menu_2
, "submenu of a popup menu command", FALSE
);
17556 if (winetest_debug
> 1) trace("testing single menu item command\n");
17558 keybd_event(VK_MENU
, 0, 0, 0);
17559 keybd_event('Q', 0, 0, 0);
17560 keybd_event('Q', 0, KEYEVENTF_KEYUP
, 0);
17561 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17562 keybd_event(VK_ESCAPE
, 0, 0, 0);
17563 keybd_event(VK_ESCAPE
, 0, KEYEVENTF_KEYUP
, 0);
17564 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17566 TranslateMessage(&msg
);
17567 DispatchMessageA(&msg
);
17569 ok_sequence(wm_single_menu_item
, "single menu item command", FALSE
);
17571 set_menu_style(hmenu
, 0);
17572 style
= get_menu_style(hmenu
);
17573 ok(style
== 0, "expected 0, got %lu\n", style
);
17575 hmenu_popup
= GetSubMenu(hmenu
, 0);
17576 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17577 set_menu_style(hmenu_popup
, MNS_NOTIFYBYPOS
);
17578 style
= get_menu_style(hmenu_popup
);
17579 ok(style
== MNS_NOTIFYBYPOS
, "expected MNS_NOTIFYBYPOS, got %lu\n", style
);
17581 hmenu_popup
= GetSubMenu(hmenu_popup
, 0);
17582 ok(hmenu_popup
!= 0, "GetSubMenu returned 0 for submenu 0\n");
17583 style
= get_menu_style(hmenu_popup
);
17584 ok(style
== 0, "expected 0, got %lu\n", style
);
17586 /* Alt+F, Right, Enter */
17587 if (winetest_debug
> 1) trace("testing submenu of a popup menu command\n");
17589 keybd_event(VK_MENU
, 0, 0, 0);
17590 keybd_event('F', 0, 0, 0);
17591 keybd_event('F', 0, KEYEVENTF_KEYUP
, 0);
17592 keybd_event(VK_MENU
, 0, KEYEVENTF_KEYUP
, 0);
17593 keybd_event(VK_RIGHT
, 0, 0, 0);
17594 keybd_event(VK_RIGHT
, 0, KEYEVENTF_KEYUP
, 0);
17595 keybd_event(VK_RETURN
, 0, 0, 0);
17596 keybd_event(VK_RETURN
, 0, KEYEVENTF_KEYUP
, 0);
17597 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
17599 TranslateMessage(&msg
);
17600 DispatchMessageA(&msg
);
17602 ok_sequence(wm_popup_menu_3
, "submenu of a popup menu command", FALSE
);
17605 DestroyWindow(hwnd
);
17606 DestroyMenu(hmenu
);
17610 static void test_paintingloop(void)
17614 paint_loop_done
= FALSE
;
17615 hwnd
= CreateWindowExA(0x0,"PaintLoopWindowClass",
17616 "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW
,
17617 100, 100, 100, 100, 0, 0, 0, NULL
);
17618 ok(hwnd
!= 0, "PaintLoop window error %lu\n", GetLastError());
17619 ShowWindow(hwnd
,SW_NORMAL
);
17622 while (!paint_loop_done
)
17625 if (PeekMessageA(&msg
, 0, 0, 0, 1))
17627 TranslateMessage(&msg
);
17628 DispatchMessageA(&msg
);
17631 DestroyWindow(hwnd
);
17634 static const struct message NCRBUTTONDOWNSeq
[] =
17636 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17637 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17638 { WM_CAPTURECHANGED
, sent
},
17639 { WM_CONTEXTMENU
, sent
, /*hwnd*/0, -1 },
17643 static const struct message NCXBUTTONUPSeq1
[] =
17645 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_BACKWARD
) },
17649 static const struct message NCXBUTTONUPSeq2
[] =
17651 { WM_APPCOMMAND
, sent
|lparam
, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE
| APPCOMMAND_BROWSER_FORWARD
) },
17655 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to minimized visible window */
17656 static const struct message WmRestoreMinimizedOverlappedSeq
[] =
17658 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_RESTORE
, 0 },
17659 { HCBT_MINMAX
, hook
},
17660 { WM_QUERYOPEN
, sent
},
17661 { WM_GETTEXT
, sent
|optional
},
17662 { WM_NCACTIVATE
, sent
|optional
},
17663 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
17664 { WM_WINDOWPOSCHANGED
, sent
|optional
},
17665 { WM_WINDOWPOSCHANGING
, sent
|optional
},
17666 { WM_GETMINMAXINFO
, sent
|defwinproc
},
17667 { WM_NCCALCSIZE
, sent
|optional
},
17668 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17669 { WM_NCPAINT
, sent
|optional
},
17670 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17671 { WM_ERASEBKGND
, sent
|optional
},
17672 { WM_WINDOWPOSCHANGED
, sent
|optional
},
17673 { HCBT_ACTIVATE
, hook
},
17674 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17675 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
17676 { WM_ACTIVATEAPP
, sent
|wparam
, TRUE
},
17677 { WM_NCACTIVATE
, sent
|wparam
, TRUE
},
17678 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17679 { WM_ACTIVATE
, sent
|wparam
, TRUE
},
17680 { HCBT_SETFOCUS
, hook
},
17681 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
17682 { WM_SETFOCUS
, sent
|defwinproc
},
17683 { WM_NCPAINT
, sent
},
17684 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17685 { WM_ERASEBKGND
, sent
},
17686 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_FRAMECHANGED
|SWP_STATECHANGED
},
17687 { WM_MOVE
, sent
|defwinproc
},
17688 { WM_SIZE
, sent
|defwinproc
},
17689 { WM_NCCALCSIZE
, sent
|optional
},
17690 { WM_NCPAINT
, sent
|optional
},
17691 { WM_ERASEBKGND
, sent
|optional
},
17692 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17693 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
17694 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17695 { WM_ACTIVATE
, sent
|wparam
, TRUE
},
17696 { WM_SYNCPAINT
, sent
|optional
},
17697 { WM_PAINT
, sent
},
17701 /* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to an active minimized window */
17702 static const struct message WmRestoreActiveMinimizedOverlappedSeq
[] =
17704 { HCBT_SYSCOMMAND
, hook
|wparam
|lparam
, SC_RESTORE
, 0 },
17705 { HCBT_MINMAX
, hook
},
17706 { WM_QUERYOPEN
, sent
},
17707 { WM_GETTEXT
, sent
|optional
},
17708 { WM_NCACTIVATE
, sent
},
17709 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
17710 { WM_WINDOWPOSCHANGED
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
17711 { WM_NCCALCSIZE
, sent
|optional
},
17712 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
17713 { WM_MOVE
, sent
|optional
},
17714 { WM_SIZE
, sent
|optional
},
17715 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win7. */
17716 { WM_GETTEXT
, sent
|optional
},
17717 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
17718 { WM_GETMINMAXINFO
, sent
|defwinproc
},
17719 { WM_NCCALCSIZE
, sent
},
17720 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Sent on Win8+. */
17721 { WM_NCPAINT
, sent
},
17722 { WM_GETTEXT
, sent
|defwinproc
|optional
},
17723 { WM_ERASEBKGND
, sent
},
17724 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
17725 { WM_MOVE
, sent
|defwinproc
},
17726 { WM_SIZE
, sent
|defwinproc
},
17727 { WM_NCCALCSIZE
, sent
|optional
},
17728 { WM_NCPAINT
, sent
|optional
},
17729 { WM_ERASEBKGND
, sent
|optional
},
17730 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17731 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 }, /* Win7 seems to send this twice. */
17732 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
17733 { HCBT_SETFOCUS
, hook
},
17734 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
17735 { WM_SETFOCUS
, sent
},
17736 /* Note this WM_ACTIVATE messages even if the window is already active */
17737 { WM_ACTIVATE
, sent
|wparam
|lparam
, WA_ACTIVE
, 0 },
17738 { WM_SYNCPAINT
, sent
|optional
},
17739 { WM_PAINT
, sent
},
17740 { WM_GETMINMAXINFO
, sent
|optional
},
17744 static struct message WmContextMenuSeq
[] = {
17745 { WM_CONTEXTMENU
, sent
|wparam
, 0 }, /* wparams set in the code */
17746 { WM_CONTEXTMENU
, sent
|wparam
|defwinproc
, 0 },
17747 { WM_CONTEXTMENU
, sent
|wparam
|defwinproc
, 0 },
17751 struct rbuttonup_thread_data
17754 HANDLE wndproc_finished
;
17757 static DWORD CALLBACK
post_rbuttonup_msg( void *arg
)
17759 struct rbuttonup_thread_data
*data
= arg
;
17762 ret
= WaitForSingleObject( data
->wndproc_finished
, 500 );
17763 todo_wine
ok( ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lx\n", ret
);
17764 if( ret
== WAIT_OBJECT_0
) return 0;
17766 PostMessageA( data
->hwnd
, WM_RBUTTONUP
, 0, 0 );
17770 static void test_defwinproc(void)
17772 HWND hwnd
, child
[3];
17774 BOOL gotwmquit
= FALSE
;
17779 struct rbuttonup_thread_data data
;
17783 hwnd
= CreateWindowExA(0, "TestWindowClass", "test_defwndproc",
17784 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0,0,500,100,0,0,0, NULL
);
17785 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
17789 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
17790 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
17792 /* Zero high word of the lParam */
17793 res
= DefWindowProcA(hwnd
, WM_SETTEXT
, 0, 0x1234);
17794 ok(res
== 0, "WM_SETTEXT was expected to fail, %Id\n", res
);
17796 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
17797 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
17799 res
= DefWindowProcW(hwnd
, WM_SETTEXT
, 0, 0x1234);
17800 ok(res
== 0, "WM_SETTEXT was expected to fail, %Id\n", res
);
17802 GetWindowTextA(hwnd
, buffA
, ARRAY_SIZE(buffA
));
17803 ok(!strcmp(buffA
, "test_defwndproc"), "unexpected window text, %s\n", buffA
);
17805 ShowWindow(hwnd
, SW_MINIMIZE
);
17809 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
17811 ok_sequence(WmRestoreMinimizedOverlappedSeq
, "DefWindowProcA(SC_RESTORE):overlapped", TRUE
);
17813 ShowWindow(hwnd
, SW_MINIMIZE
);
17814 SetActiveWindow(hwnd
);
17815 ok(GetActiveWindow() == hwnd
, "Unexpected active window\n");
17818 DefWindowProcA(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
17820 ok_sequence(WmRestoreActiveMinimizedOverlappedSeq
, "DefWindowProcA(SC_RESTORE):active minimized overlapped", TRUE
);
17822 child
[0] = CreateWindowExA(0, "TestWindowClass", "1st child",
17823 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, hwnd
, 0, 0, NULL
);
17824 child
[1] = CreateWindowExA(0, "TestWindowClass", "2nd child",
17825 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, child
[0], 0, 0, NULL
);
17826 child
[2] = CreateWindowExA(0, "TestWindowClass", "3rd child",
17827 WS_VISIBLE
| WS_CHILD
, 0,0,500,100, child
[1], 0, 0, NULL
);
17830 test_context_menu
= TRUE
;
17831 DefWindowProcA(child
[2], WM_CONTEXTMENU
, 0xcafe, 0);
17832 test_context_menu
= FALSE
;
17833 WmContextMenuSeq
[0].wParam
= (WPARAM
)child
[2];
17834 WmContextMenuSeq
[1].wParam
= (WPARAM
)child
[1];
17835 WmContextMenuSeq
[2].wParam
= (WPARAM
)child
[0];
17836 ok_sequence(WmContextMenuSeq
, "DefWindowProcA(WM_CONTEXTMENU)", FALSE
);
17837 DestroyWindow(child
[0]);
17839 GetCursorPos(&pos
);
17840 GetWindowRect(hwnd
, &rect
);
17841 x
= (rect
.left
+rect
.right
) / 2;
17842 y
= rect
.top
+ GetSystemMetrics(SM_CYFRAME
) + 1;
17843 SetCursorPos(x
, y
);
17845 res
= DefWindowProcA( hwnd
, WM_NCHITTEST
, 0, MAKELPARAM(x
, y
));
17846 ok(res
== HTCAPTION
, "WM_NCHITTEST returned %Id\n", res
);
17848 mouse_event( MOUSEEVENTF_LEFTDOWN
, 0, 0, 0, 0 );
17849 mouse_event( MOUSEEVENTF_LEFTUP
, 0, 0, 0, 0 );
17853 mouse_event( MOUSEEVENTF_RIGHTUP
, 0, 0, 0, 0 );
17854 /* workaround for missing support for clicking on window frame */
17856 data
.wndproc_finished
= CreateEventA( NULL
, FALSE
, FALSE
, NULL
);
17857 thread
= CreateThread( NULL
, 0, post_rbuttonup_msg
, (void*)&data
, 0, NULL
);
17859 DefWindowProcA( hwnd
, WM_NCRBUTTONDOWN
, HTCAPTION
, MAKELPARAM(x
, y
));
17860 ok_sequence(NCRBUTTONDOWNSeq
, "WM_NCRBUTTONDOWN on caption", FALSE
);
17862 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, 0, MAKELPARAM(x
, y
));
17863 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17864 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP without button", FALSE
);
17866 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON1
), MAKELPARAM(x
, y
));
17867 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17868 ok_sequence(NCXBUTTONUPSeq1
, "WM_NCXBUTTONUP with XBUTTON1", FALSE
);
17870 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, XBUTTON2
), MAKELPARAM(x
, y
));
17871 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17872 ok_sequence(NCXBUTTONUPSeq2
, "WM_NCXBUTTONUP with XBUTTON2", FALSE
);
17874 res
= DefWindowProcA(hwnd
, WM_NCXBUTTONUP
, MAKEWPARAM(0, 3), MAKELPARAM(x
, y
));
17875 ok(!res
, "WM_NCXBUTTONUP returned %Id\n", res
);
17876 ok_sequence(WmEmptySeq
, "WM_NCXBUTTONUP with invalid button", FALSE
);
17878 /* Test WM_MOUSEACTIVATE */
17879 #define TEST_MOUSEACTIVATE(A,B,C) \
17880 res = DefWindowProcA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0)); \
17881 ok(res == B, "WM_MOUSEACTIVATE for %s returned %Id\n", #A, res); \
17882 res = DefWindowProcA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,WM_LBUTTONDOWN)); \
17883 ok(res == C, "WM_MOUSEACTIVATE for %s returned %Id\n", #A, res);
17885 TEST_MOUSEACTIVATE(HTERROR
, MA_ACTIVATE
, MA_ACTIVATE
);
17886 TEST_MOUSEACTIVATE(HTTRANSPARENT
, MA_ACTIVATE
, MA_ACTIVATE
);
17887 TEST_MOUSEACTIVATE(HTNOWHERE
, MA_ACTIVATE
, MA_ACTIVATE
);
17888 TEST_MOUSEACTIVATE(HTCLIENT
, MA_ACTIVATE
, MA_ACTIVATE
);
17889 TEST_MOUSEACTIVATE(HTCAPTION
, MA_ACTIVATE
, MA_NOACTIVATE
);
17890 TEST_MOUSEACTIVATE(HTSYSMENU
, MA_ACTIVATE
, MA_ACTIVATE
);
17891 TEST_MOUSEACTIVATE(HTSIZE
, MA_ACTIVATE
, MA_ACTIVATE
);
17892 TEST_MOUSEACTIVATE(HTMENU
, MA_ACTIVATE
, MA_ACTIVATE
);
17893 TEST_MOUSEACTIVATE(HTHSCROLL
, MA_ACTIVATE
, MA_ACTIVATE
);
17894 TEST_MOUSEACTIVATE(HTVSCROLL
, MA_ACTIVATE
, MA_ACTIVATE
);
17895 TEST_MOUSEACTIVATE(HTMINBUTTON
, MA_ACTIVATE
, MA_ACTIVATE
);
17896 TEST_MOUSEACTIVATE(HTMAXBUTTON
, MA_ACTIVATE
, MA_ACTIVATE
);
17897 TEST_MOUSEACTIVATE(HTLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
17898 TEST_MOUSEACTIVATE(HTRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
17899 TEST_MOUSEACTIVATE(HTTOP
, MA_ACTIVATE
, MA_ACTIVATE
);
17900 TEST_MOUSEACTIVATE(HTTOPLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
17901 TEST_MOUSEACTIVATE(HTTOPRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
17902 TEST_MOUSEACTIVATE(HTBOTTOM
, MA_ACTIVATE
, MA_ACTIVATE
);
17903 TEST_MOUSEACTIVATE(HTBOTTOMLEFT
, MA_ACTIVATE
, MA_ACTIVATE
);
17904 TEST_MOUSEACTIVATE(HTBOTTOMRIGHT
, MA_ACTIVATE
, MA_ACTIVATE
);
17905 TEST_MOUSEACTIVATE(HTBORDER
, MA_ACTIVATE
, MA_ACTIVATE
);
17906 TEST_MOUSEACTIVATE(HTOBJECT
, MA_ACTIVATE
, MA_ACTIVATE
);
17907 TEST_MOUSEACTIVATE(HTCLOSE
, MA_ACTIVATE
, MA_ACTIVATE
);
17908 TEST_MOUSEACTIVATE(HTHELP
, MA_ACTIVATE
, MA_ACTIVATE
);
17910 SetEvent( data
.wndproc_finished
);
17911 WaitForSingleObject( thread
, 1000 );
17912 CloseHandle( data
.wndproc_finished
);
17913 CloseHandle( thread
);
17915 SetCursorPos(pos
.x
, pos
.y
);
17917 DefWindowProcA( hwnd
, WM_ENDSESSION
, 1, 0);
17918 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) {
17919 if( msg
.message
== WM_QUIT
) gotwmquit
= TRUE
;
17920 DispatchMessageA( &msg
);
17922 ok(!gotwmquit
, "Unexpected WM_QUIT message!\n");
17923 DestroyWindow( hwnd
);
17926 static void test_desktop_winproc(void)
17928 HINSTANCE instance
= GetModuleHandleA(NULL
);
17929 RECT rect
, default_rect
;
17930 WNDPROC desktop_proc
;
17937 ret
= GetClassInfoA(instance
, (const CHAR
*)MAKEINTATOM(32769), &cls
);
17938 ok(ret
, "Failed to get desktop class.\n");
17939 desktop_proc
= cls
.lpfnWndProc
;
17941 memset(&cls
, 0, sizeof(cls
));
17942 cls
.lpfnWndProc
= desktop_proc
;
17943 cls
.hInstance
= instance
;
17944 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
17945 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
17946 cls
.lpszClassName
= "TestDesktopClass";
17947 register_class(&cls
);
17949 hwnd
= CreateWindowExA(0, cls
.lpszClassName
, "test_desktop_wndproc",
17950 WS_VISIBLE
| WS_CAPTION
| WS_OVERLAPPEDWINDOW
, 0, 0, 500, 100, 0, 0, 0, NULL
);
17951 if (!hwnd
) /* win2003 */
17953 skip("Failed to create window with desktop window procedure.\n");
17954 goto out_unregister
;
17957 memset(&cls
, 0, sizeof(cls
));
17958 ret
= GetClassInfoA(instance
, "TestDesktopClass", &cls
);
17959 ok(ret
, "Failed to get class info.\n");
17960 ok(cls
.lpfnWndProc
== desktop_proc
, "Got %p, expected %p.\n", cls
.lpfnWndProc
, desktop_proc
);
17962 GetWindowTextA(hwnd
, buffer
, ARRAY_SIZE(buffer
));
17963 todo_wine
ok(!strcmp(buffer
, "test_desktop_wndproc"), "Got unexpected window text: %s.\n", buffer
);
17965 res
= CallWindowProcA(desktop_proc
, hwnd
, WM_SETTEXT
, 0, (LPARAM
)"test");
17966 ok(res
== TRUE
, "Failed to set text, %Id.\n", res
);
17967 GetWindowTextA(hwnd
, buffer
, ARRAY_SIZE(buffer
));
17968 ok(!strcmp(buffer
, "test"), "Got unexpected window text: %s.\n", buffer
);
17970 SetRect(&default_rect
, 0, 0, 100, 100);
17971 res
= DefWindowProcW(hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&default_rect
);
17972 ok(!res
, "Got unexpected result %Id.\n", res
);
17974 SetRect(&rect
, 0, 0, 100, 100);
17975 res
= CallWindowProcA(desktop_proc
, hwnd
, WM_NCCALCSIZE
, FALSE
, (LPARAM
)&rect
);
17976 ok(!res
, "Got unexpected result %Id.\n", res
);
17977 todo_wine
ok(EqualRect(&rect
, &default_rect
), "rect Got %s, expected %s.\n",
17978 wine_dbgstr_rect(&rect
), wine_dbgstr_rect(&default_rect
));
17980 DestroyWindow(hwnd
);
17983 UnregisterClassA("TestDesktopClass", instance
);
17986 #define open_clipboard(hwnd) open_clipboard_(__LINE__, hwnd)
17987 static BOOL
open_clipboard_(int line
, HWND hwnd
)
17989 DWORD start
= GetTickCount();
17992 BOOL ret
= OpenClipboard(hwnd
);
17993 if (ret
|| GetLastError() != ERROR_ACCESS_DENIED
)
17995 if (GetTickCount() - start
> 100)
17997 char classname
[256];
17998 DWORD le
= GetLastError();
17999 HWND clipwnd
= GetOpenClipboardWindow();
18000 /* Provide a hint as to the source of interference:
18001 * - The class name would typically be CLIPBRDWNDCLASS if the
18002 * clipboard was opened by a Windows application using the
18004 * - And it would be __wine_clipboard_manager if it was opened in
18005 * response to a native application.
18007 GetClassNameA(clipwnd
, classname
, ARRAY_SIZE(classname
));
18008 trace_(__FILE__
, line
)("%p (%s) opened the clipboard\n", clipwnd
, classname
);
18016 #define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
18017 static void clear_clipboard_(int line
, HWND hWnd
)
18020 succ
= open_clipboard_(line
, hWnd
);
18021 ok_(__FILE__
, line
)(succ
, "OpenClipboard failed, err=%lu\n", GetLastError());
18022 succ
= EmptyClipboard();
18023 ok_(__FILE__
, line
)(succ
, "EmptyClipboard failed, err=%lu\n", GetLastError());
18024 succ
= CloseClipboard();
18025 ok_(__FILE__
, line
)(succ
, "CloseClipboard failed, err=%lu\n", GetLastError());
18028 #define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
18029 static void expect_HWND_(int line
, HWND expected
, HWND got
)
18031 ok_(__FILE__
, line
)(got
==expected
, "Expected %p, got %p\n", expected
, got
);
18034 static WNDPROC pOldViewerProc
;
18036 static LRESULT CALLBACK
recursive_viewer_proc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
18038 static BOOL recursion_guard
;
18040 if (message
== WM_DRAWCLIPBOARD
&& !recursion_guard
)
18042 recursion_guard
= TRUE
;
18043 clear_clipboard(hWnd
);
18044 recursion_guard
= FALSE
;
18046 return CallWindowProcA(pOldViewerProc
, hWnd
, message
, wParam
, lParam
);
18049 static void test_clipboard_viewers(void)
18051 static struct message wm_change_cb_chain
[] =
18053 { WM_CHANGECBCHAIN
, sent
|wparam
|lparam
, 0, 0 },
18056 static const struct message wm_clipboard_destroyed
[] =
18058 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
18061 static struct message wm_clipboard_changed
[] =
18063 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
18066 static struct message wm_clipboard_changed_and_owned
[] =
18068 { WM_DESTROYCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
18069 { WM_DRAWCLIPBOARD
, sent
|wparam
|lparam
, 0, 0 },
18073 HINSTANCE hInst
= GetModuleHandleA(NULL
);
18074 HWND hWnd1
, hWnd2
, hWnd3
;
18078 hWnd1
= CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
18079 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
18080 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
18081 GetDesktopWindow(), NULL
, hInst
, NULL
);
18082 ok(!!hWnd1
, "Failed to create window, error %lu.\n", GetLastError());
18083 hWnd2
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
18084 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
18085 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
18086 GetDesktopWindow(), NULL
, hInst
, NULL
);
18087 ok(!!hWnd2
, "Failed to create window, error %lu.\n", GetLastError());
18088 hWnd3
= CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
18089 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
18090 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
18091 GetDesktopWindow(), NULL
, hInst
, NULL
);
18092 ok(!!hWnd3
, "Failed to create window, error %lu.\n", GetLastError());
18093 if (winetest_debug
> 1) trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1
, hWnd2
, hWnd3
);
18095 CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */
18098 /* Test getting the clipboard viewer and setting the viewer to NULL. */
18099 hOrigViewer
= GetClipboardViewer();
18100 hRet
= SetClipboardViewer(NULL
);
18101 ok_sequence(WmEmptySeq
, "set viewer to NULL", FALSE
);
18102 expect_HWND(hOrigViewer
, hRet
);
18103 expect_HWND(NULL
, GetClipboardViewer());
18105 /* Test registering hWnd1 as a viewer. */
18106 hRet
= SetClipboardViewer(hWnd1
);
18107 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
18108 ok_sequence(wm_clipboard_changed
, "set viewer NULL->1", FALSE
);
18109 expect_HWND(NULL
, hRet
);
18110 expect_HWND(hWnd1
, GetClipboardViewer());
18112 /* Test that changing the clipboard actually refreshes the registered viewer. */
18113 clear_clipboard(hWnd1
);
18114 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
18115 ok_sequence(wm_clipboard_changed
, "clear clipbd (viewer=owner=1)", FALSE
);
18117 /* Again, but with different owner. */
18118 clear_clipboard(hWnd2
);
18119 wm_clipboard_changed_and_owned
[1].wParam
= (WPARAM
) GetClipboardOwner();
18120 ok_sequence(wm_clipboard_changed_and_owned
, "clear clipbd (viewer=1, owner=2)", FALSE
);
18122 /* Test re-registering same window. */
18123 hRet
= SetClipboardViewer(hWnd1
);
18124 wm_clipboard_changed
[0].wParam
= (WPARAM
) GetClipboardOwner();
18125 ok_sequence(wm_clipboard_changed
, "set viewer 1->1", FALSE
);
18126 expect_HWND(hWnd1
, hRet
);
18127 expect_HWND(hWnd1
, GetClipboardViewer());
18129 /* Test ChangeClipboardChain. */
18130 ChangeClipboardChain(hWnd2
, hWnd3
);
18131 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
18132 wm_change_cb_chain
[0].lParam
= (LPARAM
) hWnd3
;
18133 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=3)", FALSE
);
18134 expect_HWND(hWnd1
, GetClipboardViewer());
18136 ChangeClipboardChain(hWnd2
, NULL
);
18137 wm_change_cb_chain
[0].wParam
= (WPARAM
) hWnd2
;
18138 wm_change_cb_chain
[0].lParam
= 0;
18139 ok_sequence(wm_change_cb_chain
, "change chain (viewer=1, remove=2, next=NULL)", FALSE
);
18140 expect_HWND(hWnd1
, GetClipboardViewer());
18142 ChangeClipboardChain(NULL
, hWnd2
);
18143 ok_sequence(WmEmptySeq
, "change chain (viewer=1, remove=NULL, next=2)", FALSE
);
18144 expect_HWND(hWnd1
, GetClipboardViewer());
18146 /* Actually change clipboard viewer with ChangeClipboardChain. */
18147 ChangeClipboardChain(hWnd1
, hWnd2
);
18148 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=2)", FALSE
);
18149 expect_HWND(hWnd2
, GetClipboardViewer());
18151 /* Test that no refresh messages are sent when viewer has unregistered. */
18152 clear_clipboard(hWnd2
);
18153 ok_sequence(WmEmptySeq
, "clear clipd (viewer=2, owner=1)", FALSE
);
18155 /* Register hWnd1 again. */
18156 ChangeClipboardChain(hWnd2
, hWnd1
);
18157 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=2, next=1)", FALSE
);
18158 expect_HWND(hWnd1
, GetClipboardViewer());
18160 /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
18161 * changes the clipboard. When this happens, the system shouldn't send
18162 * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
18164 pOldViewerProc
= (WNDPROC
) SetWindowLongPtrA(hWnd1
, GWLP_WNDPROC
, (LONG_PTR
) recursive_viewer_proc
);
18165 clear_clipboard(hWnd2
);
18166 /* The clipboard owner is changed in recursive_viewer_proc: */
18167 wm_clipboard_changed
[0].wParam
= (WPARAM
) hWnd2
;
18168 ok_sequence(wm_clipboard_changed
, "recursive clear clipbd (viewer=1, owner=2)", TRUE
);
18170 /* Test unregistering. */
18171 ChangeClipboardChain(hWnd1
, NULL
);
18172 ok_sequence(WmEmptySeq
, "change chain (viewer=remove=1, next=NULL)", FALSE
);
18173 expect_HWND(NULL
, GetClipboardViewer());
18175 clear_clipboard(hWnd1
);
18176 ok_sequence(wm_clipboard_destroyed
, "clear clipbd (no viewer, owner=1)", FALSE
);
18178 DestroyWindow(hWnd1
);
18179 DestroyWindow(hWnd2
);
18180 DestroyWindow(hWnd3
);
18181 SetClipboardViewer(hOrigViewer
);
18184 static void test_PostMessage(void)
18186 static const struct
18192 { HWND_TOP
/* 0 */, TRUE
},
18193 { HWND_BROADCAST
, TRUE
},
18194 { HWND_BOTTOM
, TRUE
},
18195 { HWND_TOPMOST
, TRUE
},
18196 { HWND_NOTOPMOST
, FALSE
},
18197 { HWND_MESSAGE
, FALSE
},
18198 { (HWND
)0xdeadbeef, FALSE
}
18204 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
18206 SetLastError(0xdeadbeef);
18207 hwnd
= CreateWindowExW(0, staticW
, NULL
, WS_POPUP
, 0,0,0,0,0,0,0, NULL
);
18208 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
18210 win_skip("Skipping some PostMessage tests on Win9x/WinMe\n");
18213 ok(!!hwnd
, "Failed to create window, error %lu.\n", GetLastError());
18217 PostMessageA(hwnd
, WM_USER
+1, 0x1234, 0x5678);
18218 PostMessageA(0, WM_USER
+2, 0x5678, 0x1234);
18220 for (i
= 0; i
< ARRAY_SIZE(data
); i
++)
18222 memset(&msg
, 0xab, sizeof(msg
));
18223 ret
= PeekMessageA(&msg
, data
[i
].hwnd
, 0, 0, PM_NOREMOVE
);
18224 ok(ret
== data
[i
].ret
, "%d: hwnd %p expected %d, got %d\n", i
, data
[i
].hwnd
, data
[i
].ret
, ret
);
18228 ok(ret
&& msg
.hwnd
== 0 && msg
.message
== WM_USER
+2 &&
18229 msg
.wParam
== 0x5678 && msg
.lParam
== 0x1234,
18230 "%d: got ret %d hwnd %p msg %04x wParam %08Ix lParam %08Ix instead of TRUE/0/WM_USER+2/0x5678/0x1234\n",
18231 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
);
18233 ok(ret
&& msg
.hwnd
== hwnd
&& msg
.message
== WM_USER
+1 &&
18234 msg
.wParam
== 0x1234 && msg
.lParam
== 0x5678,
18235 "%d: got ret %d hwnd %p msg %04x wParam %08Ix lParam %08Ix instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n",
18236 i
, ret
, msg
.hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
, msg
.hwnd
);
18240 DestroyWindow(hwnd
);
18244 static WPARAM g_broadcast_wparam
;
18245 static UINT g_broadcast_msg
;
18246 static LRESULT WINAPI
broadcast_test_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
18248 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
18250 if (message
== g_broadcast_msg
)
18251 g_broadcast_wparam
= wParam
;
18253 return CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
18255 static WNDPROC
*g_oldproc_sub
;
18256 static WPARAM
*g_broadcast_sub_wparam
;
18257 static LRESULT WINAPI
broadcast_test_sub_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
18259 int sub_index
= GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
18261 if (message
== g_broadcast_msg
)
18262 g_broadcast_sub_wparam
[sub_index
] = wParam
;
18264 return CallWindowProcA(g_oldproc_sub
[sub_index
], hwnd
, message
, wParam
, lParam
);
18267 static void test_broadcast(void)
18269 static const UINT messages
[] =
18275 0xc000, /* lowest possible atom returned by RegisterWindowMessage */
18278 static const struct
18284 {WS_OVERLAPPED
, TRUE
},
18285 {WS_OVERLAPPED
|WS_DLGFRAME
, TRUE
},
18286 {WS_OVERLAPPED
|WS_BORDER
, TRUE
},
18287 {WS_OVERLAPPED
|WS_CAPTION
, TRUE
},
18289 {WS_CHILD
|WS_DLGFRAME
, FALSE
},
18290 {WS_CHILD
|WS_BORDER
, FALSE
},
18291 {WS_CHILD
|WS_CAPTION
, FALSE
},
18292 {WS_CHILD
|WS_POPUP
, TRUE
},
18294 {WS_POPUP
|WS_DLGFRAME
, TRUE
},
18295 {WS_POPUP
|WS_BORDER
, TRUE
},
18296 {WS_POPUP
|WS_CAPTION
, TRUE
},
18303 hwnd_sub
= malloc(ARRAY_SIZE(bcast_expect
) * sizeof(*hwnd_sub
));
18304 g_oldproc_sub
= malloc(ARRAY_SIZE(bcast_expect
) * sizeof(*g_oldproc_sub
));
18305 g_broadcast_sub_wparam
= malloc(ARRAY_SIZE(bcast_expect
) * sizeof(*g_broadcast_sub_wparam
));
18307 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
, 0, 0, 0, 0, 0, 0, 0, NULL
);
18308 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
18310 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_proc
);
18311 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
18313 for (i
= 0; i
< ARRAY_SIZE(messages
); i
++)
18316 BOOL msg_expected
= (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000);
18320 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
18323 /* post, broadcast */
18324 ret
= PostMessageA(HWND_BROADCAST
, messages
[i
], 0, 0);
18325 ok(ret
, "%d: got %d, error %ld\n", i
, ret
, GetLastError());
18327 memset(&msg
, 0xab, sizeof(msg
));
18328 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
18329 ok(ret
== msg_expected
, "%d: message %04x, got %d, error %ld\n", i
, messages
[i
], ret
, GetLastError());
18331 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
18333 /* post, topmost */
18334 ret
= PostMessageA(HWND_TOPMOST
, messages
[i
], 0, 0);
18335 ok(ret
, "%d: got %d, error %ld\n", i
, ret
, GetLastError());
18337 memset(&msg
, 0xab, sizeof(msg
));
18338 ret
= PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
);
18339 ok(ret
== msg_expected
, "%d: message %04x, got %d, error %ld\n", i
, messages
[i
], ret
, GetLastError());
18341 ok(msg
.hwnd
== hwnd
, "%d: got %p\n", i
, msg
.hwnd
);
18344 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18346 hwnd_sub
[j
] = CreateWindowA("static", NULL
, bcast_expect
[j
].style
, 0, 0, 0, 0, hwnd
, 0, 0, NULL
);
18347 ok(hwnd_sub
[j
] != NULL
, "got %p\n", hwnd_sub
[j
]);
18348 /* CreateWindow adds extra style flags, so call SetWindowLong to clear some of those. */
18349 SetWindowLongA(hwnd_sub
[j
], GWL_STYLE
, bcast_expect
[j
].style
);
18351 g_oldproc_sub
[j
] = (WNDPROC
)SetWindowLongPtrA(hwnd_sub
[j
], GWLP_WNDPROC
, (LONG_PTR
)broadcast_test_sub_proc
);
18352 SetWindowLongPtrA(hwnd_sub
[j
], GWLP_USERDATA
, (LONG_PTR
)j
);
18355 for (i
= 0; i
< ARRAY_SIZE(messages
); i
++)
18358 BOOL msg_expected
= (messages
[i
] < WM_USER
|| messages
[i
] >= 0xc000);
18360 /* send, broadcast */
18361 g_broadcast_wparam
= 0xdead;
18362 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18363 g_broadcast_sub_wparam
[j
] = 0xdead;
18364 g_broadcast_msg
= messages
[i
];
18365 ret
= SendMessageTimeoutA(HWND_BROADCAST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
18366 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
18367 win_skip("broadcasting test %d, timeout\n", i
);
18370 WPARAM wparam_expected
= msg_expected
? 0xbaadbeef : 0xdead;
18371 ok(g_broadcast_wparam
== wparam_expected
, "%d: message %04x, got %#Ix, error %ld\n",
18372 i
, messages
[i
], g_broadcast_wparam
, GetLastError());
18373 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18375 wparam_expected
= (msg_expected
&& bcast_expect
[j
].receive
) ? 0xbaadbeef : 0xdead;
18376 ok(g_broadcast_sub_wparam
[j
] == wparam_expected
,
18377 "%d,%d: message %04x, got %#Ix, error %ld\n", i
, j
, messages
[i
],
18378 g_broadcast_sub_wparam
[j
], GetLastError());
18382 /* send, topmost */
18383 g_broadcast_wparam
= 0xdead;
18384 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18385 g_broadcast_sub_wparam
[j
] = 0xdead;
18386 ret
= SendMessageTimeoutA(HWND_TOPMOST
, messages
[i
], 0xbaadbeef, 0, SMTO_NORMAL
, 2000, NULL
);
18387 if (!ret
&& GetLastError() == ERROR_TIMEOUT
)
18388 win_skip("broadcasting test %d, timeout\n", i
);
18391 WPARAM wparam_expected
= msg_expected
? 0xbaadbeef : 0xdead;
18392 ok(g_broadcast_wparam
== wparam_expected
, "%d: message %04x, got %#Ix, error %ld\n",
18393 i
, messages
[i
], g_broadcast_wparam
, GetLastError());
18394 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18396 wparam_expected
= (msg_expected
&& bcast_expect
[j
].receive
) ? 0xbaadbeef : 0xdead;
18397 ok(g_broadcast_sub_wparam
[j
] == wparam_expected
,
18398 "%d,%d: message %04x, got %#Ix, error %ld\n", i
, j
, messages
[i
],
18399 g_broadcast_sub_wparam
[j
], GetLastError());
18404 for (j
= 0; j
< ARRAY_SIZE(bcast_expect
); j
++)
18405 DestroyWindow(hwnd_sub
[j
]);
18407 free(g_broadcast_sub_wparam
);
18408 free(g_oldproc_sub
);
18411 DestroyWindow(hwnd
);
18414 static const struct
18418 } wait_idle_expect
[] =
18420 /* 0 */ { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18421 { WAIT_TIMEOUT
, 0, FALSE
},
18422 { WAIT_TIMEOUT
, 0, FALSE
},
18423 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18424 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18425 /* 5 */ { WAIT_TIMEOUT
, 0, FALSE
},
18426 { WAIT_TIMEOUT
, 0, FALSE
},
18427 { WAIT_TIMEOUT
, WAIT_TIMEOUT
, FALSE
},
18430 /* 10 */ { 0, 0, FALSE
},
18432 { 0, WAIT_TIMEOUT
, FALSE
},
18435 /* 15 */ { 0, 0, FALSE
},
18436 { WAIT_TIMEOUT
, 0, FALSE
},
18437 { WAIT_TIMEOUT
, 0, FALSE
},
18438 { WAIT_TIMEOUT
, 0, FALSE
},
18439 { WAIT_TIMEOUT
, 0, FALSE
},
18440 /* 20 */ { WAIT_TIMEOUT
, 0, FALSE
},
18443 static DWORD CALLBACK
do_wait_idle_child_thread( void *arg
)
18447 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18449 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
18453 static void do_wait_idle_child( int arg
)
18460 HANDLE start_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_start" );
18461 HANDLE end_event
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, "test_WaitForInputIdle_end" );
18463 memset( &cls
, 0, sizeof(cls
) );
18464 cls
.lpfnWndProc
= DefWindowProcA
;
18465 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
18466 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
18467 cls
.lpszClassName
= "TestClass";
18468 register_class(&cls
);
18470 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
); /* create the msg queue */
18472 ok( start_event
!= 0, "failed to create start event, error %lu\n", GetLastError() );
18473 ok( end_event
!= 0, "failed to create end event, error %lu\n", GetLastError() );
18478 SetEvent( start_event
);
18481 SetEvent( start_event
);
18483 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
18486 SetEvent( start_event
);
18488 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18489 PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND
, 0x1234, 0xabcd );
18490 PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
);
18493 SetEvent( start_event
);
18495 SendMessageA( HWND_BROADCAST
, WM_WININICHANGE
, 0, 0 );
18498 SetEvent( start_event
);
18500 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18501 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
18504 SetEvent( start_event
);
18506 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18507 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
18510 SetEvent( start_event
);
18512 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18513 while (PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
))
18515 GetMessageA( &msg
, 0, 0, 0 );
18516 DispatchMessageA( &msg
);
18520 SetEvent( start_event
);
18522 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18523 SetTimer( hwnd
, 3, 1, NULL
);
18525 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
|PM_NOYIELD
)) DispatchMessageA( &msg
);
18528 SetEvent( start_event
);
18530 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18531 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
18534 SetEvent( start_event
);
18536 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18537 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
18538 for (;;) GetMessageA( &msg
, 0, 0, 0 );
18541 SetEvent( start_event
);
18543 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
|WS_VISIBLE
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18544 SetTimer( hwnd
, 3, 1, NULL
);
18546 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
18549 SetEvent( start_event
);
18551 return; /* exiting the process makes WaitForInputIdle return success too */
18553 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18555 MsgWaitForMultipleObjects( 0, NULL
, FALSE
, 100, QS_ALLINPUT
);
18556 SetEvent( start_event
);
18559 SetEvent( start_event
);
18560 PeekMessageA( &msg
, 0, 0, 0, PM_NOREMOVE
);
18562 thread
= CreateThread( NULL
, 0, do_wait_idle_child_thread
, NULL
, 0, &id
);
18563 WaitForSingleObject( thread
, 10000 );
18564 CloseHandle( thread
);
18567 SetEvent( start_event
);
18569 PeekMessageA( &msg
, HWND_TOPMOST
, 0, 0, PM_NOREMOVE
);
18572 SetEvent( start_event
);
18574 PeekMessageA( &msg
, HWND_BROADCAST
, 0, 0, PM_NOREMOVE
);
18577 SetEvent( start_event
);
18579 PeekMessageA( &msg
, HWND_BOTTOM
, 0, 0, PM_NOREMOVE
);
18582 SetEvent( start_event
);
18584 PeekMessageA( &msg
, (HWND
)0xdeadbeef, 0, 0, PM_NOREMOVE
);
18587 SetEvent( start_event
);
18589 PeekMessageA( &msg
, HWND_NOTOPMOST
, 0, 0, PM_NOREMOVE
);
18592 SetEvent( start_event
);
18594 PeekMessageA( &msg
, HWND_MESSAGE
, 0, 0, PM_NOREMOVE
);
18597 SetEvent( start_event
);
18599 PeekMessageA( &msg
, GetDesktopWindow(), 0, 0, PM_NOREMOVE
);
18602 WaitForSingleObject( end_event
, 2000 );
18603 CloseHandle( start_event
);
18604 CloseHandle( end_event
);
18605 if (hwnd
) DestroyWindow( hwnd
);
18608 static LRESULT CALLBACK
wait_idle_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
18610 if (msg
== WM_WININICHANGE
) Sleep( 200 ); /* make sure the child waits */
18611 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
18614 static DWORD CALLBACK
wait_idle_thread( void *arg
)
18620 memset( &cls
, 0, sizeof(cls
) );
18621 cls
.lpfnWndProc
= wait_idle_proc
;
18622 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
18623 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
18624 cls
.lpszClassName
= "TestClass";
18625 register_class(&cls
);
18627 hwnd
= CreateWindowExA(0, "TestClass", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
18628 while (GetMessageA( &msg
, 0, 0, 0 )) DispatchMessageA( &msg
);
18629 DestroyWindow(hwnd
);
18633 static void test_WaitForInputIdle( char *argv0
)
18635 char path
[MAX_PATH
];
18636 PROCESS_INFORMATION pi
;
18637 STARTUPINFOA startup
;
18639 HANDLE start_event
, end_event
, thread
;
18642 const IMAGE_DOS_HEADER
*dos
= (const IMAGE_DOS_HEADER
*)GetModuleHandleA(0);
18643 const IMAGE_NT_HEADERS
*nt
= (const IMAGE_NT_HEADERS
*)((const char *)dos
+ dos
->e_lfanew
);
18644 BOOL console_app
= (nt
->OptionalHeader
.Subsystem
!= IMAGE_SUBSYSTEM_WINDOWS_GUI
);
18646 if (console_app
) /* build the test with -mwindows for better coverage */
18647 trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
18649 start_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_start");
18650 end_event
= CreateEventA(NULL
, 0, 0, "test_WaitForInputIdle_end");
18651 ok(start_event
!= 0, "failed to create start event, error %lu\n", GetLastError());
18652 ok(end_event
!= 0, "failed to create end event, error %lu\n", GetLastError());
18654 memset( &startup
, 0, sizeof(startup
) );
18655 startup
.cb
= sizeof(startup
);
18656 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
18657 startup
.wShowWindow
= SW_SHOWNORMAL
;
18659 thread
= CreateThread( NULL
, 0, wait_idle_thread
, NULL
, 0, &id
);
18661 for (i
= 0; i
< ARRAY_SIZE(wait_idle_expect
); i
++)
18663 ResetEvent( start_event
);
18664 ResetEvent( end_event
);
18665 sprintf( path
, "%s msg %u", argv0
, i
);
18666 ret
= CreateProcessA( NULL
, path
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup
, &pi
);
18667 ok( ret
, "CreateProcess '%s' failed err %lu.\n", path
, GetLastError() );
18670 ret
= WaitForSingleObject( start_event
, 5000 );
18671 ok( ret
== WAIT_OBJECT_0
, "%u: WaitForSingleObject failed\n", i
);
18672 if (ret
== WAIT_OBJECT_0
)
18674 ret
= WaitForInputIdle( pi
.hProcess
, 1000 );
18675 if (ret
== WAIT_FAILED
)
18677 ret
== wait_idle_expect
[i
].exp
||
18678 broken(ret
== wait_idle_expect
[i
].broken
),
18679 "%u: WaitForInputIdle error %08x expected %08lx\n",
18680 i
, ret
, wait_idle_expect
[i
].exp
);
18681 else todo_wine_if (wait_idle_expect
[i
].todo
)
18682 ok( ret
== wait_idle_expect
[i
].exp
|| broken(ret
== wait_idle_expect
[i
].broken
),
18683 "%u: WaitForInputIdle error %08x expected %08lx\n",
18684 i
, ret
, wait_idle_expect
[i
].exp
);
18685 SetEvent( end_event
);
18686 WaitForSingleObject( pi
.hProcess
, 1000 ); /* give it a chance to exit on its own */
18688 TerminateProcess( pi
.hProcess
, 0 ); /* just in case */
18689 wait_child_process( pi
.hProcess
);
18690 ret
= WaitForInputIdle( pi
.hProcess
, 100 );
18691 ok( ret
== WAIT_FAILED
, "%u: WaitForInputIdle after exit error %08x\n", i
, ret
);
18692 CloseHandle( pi
.hProcess
);
18693 CloseHandle( pi
.hThread
);
18696 CloseHandle( end_event
);
18697 CloseHandle( start_event
);
18698 PostThreadMessageA( id
, WM_QUIT
, 0, 0 );
18699 WaitForSingleObject( thread
, 10000 );
18700 CloseHandle( thread
);
18703 static const struct message WmSetParentSeq_1
[] = {
18704 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
18705 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
18706 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
18707 { WM_CHILDACTIVATE
, sent
},
18708 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOCLIENTSIZE
},
18709 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
18710 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
, 0, 0 },
18711 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
18715 static const struct message WmSetParentSeq_2
[] = {
18716 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
18717 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
18718 { EVENT_OBJECT_HIDE
, winevent_hook
|wparam
|lparam
, 0, 0 },
18719 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
18720 { HCBT_SETFOCUS
, hook
|optional
},
18721 { WM_NCACTIVATE
, sent
|wparam
|optional
, 0 },
18722 { WM_ACTIVATE
, sent
|wparam
|optional
, 0 },
18723 { WM_ACTIVATEAPP
, sent
|wparam
|optional
, 0 },
18724 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
18725 { WM_KILLFOCUS
, sent
|wparam
, 0 },
18726 { EVENT_OBJECT_PARENTCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
18727 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
},
18728 { HCBT_ACTIVATE
, hook
|optional
},
18729 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
18730 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOSIZE
|SWP_NOMOVE
},
18731 { WM_NCACTIVATE
, sent
|wparam
|optional
, 1 },
18732 { WM_ACTIVATE
, sent
|wparam
|optional
, 1 },
18733 { HCBT_SETFOCUS
, hook
|optional
},
18734 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
|optional
, OBJID_CLIENT
, 0 },
18735 { WM_SETFOCUS
, sent
|optional
|defwinproc
},
18736 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOREDRAW
|SWP_NOSIZE
|SWP_NOCLIENTSIZE
},
18737 { WM_MOVE
, sent
|defwinproc
|wparam
, 0 },
18738 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
18739 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
18740 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
},
18741 { EVENT_OBJECT_SHOW
, winevent_hook
|wparam
|lparam
, 0, 0 },
18742 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_SHOWWINDOW
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
18747 static void test_SetParent(void)
18749 HWND parent1
, parent2
, child
, popup
;
18752 parent1
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
18753 100, 100, 200, 200, 0, 0, 0, NULL
);
18754 ok(parent1
!= 0, "Failed to create parent1 window\n");
18756 parent2
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
18757 400, 100, 200, 200, 0, 0, 0, NULL
);
18758 ok(parent2
!= 0, "Failed to create parent2 window\n");
18760 /* WS_CHILD window */
18761 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
| WS_VISIBLE
,
18762 10, 10, 150, 150, parent1
, 0, 0, NULL
);
18763 ok(child
!= 0, "Failed to create child window\n");
18765 GetWindowRect(parent1
, &rc
);
18766 if (winetest_debug
> 1) trace("parent1 %s\n", wine_dbgstr_rect(&rc
));
18767 GetWindowRect(child
, &rc_old
);
18768 MapWindowPoints(0, parent1
, (POINT
*)&rc_old
, 2);
18769 if (winetest_debug
> 1) trace("child %s\n", wine_dbgstr_rect(&rc_old
));
18773 SetParent(child
, parent2
);
18775 ok_sequence(WmSetParentSeq_1
, "SetParent() visible WS_CHILD", FALSE
);
18777 ok(GetWindowLongA(child
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
18778 ok(!IsWindowVisible(child
), "IsWindowVisible() should return FALSE\n");
18780 GetWindowRect(parent2
, &rc
);
18781 if (winetest_debug
> 1) trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
18782 GetWindowRect(child
, &rc
);
18783 MapWindowPoints(0, parent2
, (POINT
*)&rc
, 2);
18784 if (winetest_debug
> 1) trace("child %s\n", wine_dbgstr_rect(&rc
));
18786 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
18787 wine_dbgstr_rect(&rc
));
18789 /* WS_POPUP window */
18790 popup
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_POPUP
| WS_VISIBLE
,
18791 20, 20, 100, 100, 0, 0, 0, NULL
);
18792 ok(popup
!= 0, "Failed to create popup window\n");
18794 GetWindowRect(popup
, &rc_old
);
18795 if (winetest_debug
> 1) trace("popup %s\n", wine_dbgstr_rect(&rc_old
));
18799 SetParent(popup
, child
);
18801 ok_sequence(WmSetParentSeq_2
, "SetParent() visible WS_POPUP", TRUE
);
18803 ok(GetWindowLongA(popup
, GWL_STYLE
) & WS_VISIBLE
, "WS_VISIBLE should be set\n");
18804 ok(!IsWindowVisible(popup
), "IsWindowVisible() should return FALSE\n");
18806 GetWindowRect(child
, &rc
);
18807 if (winetest_debug
> 1) trace("parent2 %s\n", wine_dbgstr_rect(&rc
));
18808 GetWindowRect(popup
, &rc
);
18809 MapWindowPoints(0, child
, (POINT
*)&rc
, 2);
18810 if (winetest_debug
> 1) trace("popup %s\n", wine_dbgstr_rect(&rc
));
18812 ok(EqualRect(&rc_old
, &rc
), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old
),
18813 wine_dbgstr_rect(&rc
));
18815 DestroyWindow(popup
);
18816 DestroyWindow(child
);
18817 DestroyWindow(parent1
);
18818 DestroyWindow(parent2
);
18823 static const struct message WmKeyReleaseOnly
[] = {
18824 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x80000001 },
18825 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0x80000001 },
18828 static const struct message WmKeyPressNormal
[] = {
18829 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x1 },
18830 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x1 },
18833 static const struct message WmKeyPressRepeat
[] = {
18834 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0x40000001 },
18835 { WM_KEYDOWN
, sent
|wparam
|lparam
, 0x41, 0x40000001 },
18838 static const struct message WmKeyReleaseNormal
[] = {
18839 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, 0x41, 0xc0000001 },
18840 { WM_KEYUP
, sent
|wparam
|lparam
, 0x41, 0xc0000001 },
18844 static void test_keyflags(void)
18848 BYTE keyboard_state
[256];
18851 test_window
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
18852 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
),
18858 /* keyup without a keydown */
18859 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
18860 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18861 DispatchMessageA(&msg
);
18862 ok_sequence(WmKeyReleaseOnly
, "key release only", TRUE
);
18864 key_state
= GetAsyncKeyState(0x41);
18865 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18867 key_state
= GetKeyState(0x41);
18868 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18871 keybd_event(0x41, 0, 0, 0);
18872 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18873 DispatchMessageA(&msg
);
18874 ok_sequence(WmKeyPressNormal
, "key press only", FALSE
);
18876 key_state
= GetAsyncKeyState(0x41);
18877 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18879 key_state
= GetKeyState(0x41);
18880 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18882 /* keydown repeat */
18883 keybd_event(0x41, 0, 0, 0);
18884 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18885 DispatchMessageA(&msg
);
18886 ok_sequence(WmKeyPressRepeat
, "key press repeat", FALSE
);
18888 key_state
= GetAsyncKeyState(0x41);
18889 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18891 key_state
= GetKeyState(0x41);
18892 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18895 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
18896 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18897 DispatchMessageA(&msg
);
18898 ok_sequence(WmKeyReleaseNormal
, "key release repeat", FALSE
);
18900 key_state
= GetAsyncKeyState(0x41);
18901 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18903 key_state
= GetKeyState(0x41);
18904 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18906 /* set the key state in this thread */
18907 GetKeyboardState(keyboard_state
);
18908 keyboard_state
[0x41] = 0x80;
18909 SetKeyboardState(keyboard_state
);
18911 key_state
= GetAsyncKeyState(0x41);
18912 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18915 keybd_event(0x41, 0, 0, 0);
18916 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18917 DispatchMessageA(&msg
);
18918 ok_sequence(WmKeyPressRepeat
, "key press after setkeyboardstate", TRUE
);
18920 key_state
= GetAsyncKeyState(0x41);
18921 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18923 key_state
= GetKeyState(0x41);
18924 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18926 /* clear the key state in this thread */
18927 GetKeyboardState(keyboard_state
);
18928 keyboard_state
[0x41] = 0;
18929 SetKeyboardState(keyboard_state
);
18931 key_state
= GetAsyncKeyState(0x41);
18932 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
18935 keybd_event(0x41, 0, KEYEVENTF_KEYUP
, 0);
18936 while (PeekMessageA(&msg
, NULL
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
))
18937 DispatchMessageA(&msg
);
18938 ok_sequence(WmKeyReleaseOnly
, "key release after setkeyboardstate", TRUE
);
18940 key_state
= GetAsyncKeyState(0x41);
18941 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18943 key_state
= GetKeyState(0x41);
18944 ok((key_state
& 0x8000) == 0, "unexpected key state %x\n", key_state
);
18946 DestroyWindow(test_window
);
18950 static const struct message WmHotkeyPressLWIN
[] = {
18951 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
18952 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
18953 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
18956 static const struct message WmHotkeyPress
[] = {
18957 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
18958 { WM_HOTKEY
, sent
|wparam
, 5 },
18961 static const struct message WmHotkeyRelease
[] = {
18962 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
18963 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0x80000001 },
18964 { WM_KEYUP
, sent
|lparam
, 0, 0x80000001 },
18967 static const struct message WmHotkeyReleaseLWIN
[] = {
18968 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
18969 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
18970 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
18973 static const struct message WmHotkeyCombined
[] = {
18974 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
18975 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
18976 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
18977 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
18978 { WM_APP
, sent
, 0, 0 },
18979 { WM_HOTKEY
, sent
|wparam
, 5 },
18980 { WM_APP
+1, sent
, 0, 0 },
18981 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
18982 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
18983 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
18984 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
18985 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
18986 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
18989 static const struct message WmHotkeyPrevious
[] = {
18990 { WM_KEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
},
18991 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
18992 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
18993 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LWIN
, LLKHF_INJECTED
|LLKHF_UP
},
18994 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 1 },
18995 { WM_KEYDOWN
, sent
|wparam
|lparam
, VK_LWIN
, 1 },
18996 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 1 },
18997 { WM_KEYDOWN
, sent
|lparam
, 0, 1 },
18998 { HCBT_KEYSKIPPED
, hook
|optional
|lparam
, 0, 0xc0000001 },
18999 { WM_KEYUP
, sent
|lparam
, 0, 0xc0000001 },
19000 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_LWIN
, 0xc0000001 },
19001 { WM_KEYUP
, sent
|wparam
|lparam
, VK_LWIN
, 0xc0000001 },
19004 static const struct message WmHotkeyNew
[] = {
19005 { WM_KEYDOWN
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
},
19006 { WM_KEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
},
19007 { WM_HOTKEY
, sent
|wparam
, 5 },
19008 { HCBT_KEYSKIPPED
, hook
|optional
, 0, 0x80000001 },
19009 { WM_KEYUP
, sent
, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */
19012 static const struct message WmHotkeyPressALT
[] = {
19013 { WM_SYSKEYDOWN
, kbd_hook
|wparam
|lparam
, VK_LMENU
, LLKHF_INJECTED
|LLKHF_ALTDOWN
},
19014 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0x20000001 },
19015 { WM_SYSKEYDOWN
, sent
|wparam
|lparam
, VK_MENU
, 0x20000001 },
19018 static const struct message WmHotkeyPressWithALT
[] = {
19019 { WM_SYSKEYDOWN
, kbd_hook
, 0, LLKHF_INJECTED
|LLKHF_ALTDOWN
}, /* lparam not checked */
19020 { WM_HOTKEY
, sent
|wparam
, 6 },
19023 static const struct message WmHotkeyReleaseWithALT
[] = {
19024 { WM_SYSKEYUP
, kbd_hook
|lparam
, 0, LLKHF_INJECTED
|LLKHF_UP
|LLKHF_ALTDOWN
},
19025 { HCBT_KEYSKIPPED
, hook
|lparam
|optional
, 0, 0xa0000001 },
19026 { WM_SYSKEYUP
, sent
|lparam
, 0, 0xa0000001 },
19029 static const struct message WmHotkeyReleaseALT
[] = {
19030 { WM_KEYUP
, kbd_hook
|wparam
|lparam
, VK_LMENU
, LLKHF_INJECTED
|LLKHF_UP
},
19031 { HCBT_KEYSKIPPED
, hook
|wparam
|lparam
|optional
, VK_MENU
, 0xc0000001 },
19032 { WM_KEYUP
, sent
|wparam
|lparam
, VK_MENU
, 0xc0000001 },
19036 static int hotkey_letter
;
19038 static LRESULT CALLBACK
KeyboardHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
19040 struct recvd_message msg
;
19042 if (nCode
== HC_ACTION
)
19044 KBDLLHOOKSTRUCT
*kdbhookstruct
= (KBDLLHOOKSTRUCT
*)lParam
;
19047 msg
.message
= wParam
;
19048 msg
.flags
= kbd_hook
|wparam
|lparam
;
19049 msg
.wParam
= kdbhookstruct
->vkCode
;
19050 msg
.lParam
= kdbhookstruct
->flags
;
19051 msg
.descr
= "KeyboardHookProc";
19054 if (wParam
== WM_KEYUP
|| wParam
== WM_KEYDOWN
||
19055 wParam
== WM_SYSKEYUP
|| wParam
== WM_SYSKEYDOWN
)
19057 ok(kdbhookstruct
->vkCode
== VK_LWIN
||
19058 kdbhookstruct
->vkCode
== VK_LMENU
||
19059 kdbhookstruct
->vkCode
== hotkey_letter
,
19060 "unexpected keycode %lx\n", kdbhookstruct
->vkCode
);
19064 return CallNextHookEx(hKBD_hook
, nCode
, wParam
, lParam
);
19067 static void test_hotkey(void)
19069 HWND test_window
, taskbar_window
;
19072 DWORD queue_status
;
19075 SetLastError(0xdeadbeef);
19076 ret
= UnregisterHotKey(NULL
, 0);
19079 skip("hotkeys not supported\n");
19083 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19084 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19085 "unexpected error %ld\n", GetLastError());
19087 test_window
= CreateWindowExA(0, "HotkeyWindowClass", NULL
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
19088 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
),
19091 SetForegroundWindow(test_window
);
19095 SetLastError(0xdeadbeef);
19096 ret
= UnregisterHotKey(test_window
, 0);
19097 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19098 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19099 "unexpected error %ld\n", GetLastError());
19101 /* Search for a Windows Key + letter combination that hasn't been registered */
19102 for (hotkey_letter
= 'A'; hotkey_letter
<= 'Z'; hotkey_letter
++)
19104 SetLastError(0xdeadbeef);
19105 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
19113 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19114 "unexpected error %ld\n", GetLastError());
19118 if (hotkey_letter
> 'Z')
19120 ok(0, "Couldn't find any free Windows Key + letter combination\n");
19124 hKBD_hook
= SetWindowsHookExA(WH_KEYBOARD_LL
, KeyboardHookProc
, GetModuleHandleA(NULL
), 0);
19125 if (!hKBD_hook
) win_skip("WH_KEYBOARD_LL is not supported\n");
19127 /* Same key combination, different id */
19128 SetLastError(0xdeadbeef);
19129 ret
= RegisterHotKey(test_window
, 4, MOD_WIN
, hotkey_letter
);
19130 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19131 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19132 "unexpected error %ld\n", GetLastError());
19134 /* Same key combination, different window */
19135 SetLastError(0xdeadbeef);
19136 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
19137 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19138 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19139 "unexpected error %ld\n", GetLastError());
19141 /* Register the same hotkey twice */
19142 SetLastError(0xdeadbeef);
19143 ret
= RegisterHotKey(test_window
, 5, MOD_WIN
, hotkey_letter
);
19144 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19145 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19146 "unexpected error %ld\n", GetLastError());
19148 /* Window on another thread */
19149 taskbar_window
= FindWindowA("Shell_TrayWnd", NULL
);
19150 if (!taskbar_window
)
19152 skip("no taskbar?\n");
19156 SetLastError(0xdeadbeef);
19157 ret
= RegisterHotKey(taskbar_window
, 5, 0, hotkey_letter
);
19158 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19159 ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD
|| broken(GetLastError() == 0xdeadbeef),
19160 "unexpected error %ld\n", GetLastError());
19163 /* Inject the appropriate key sequence */
19164 keybd_event(VK_LWIN
, 0, 0, 0);
19165 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19166 DispatchMessageA(&msg
);
19167 ok_sequence(WmHotkeyPressLWIN
, "window hotkey press LWIN", FALSE
);
19169 keybd_event(hotkey_letter
, 0, 0, 0);
19170 queue_status
= GetQueueStatus(QS_HOTKEY
);
19171 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
19172 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19174 if (msg
.message
== WM_HOTKEY
)
19176 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
19177 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
19179 DispatchMessageA(&msg
);
19181 ok_sequence(WmHotkeyPress
, "window hotkey press", FALSE
);
19183 queue_status
= GetQueueStatus(QS_HOTKEY
);
19184 ok((queue_status
& (QS_HOTKEY
<< 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %lx\n", queue_status
);
19186 key_state
= GetAsyncKeyState(hotkey_letter
);
19187 ok((key_state
& 0x8000) == 0x8000, "unexpected key state %x\n", key_state
);
19189 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19190 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19191 DispatchMessageA(&msg
);
19192 ok_sequence(WmHotkeyRelease
, "window hotkey release", TRUE
);
19194 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
19195 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19196 DispatchMessageA(&msg
);
19197 ok_sequence(WmHotkeyReleaseLWIN
, "window hotkey release LWIN", FALSE
);
19199 /* normal posted WM_HOTKEY messages set QS_HOTKEY */
19200 PostMessageA(test_window
, WM_HOTKEY
, 0, 0);
19201 queue_status
= GetQueueStatus(QS_HOTKEY
);
19202 ok((queue_status
& (QS_HOTKEY
<< 16)) == QS_HOTKEY
<< 16, "expected QS_HOTKEY << 16 set, got %lx\n", queue_status
);
19203 queue_status
= GetQueueStatus(QS_POSTMESSAGE
);
19204 ok((queue_status
& (QS_POSTMESSAGE
<< 16)) == QS_POSTMESSAGE
<< 16, "expected QS_POSTMESSAGE << 16 set, got %lx\n", queue_status
);
19205 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19206 DispatchMessageA(&msg
);
19209 /* Send and process all messages at once */
19210 PostMessageA(test_window
, WM_APP
, 0, 0);
19211 keybd_event(VK_LWIN
, 0, 0, 0);
19212 keybd_event(hotkey_letter
, 0, 0, 0);
19213 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19214 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
19216 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19218 if (msg
.message
== WM_HOTKEY
)
19220 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
19221 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
19223 DispatchMessageA(&msg
);
19225 ok_sequence(WmHotkeyCombined
, "window hotkey combined", FALSE
);
19227 /* Register same hwnd/id with different key combination */
19228 ret
= RegisterHotKey(test_window
, 5, 0, hotkey_letter
);
19229 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
19231 /* Previous key combination does not work */
19232 keybd_event(VK_LWIN
, 0, 0, 0);
19233 keybd_event(hotkey_letter
, 0, 0, 0);
19234 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19235 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
19237 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19238 DispatchMessageA(&msg
);
19239 ok_sequence(WmHotkeyPrevious
, "window hotkey previous", FALSE
);
19241 /* New key combination works */
19242 keybd_event(hotkey_letter
, 0, 0, 0);
19243 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19245 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19247 if (msg
.message
== WM_HOTKEY
)
19249 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
19250 ok(msg
.lParam
== MAKELPARAM(0, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
19252 DispatchMessageA(&msg
);
19254 ok_sequence(WmHotkeyNew
, "window hotkey new", FALSE
);
19256 /* Unregister hotkey properly */
19257 ret
= UnregisterHotKey(test_window
, 5);
19258 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
19260 /* Unregister hotkey again */
19261 SetLastError(0xdeadbeef);
19262 ret
= UnregisterHotKey(test_window
, 5);
19263 ok(ret
== FALSE
, "expected FALSE, got %i\n", ret
);
19264 ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19265 "unexpected error %ld\n", GetLastError());
19267 /* Register thread hotkey */
19268 ret
= RegisterHotKey(NULL
, 5, MOD_WIN
, hotkey_letter
);
19269 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
19271 /* Inject the appropriate key sequence */
19272 keybd_event(VK_LWIN
, 0, 0, 0);
19273 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19275 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19276 DispatchMessageA(&msg
);
19278 ok_sequence(WmHotkeyPressLWIN
, "thread hotkey press LWIN", FALSE
);
19280 keybd_event(hotkey_letter
, 0, 0, 0);
19281 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19283 if (msg
.message
== WM_HOTKEY
)
19285 struct recvd_message message
;
19286 ok(msg
.hwnd
== NULL
, "unexpected hwnd %p\n", msg
.hwnd
);
19287 ok(msg
.lParam
== MAKELPARAM(MOD_WIN
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
19288 message
.message
= msg
.message
;
19289 message
.flags
= sent
|wparam
|lparam
;
19290 message
.wParam
= msg
.wParam
;
19291 message
.lParam
= msg
.lParam
;
19292 message
.descr
= "test_hotkey thread message";
19293 add_message(&message
);
19296 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19297 DispatchMessageA(&msg
);
19299 ok_sequence(WmHotkeyPress
, "thread hotkey press", FALSE
);
19301 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19302 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19304 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19305 DispatchMessageA(&msg
);
19307 ok_sequence(WmHotkeyRelease
, "thread hotkey release", TRUE
);
19309 keybd_event(VK_LWIN
, 0, KEYEVENTF_KEYUP
, 0);
19310 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19312 ok(msg
.hwnd
!= NULL
, "unexpected thread message %x\n", msg
.message
);
19313 DispatchMessageA(&msg
);
19315 ok_sequence(WmHotkeyReleaseLWIN
, "thread hotkey release LWIN", FALSE
);
19317 /* Search for an ALT + letter combination that hasn't been registered */
19318 for (hotkey_letter
= 'A'; hotkey_letter
<= 'Z'; hotkey_letter
++)
19320 SetLastError(0xdeadbeef);
19321 ret
= RegisterHotKey(test_window
, 6, MOD_ALT
, hotkey_letter
);
19329 ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED
|| broken(GetLastError() == 0xdeadbeef),
19330 "unexpected error %ld\n", GetLastError());
19334 if (hotkey_letter
> 'Z')
19336 ok(0, "Couldn't find any free ALT + letter combination\n");
19340 keybd_event(VK_LMENU
, 0, 0, 0);
19341 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19342 DispatchMessageA(&msg
);
19343 ok_sequence(WmHotkeyPressALT
, "window hotkey press ALT", TRUE
);
19345 keybd_event(hotkey_letter
, 0, 0, 0);
19346 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19348 if (msg
.message
== WM_HOTKEY
)
19350 ok(msg
.hwnd
== test_window
, "unexpected hwnd %p\n", msg
.hwnd
);
19351 ok(msg
.lParam
== MAKELPARAM(MOD_ALT
, hotkey_letter
), "unexpected WM_HOTKEY lparam %Ix\n", msg
.lParam
);
19353 DispatchMessageA(&msg
);
19355 ok_sequence(WmHotkeyPressWithALT
, "window hotkey press with ALT", FALSE
);
19357 keybd_event(hotkey_letter
, 0, KEYEVENTF_KEYUP
, 0);
19358 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19359 DispatchMessageA(&msg
);
19360 ok_sequence(WmHotkeyReleaseWithALT
, "window hotkey release with ALT", TRUE
);
19362 keybd_event(VK_LMENU
, 0, KEYEVENTF_KEYUP
, 0);
19363 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
19364 DispatchMessageA(&msg
);
19365 ok_sequence(WmHotkeyReleaseALT
, "window hotkey release ALT", FALSE
);
19367 /* Unregister thread hotkey */
19368 ret
= UnregisterHotKey(NULL
, 5);
19369 ok(ret
== TRUE
, "expected TRUE, got %i, err=%ld\n", ret
, GetLastError());
19371 if (hKBD_hook
) UnhookWindowsHookEx(hKBD_hook
);
19375 UnregisterHotKey(NULL
, 5);
19376 UnregisterHotKey(test_window
, 5);
19377 UnregisterHotKey(test_window
, 6);
19378 DestroyWindow(test_window
);
19383 static const struct message WmSetFocus_1
[] = {
19384 { HCBT_SETFOCUS
, hook
}, /* child */
19385 { HCBT_ACTIVATE
, hook
}, /* parent */
19386 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
19387 { WM_QUERYNEWPALETTE
, sent
|wparam
|lparam
|parent
|optional
, 0, 0 },
19388 { WM_WINDOWPOSCHANGING
, sent
|parent
, 0, SWP_NOSIZE
|SWP_NOMOVE
},
19389 { WM_ACTIVATEAPP
, sent
|wparam
|parent
, 1 },
19390 { WM_NCACTIVATE
, sent
|parent
},
19391 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
19392 { WM_GETTEXT
, sent
|defwinproc
|parent
|optional
},
19393 { WM_ACTIVATE
, sent
|wparam
|parent
, 1 },
19394 { HCBT_SETFOCUS
, hook
}, /* parent */
19395 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
19396 { WM_SETFOCUS
, sent
|defwinproc
|parent
},
19397 { WM_KILLFOCUS
, sent
|parent
},
19398 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
19399 { WM_SETFOCUS
, sent
},
19402 static const struct message WmSetFocus_2
[] = {
19403 { HCBT_SETFOCUS
, hook
}, /* parent */
19404 { WM_KILLFOCUS
, sent
},
19405 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
19406 { WM_SETFOCUS
, sent
|parent
},
19409 static const struct message WmSetFocus_3
[] = {
19410 { HCBT_SETFOCUS
, hook
}, /* child */
19414 static void test_SetFocus(void)
19416 HWND parent
, old_parent
, child
, old_focus
, old_active
;
19418 struct wnd_event wnd_event
;
19422 wnd_event
.start_event
= CreateEventW(NULL
, 0, 0, NULL
);
19423 ok(wnd_event
.start_event
!= 0, "CreateEvent error %ld\n", GetLastError());
19424 hthread
= CreateThread(NULL
, 0, thread_proc
, &wnd_event
, 0, &tid
);
19425 ok(hthread
!= 0, "CreateThread error %ld\n", GetLastError());
19426 ret
= WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
19427 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
19428 CloseHandle(wnd_event
.start_event
);
19430 parent
= CreateWindowExA(0, "TestParentClass", NULL
, WS_OVERLAPPEDWINDOW
,
19431 0, 0, 0, 0, 0, 0, 0, NULL
);
19432 ok(parent
!= 0, "failed to create parent window\n");
19433 child
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CHILD
,
19434 0, 0, 0, 0, parent
, 0, 0, NULL
);
19435 ok(child
!= 0, "failed to create child window\n");
19437 if (winetest_debug
> 1) trace("parent %p, child %p, thread window %p\n", parent
, child
, wnd_event
.hwnd
);
19440 SetActiveWindow(0);
19445 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
19446 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
19448 log_all_parent_messages
++;
19450 old_focus
= SetFocus(child
);
19451 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19452 ok_sequence(WmSetFocus_1
, "SetFocus on a child window", TRUE
);
19453 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
19454 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19455 ok(GetFocus() == child
, "expected focus %p, got %p\n", child
, GetFocus());
19457 old_focus
= SetFocus(parent
);
19458 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19459 ok_sequence(WmSetFocus_2
, "SetFocus on a parent window", FALSE
);
19460 ok(old_focus
== child
, "expected old focus %p, got %p\n", child
, old_focus
);
19461 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19462 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19464 SetLastError(0xdeadbeef);
19465 old_focus
= SetFocus((HWND
)0xdeadbeef);
19466 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
19467 "expected ERROR_INVALID_WINDOW_HANDLE, got %ld\n", GetLastError());
19468 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19469 ok_sequence(WmEmptySeq
, "SetFocus on an invalid window", FALSE
);
19470 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19471 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19472 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19474 SetLastError(0xdeadbeef);
19475 old_focus
= SetFocus(GetDesktopWindow());
19476 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
19477 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
19478 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19479 ok_sequence(WmEmptySeq
, "SetFocus on a desktop window", TRUE
);
19480 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19481 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19482 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19484 SetLastError(0xdeadbeef);
19485 old_focus
= SetFocus(wnd_event
.hwnd
);
19486 ok(GetLastError() == ERROR_ACCESS_DENIED
/* Vista+ */ ||
19487 broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
19488 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19489 ok_sequence(WmEmptySeq
, "SetFocus on another thread window", TRUE
);
19490 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19491 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19492 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19494 SetLastError(0xdeadbeef);
19495 old_active
= SetActiveWindow((HWND
)0xdeadbeef);
19496 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
|| broken(GetLastError() == 0xdeadbeef),
19497 "expected ERROR_INVALID_WINDOW_HANDLE, got %ld\n", GetLastError());
19498 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19499 ok_sequence(WmEmptySeq
, "SetActiveWindow on an invalid window", FALSE
);
19500 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
19501 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19502 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19504 SetLastError(0xdeadbeef);
19505 old_active
= SetActiveWindow(GetDesktopWindow());
19507 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
19508 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19509 ok_sequence(WmEmptySeq
, "SetActiveWindow on a desktop window", TRUE
);
19510 ok(old_active
== 0, "expected old focus 0, got %p\n", old_focus
);
19511 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19512 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19514 SetLastError(0xdeadbeef);
19515 old_active
= SetActiveWindow(wnd_event
.hwnd
);
19517 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
19518 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19519 ok_sequence(WmEmptySeq
, "SetActiveWindow on another thread window", TRUE
);
19520 ok(old_active
== 0, "expected old focus 0, got %p\n", old_active
);
19521 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19522 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19524 SetLastError(0xdeadbeef);
19525 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, TRUE
);
19526 ok(ret
, "AttachThreadInput error %ld\n", GetLastError());
19528 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19529 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19534 old_focus
= SetFocus(wnd_event
.hwnd
);
19535 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19536 ok(old_focus
== wnd_event
.hwnd
, "expected old focus %p, got %p\n", wnd_event
.hwnd
, old_focus
);
19537 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
19538 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
19540 old_focus
= SetFocus(parent
);
19541 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19542 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
19543 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19544 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19549 old_active
= SetActiveWindow(wnd_event
.hwnd
);
19550 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19551 ok(old_active
== parent
, "expected old focus %p, got %p\n", parent
, old_active
);
19552 ok(GetActiveWindow() == wnd_event
.hwnd
, "expected active %p, got %p\n", wnd_event
.hwnd
, GetActiveWindow());
19553 ok(GetFocus() == wnd_event
.hwnd
, "expected focus %p, got %p\n", wnd_event
.hwnd
, GetFocus());
19555 SetLastError(0xdeadbeef);
19556 ret
= AttachThreadInput(GetCurrentThreadId(), tid
, FALSE
);
19557 ok(ret
, "AttachThreadInput error %ld\n", GetLastError());
19559 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
19560 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
19562 old_parent
= SetParent(child
, GetDesktopWindow());
19563 ok(old_parent
== parent
, "expected old parent %p, got %p\n", parent
, old_parent
);
19565 ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow());
19566 ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
19568 old_focus
= SetFocus(parent
);
19569 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19570 ok(old_focus
== parent
, "expected old focus %p, got %p\n", parent
, old_focus
);
19571 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19572 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19577 SetLastError(0xdeadbeef);
19578 old_focus
= SetFocus(child
);
19580 ok(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista+ */ ||
19581 broken(GetLastError() == 0) /* XP */ ||
19582 broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
19583 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19584 ok_sequence(WmSetFocus_3
, "SetFocus on a child window", TRUE
);
19585 ok(old_focus
== 0, "expected old focus 0, got %p\n", old_focus
);
19586 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19587 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19589 SetLastError(0xdeadbeef);
19590 old_active
= SetActiveWindow(child
);
19591 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
19592 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
19593 ok_sequence(WmEmptySeq
, "SetActiveWindow on a child window", FALSE
);
19594 ok(old_active
== parent
, "expected old active %p, got %p\n", parent
, old_active
);
19595 ok(GetActiveWindow() == parent
, "expected active %p, got %p\n", parent
, GetActiveWindow());
19596 ok(GetFocus() == parent
, "expected focus %p, got %p\n", parent
, GetFocus());
19598 log_all_parent_messages
--;
19600 DestroyWindow(child
);
19601 DestroyWindow(parent
);
19603 ret
= PostMessageA(wnd_event
.hwnd
, WM_QUIT
, 0, 0);
19604 ok(ret
, "PostMessage(WM_QUIT) error %ld\n", GetLastError());
19605 ret
= WaitForSingleObject(hthread
, INFINITE
);
19606 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
19607 CloseHandle(hthread
);
19610 static const struct message WmSetLayeredStyle
[] = {
19611 { WM_STYLECHANGING
, sent
},
19612 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
19613 { WM_STYLECHANGED
, sent
},
19614 { WM_GETTEXT
, sent
|defwinproc
|optional
},
19618 static const struct message WmSetLayeredStyle2
[] = {
19619 { WM_STYLECHANGING
, sent
},
19620 { WM_STYLECHANGED
, sent
},
19621 { WM_WINDOWPOSCHANGING
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
19622 { WM_NCCALCSIZE
, sent
|optional
|wparam
|defwinproc
, 1 },
19623 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
19624 { WM_WINDOWPOSCHANGED
, sent
|optional
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOACTIVATE
|SWP_NOSIZE
|SWP_NOMOVE
},
19625 { WM_MOVE
, sent
|optional
|defwinproc
|wparam
, 0 },
19626 { WM_SIZE
, sent
|optional
|defwinproc
|wparam
, SIZE_RESTORED
},
19627 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|optional
, 0, 0 },
19631 static const struct message WmLayeredWinEmptySeq
[] = {
19632 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
19636 struct layered_window_info
19645 static DWORD CALLBACK
update_layered_proc( void *param
)
19647 struct layered_window_info
*info
= param
;
19648 POINT src
= { 0, 0 };
19650 info
->ret
= pUpdateLayeredWindow( info
->hwnd
, 0, NULL
, &info
->size
,
19651 info
->hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19652 ok( info
->ret
, "failed\n");
19653 SetEvent( info
->event
);
19657 static void test_layered_window(void)
19668 struct layered_window_info info
;
19670 if (!pUpdateLayeredWindow
)
19672 win_skip( "UpdateLayeredWindow not supported\n" );
19676 hdc
= CreateCompatibleDC( 0 );
19677 bmp
= CreateCompatibleBitmap( hdc
, 300, 300 );
19678 SelectObject( hdc
, bmp
);
19680 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
,
19681 100, 100, 300, 300, 0, 0, 0, NULL
);
19682 ok( hwnd
!= 0, "failed to create window\n" );
19683 ShowWindow( hwnd
, SW_SHOWNORMAL
);
19684 UpdateWindow( hwnd
);
19688 GetWindowRect( hwnd
, &rect
);
19689 GetClientRect( hwnd
, &client
);
19690 ok( client
.right
< rect
.right
- rect
.left
, "wrong client area\n" );
19691 ok( client
.bottom
< rect
.bottom
- rect
.top
, "wrong client area\n" );
19694 pos
.x
= pos
.y
= 300;
19695 size
.cx
= size
.cy
= 250;
19696 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19697 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
19698 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
19699 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
19700 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
19702 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19703 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
19704 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
19705 GetWindowRect( hwnd
, &rect
);
19706 ok( rect
.left
== 300 && rect
.top
== 300 && rect
.right
== 550 && rect
.bottom
== 550,
19707 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19708 GetClientRect( hwnd
, &rect
);
19709 ok( rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
- 50,
19710 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19714 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19715 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
19716 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
19717 GetWindowRect( hwnd
, &rect
);
19718 ok( rect
.left
== 300 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 450,
19719 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19720 GetClientRect( hwnd
, &rect
);
19721 ok( rect
.right
== client
.right
- 150 && rect
.bottom
== client
.bottom
- 50,
19722 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19724 SetWindowLongA( hwnd
, GWL_STYLE
,
19725 GetWindowLongA(hwnd
, GWL_STYLE
) & ~(WS_CAPTION
| WS_THICKFRAME
| WS_SYSMENU
) );
19726 ok_sequence( WmSetLayeredStyle2
, "WmSetLayeredStyle2", FALSE
);
19730 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19731 ok( ret
, "UpdateLayeredWindow failed err %lu\n", GetLastError() );
19732 ok_sequence( WmLayeredWinEmptySeq
, "UpdateLayeredWindow", FALSE
);
19733 GetWindowRect( hwnd
, &rect
);
19734 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
19735 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19736 GetClientRect( hwnd
, &rect
);
19737 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
19738 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
19739 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19742 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19743 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
19744 ok( GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == ERROR_MR_MID_NOT_FOUND
) ||
19745 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win7 */, "wrong error %lu\n", GetLastError() );
19748 ret
= pUpdateLayeredWindow( hwnd
, 0, &pos
, &size
, hdc
, &src
, 0, NULL
, ULW_OPAQUE
);
19749 ok( !ret
, "UpdateLayeredWindow should fail on non-layered window\n" );
19750 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
19752 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) & ~WS_EX_LAYERED
);
19753 ok_sequence( WmSetLayeredStyle
, "WmSetLayeredStyle", FALSE
);
19754 GetWindowRect( hwnd
, &rect
);
19755 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 400 && rect
.bottom
== 450,
19756 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19757 GetClientRect( hwnd
, &rect
);
19758 ok( (rect
.right
== 200 && rect
.bottom
== 250) ||
19759 broken(rect
.right
== client
.right
- 100 && rect
.bottom
== client
.bottom
- 50),
19760 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19762 SetWindowLongA( hwnd
, GWL_EXSTYLE
, GetWindowLongA(hwnd
, GWL_EXSTYLE
) | WS_EX_LAYERED
);
19765 info
.size
.cx
= 250;
19766 info
.size
.cy
= 300;
19767 info
.event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
19769 thread
= CreateThread( NULL
, 0, update_layered_proc
, &info
, 0, &tid
);
19770 ok( WaitForSingleObject( info
.event
, 1000 ) == 0, "wait failed\n" );
19771 ok( info
.ret
, "UpdateLayeredWindow failed in other thread\n" );
19772 WaitForSingleObject( thread
, 1000 );
19773 CloseHandle( thread
);
19774 GetWindowRect( hwnd
, &rect
);
19775 ok( rect
.left
== 200 && rect
.top
== 200 && rect
.right
== 450 && rect
.bottom
== 500,
19776 "wrong window rect %s\n", wine_dbgstr_rect( &rect
));
19777 GetClientRect( hwnd
, &rect
);
19778 ok( (rect
.right
== 250 && rect
.bottom
== 300) ||
19779 broken(rect
.right
== client
.right
- 50 && rect
.bottom
== client
.bottom
),
19780 "wrong client rect %s\n", wine_dbgstr_rect( &rect
));
19782 DestroyWindow( hwnd
);
19784 DeleteObject( bmp
);
19787 static HMENU hpopupmenu
;
19789 static LRESULT WINAPI
minimize_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
19793 if (ignore_message( message
)) return 0;
19794 ret
= MsgCheckProc( FALSE
, hwnd
, message
, wParam
, lParam
);
19798 ShowWindow(hwnd
, SW_MINIMIZE
);
19808 static LRESULT WINAPI
cancel_popup_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
19810 if (ignore_message( message
)) return 0;
19814 todo_wine
ok(GetCapture() == hwnd
, "expected %p, got %p\n", hwnd
, GetCapture());
19818 case WM_INITMENUPOPUP
:
19819 case WM_UNINITMENUPOPUP
:
19820 ok((HMENU
)wParam
== hpopupmenu
, "expected %p, got %Ix\n", hpopupmenu
, wParam
);
19822 case WM_CAPTURECHANGED
:
19823 todo_wine
ok(!lParam
|| (HWND
)lParam
== hwnd
, "lost capture to %Ix\n", lParam
);
19827 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
19830 static LRESULT WINAPI
cancel_init_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
19832 if (ignore_message( message
)) return 0;
19835 case WM_ENTERMENULOOP
:
19836 ok(EndMenu() == TRUE
, "EndMenu() failed\n");
19840 return MsgCheckProc (FALSE
, hwnd
, message
, wParam
, lParam
);
19843 static void test_TrackPopupMenu(void)
19849 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
19852 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
19854 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
19856 hpopupmenu
= CreatePopupMenu();
19857 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
19859 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 1");
19860 AppendMenuA(hpopupmenu
, MF_STRING
, 100, "item 2");
19864 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19865 ok_sequence(WmTrackPopupMenu
, "TrackPopupMenu", TRUE
);
19866 ok(ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError());
19868 /* Test popup closing with an ESC-press */
19870 PostMessageW(hwnd
, WM_KEYDOWN
, VK_ESCAPE
, 0);
19871 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19872 ok(ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError());
19873 PostQuitMessage(0);
19875 while ( PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
) )
19877 TranslateMessage(&msg
);
19878 DispatchMessageA(&msg
);
19880 ok_sequence(WmTrackPopupMenuEsc
, "TrackPopupMenuEsc", FALSE
); /* Shouldn't get any message */
19882 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_init_proc
);
19886 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19887 ok_sequence(WmTrackPopupMenuAbort
, "WmTrackPopupMenuAbort", TRUE
);
19888 ok(ret
== TRUE
, "TrackPopupMenu failed\n");
19890 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)minimize_popup_proc
);
19892 /* set cursor over the window, otherwise the WM_CANCELMODE message may not always be sent */
19893 SetCursorPos( 0, 0 );
19894 ShowWindow( hwnd
, SW_SHOW
);
19898 SetTimer( hwnd
, TIMER_ID
, 500, NULL
);
19899 ret
= TrackPopupMenu( hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19900 ok_sequence( WmTrackPopupMenuMinimizeWindow
, "TrackPopupMenuMinimizeWindow", TRUE
);
19901 ok( ret
== 1, "TrackPopupMenu failed with error %li\n", GetLastError() );
19902 KillTimer( hwnd
, TIMER_ID
);
19903 ShowWindow( hwnd
, SW_RESTORE
);
19905 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
19911 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19912 ok_sequence(WmTrackPopupMenuCapture
, "TrackPopupMenuCapture", TRUE
);
19913 ok(ret
== 1, "TrackPopupMenuCapture failed with error %li\n", GetLastError());
19915 DestroyMenu(hpopupmenu
);
19916 DestroyWindow(hwnd
);
19919 static void test_TrackPopupMenuEmpty(void)
19924 hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, 0,
19927 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
19929 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)cancel_popup_proc
);
19931 hpopupmenu
= CreatePopupMenu();
19932 ok(hpopupmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
19936 ret
= TrackPopupMenu(hpopupmenu
, 0, 100,100, 0, hwnd
, NULL
);
19937 ok_sequence(WmTrackPopupMenuEmpty
, "TrackPopupMenuEmpty", TRUE
);
19938 ok(ret
== 0, "TrackPopupMenu succeeded\n");
19940 DestroyMenu(hpopupmenu
);
19941 DestroyWindow(hwnd
);
19944 static const struct message send_message_1
[] = {
19945 { WM_USER
+2, sent
|wparam
|lparam
, 0, 0 },
19946 { WM_USER
, sent
|wparam
|lparam
, 0, 0 },
19949 static const struct message send_message_2
[] = {
19950 { WM_USER
+4, sent
|wparam
|lparam
, 0, 0 },
19953 static const struct message send_message_3
[] = {
19954 { WM_USER
+3, sent
|wparam
|lparam
, 0, 0 },
19955 { WM_USER
+1, sent
|wparam
|lparam
, 0, 0 },
19958 static const struct message send_message_5
[] = {
19959 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
, 0, SWP_NOZORDER
}, /* win7+ dual monitor */
19960 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* win7+ dual monitor */
19961 { WM_WINDOWPOSCHANGING
, sent
|wparam
|optional
, SWP_NOACTIVATE
, 0, SWP_NOZORDER
}, /* win7+ dual monitor */
19962 { WM_GETMINMAXINFO
, sent
|defwinproc
|optional
}, /* win7+ dual monitor */
19966 static DWORD WINAPI
SendMessage_thread_1(void *param
)
19968 struct wnd_event
*wnd_event
= param
;
19971 if (winetest_debug
> 1) trace("thread: starting\n");
19972 WaitForSingleObject(wnd_event
->start_event
, INFINITE
);
19974 if (winetest_debug
> 1) trace("thread: call PostMessage\n");
19975 PostMessageA(wnd_event
->hwnd
, WM_USER
, 0, 0);
19977 if (winetest_debug
> 1) trace("thread: call PostMessage\n");
19978 PostMessageA(wnd_event
->hwnd
, WM_USER
+1, 0, 0);
19980 if (winetest_debug
> 1) trace("thread: call SendMessage\n");
19981 SendMessageA(wnd_event
->hwnd
, WM_USER
+2, 0, 0);
19982 SetEvent(wnd_event
->stop_event
);
19983 ret
= WaitForSingleObject(wnd_event
->getmessage_complete
, 100);
19984 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed, ret:%lx\n", ret
);
19986 if (winetest_debug
> 1) trace("thread: call SendMessage\n");
19987 SendMessageA(wnd_event
->hwnd
, WM_USER
+3, 0, 0);
19992 static void test_SendMessage_other_thread(void)
19994 DWORD qs_all_input
= QS_ALLINPUT
& ~QS_RAWINPUT
;
19996 struct wnd_event wnd_event
;
20000 wnd_event
.start_event
= CreateEventA(NULL
, 0, 0, NULL
);
20001 wnd_event
.stop_event
= CreateEventA(NULL
, 0, 0, NULL
);
20002 wnd_event
.getmessage_complete
= CreateEventA(NULL
, 0, 0, NULL
);
20004 wnd_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
20005 100, 100, 200, 200, 0, 0, 0, NULL
);
20006 ok(wnd_event
.hwnd
!= 0, "CreateWindowEx failed\n");
20008 hthread
= CreateThread(NULL
, 0, SendMessage_thread_1
, &wnd_event
, 0, &tid
);
20009 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
20010 CloseHandle(hthread
);
20015 ret
= GetQueueStatus(QS_SENDMESSAGE
);
20016 ok(ret
== 0, "wrong status %08lx\n", ret
);
20018 SetEvent(wnd_event
.start_event
);
20020 /* wait for other thread's SendMessage */
20023 ret
= GetQueueStatus(QS_SENDMESSAGE
);
20024 if (ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
)) break;
20028 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
20029 ok(ret
== MAKELONG(QS_POSTMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08lx\n", ret
);
20031 if (winetest_debug
> 1) trace("main: call GetMessage\n");
20032 GetMessageA(&msg
, 0, 0, 0);
20033 ok(msg
.message
== WM_USER
, "expected WM_USER, got %04x\n", msg
.message
);
20034 DispatchMessageA(&msg
);
20035 ok_sequence(send_message_1
, "SendMessage from other thread 1", FALSE
);
20037 SetEvent(wnd_event
.getmessage_complete
);
20039 ret
= WaitForSingleObject(wnd_event
.stop_event
, 100);
20040 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed, ret:%lx\n", ret
);
20042 /* intentionally yield */
20043 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
20045 if (winetest_debug
> 1) trace("main: call SendMessage\n");
20046 SendMessageA(wnd_event
.hwnd
, WM_USER
+4, 0, 0);
20047 ok_sequence(send_message_2
, "SendMessage from other thread 2", FALSE
);
20049 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
20050 ok(ret
== MAKELONG(QS_SENDMESSAGE
, QS_SENDMESSAGE
|QS_POSTMESSAGE
), "wrong status %08lx\n", ret
);
20052 if (winetest_debug
> 1) trace("main: call PeekMessage\n");
20053 ok(PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
), "PeekMessage should not fail\n");
20054 ok(msg
.message
== WM_USER
+1, "expected WM_USER+1, got %04x\n", msg
.message
);
20055 DispatchMessageA(&msg
);
20056 ok_sequence(send_message_3
, "SendMessage from other thread 3", FALSE
);
20058 /* intentionally yield */
20059 MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, qs_all_input
);
20061 if (winetest_debug
> 1) trace("main: call PeekMessage\n");
20062 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
20063 ok(ignore_message(msg
.message
), "got unexpected message %04x from PeekMessageA\n", msg
.message
);
20065 ok_sequence(send_message_5
, "SendMessage from other thread 5", FALSE
);
20067 ret
= GetQueueStatus(QS_SENDMESSAGE
|QS_POSTMESSAGE
);
20068 ok(ret
== 0, "wrong status %08lx\n", ret
);
20070 if (winetest_debug
> 1) trace("main: call DestroyWindow\n");
20071 DestroyWindow(msg
.hwnd
);
20076 CloseHandle(wnd_event
.start_event
);
20077 CloseHandle(wnd_event
.stop_event
);
20078 CloseHandle(wnd_event
.getmessage_complete
);
20081 static DWORD WINAPI
SetParent_thread(void *param
)
20083 struct wnd_event
*wnd_event
= param
;
20085 if (winetest_debug
> 1) trace("thread: started\n");
20086 SetEvent(wnd_event
->start_event
);
20088 /* this leads to sending an internal message under Wine */
20089 if (winetest_debug
> 1) trace("thread: call SetParent\n");
20090 SetParent(wnd_event
->hwnd
, wnd_event
->hwnd
);
20095 static void test_setparent_status(void)
20098 struct wnd_event wnd_event
;
20101 wnd_event
.start_event
= CreateEventA(NULL
, 0, 0, NULL
);
20103 wnd_event
.hwnd
= CreateWindowExA(0, "TestWindowClass", NULL
, WS_OVERLAPPEDWINDOW
,
20104 100, 100, 200, 200, 0, 0, 0, NULL
);
20105 ok(wnd_event
.hwnd
!= 0, "CreateWindowEx failed\n");
20107 ret
= GetQueueStatus(QS_SENDMESSAGE
);
20108 ok(ret
== 0, "wrong status %08lx\n", ret
);
20110 hthread
= CreateThread(NULL
, 0, SetParent_thread
, &wnd_event
, 0, NULL
);
20111 ok(hthread
!= NULL
, "CreateThread failed, error %ld\n", GetLastError());
20113 WaitForSingleObject(wnd_event
.start_event
, INFINITE
);
20115 /* background thread's SetParent should complete allowing the thread to exit */
20116 ret
= MsgWaitForMultipleObjects(1, &hthread
, FALSE
, 1000, QS_SENDMESSAGE
);
20117 todo_wine
ok(ret
== WAIT_OBJECT_0
, "MsgWaitForMultipleObjects returned %08lx\n", ret
);
20119 /* QS_SENDMESSAGE status should not have been set by SetParent */
20120 ret
= GetQueueStatus(QS_SENDMESSAGE
);
20121 todo_wine
ok(ret
== 0, "wrong status %08lx\n", ret
);
20123 DestroyWindow(wnd_event
.hwnd
);
20125 WaitForSingleObject(hthread
, INFINITE
);
20126 CloseHandle(hthread
);
20127 CloseHandle(wnd_event
.start_event
);
20130 static LRESULT CALLBACK
insendmessage_wnd_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
20132 DWORD flags
= InSendMessageEx( NULL
);
20138 ok( flags
== ISMEX_SEND
, "wrong flags %lx\n", flags
);
20139 ok( InSendMessage(), "InSendMessage returned false\n" );
20140 ret
= ReplyMessage( msg
);
20141 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
20142 flags
= InSendMessageEx( NULL
);
20143 ok( flags
== (ISMEX_SEND
| ISMEX_REPLIED
) || broken( flags
== (ISMEX_NOTIFY
| ISMEX_REPLIED
) ),
20144 "wrong flags %lx\n", flags
);
20145 ok( InSendMessage(), "InSendMessage returned false\n" );
20148 ok( flags
== ISMEX_NOTIFY
, "wrong flags %lx\n", flags
);
20149 ok( InSendMessage(), "InSendMessage returned false\n" );
20150 ret
= ReplyMessage( msg
);
20151 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
20152 flags
= InSendMessageEx( NULL
);
20153 ok( flags
== ISMEX_NOTIFY
, "wrong flags %lx\n", flags
);
20154 ok( InSendMessage(), "InSendMessage returned false\n" );
20157 ok( flags
== ISMEX_CALLBACK
, "wrong flags %lx\n", flags
);
20158 ok( InSendMessage(), "InSendMessage returned false\n" );
20159 ret
= ReplyMessage( msg
);
20160 ok( ret
, "ReplyMessage failed err %lu\n", GetLastError() );
20161 flags
= InSendMessageEx( NULL
);
20162 ok( flags
== (ISMEX_CALLBACK
| ISMEX_REPLIED
) || flags
== ISMEX_SEND
, "wrong flags %lx\n", flags
);
20163 ok( InSendMessage(), "InSendMessage returned false\n" );
20166 ok( flags
== ISMEX_NOSEND
, "wrong flags %lx\n", flags
);
20167 ok( !InSendMessage(), "InSendMessage returned true\n" );
20168 ret
= ReplyMessage( msg
);
20169 ok( !ret
, "ReplyMessage succeeded\n" );
20173 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
20176 static void CALLBACK
msg_callback( HWND hwnd
, UINT msg
, ULONG_PTR arg
, LRESULT result
)
20178 ok( msg
== WM_USER
+ 2, "wrong msg %x\n", msg
);
20179 ok( result
== WM_USER
+ 2, "wrong result %Ix\n", result
);
20182 static DWORD WINAPI
send_message_thread( void *arg
)
20186 SendMessageA( win
, WM_USER
, 0, 0 );
20187 SendNotifyMessageA( win
, WM_USER
+ 1, 0, 0 );
20188 SendMessageCallbackA( win
, WM_USER
+ 2, 0, 0, msg_callback
, 0 );
20189 PostMessageA( win
, WM_USER
+ 3, 0, 0 );
20190 PostMessageA( win
, WM_QUIT
, 0, 0 );
20194 static void test_InSendMessage(void)
20202 memset(&cls
, 0, sizeof(cls
));
20203 cls
.lpfnWndProc
= insendmessage_wnd_proc
;
20204 cls
.hInstance
= GetModuleHandleA(NULL
);
20205 cls
.lpszClassName
= "InSendMessage_test";
20206 register_class(&cls
);
20208 win
= CreateWindowA( "InSendMessage_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
20209 ok( win
!= NULL
, "CreateWindow failed: %ld\n", GetLastError() );
20211 thread
= CreateThread( NULL
, 0, send_message_thread
, win
, 0, &tid
);
20212 ok( thread
!= NULL
, "CreateThread failed: %ld\n", GetLastError() );
20214 while (GetMessageA(&msg
, NULL
, 0, 0)) DispatchMessageA( &msg
);
20216 ok( WaitForSingleObject( thread
, 30000 ) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
20217 CloseHandle( thread
);
20219 DestroyWindow( win
);
20220 UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL
) );
20223 static const struct message DoubleSetCaptureSeq
[] =
20225 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
20226 { EVENT_SYSTEM_CAPTUREEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
20227 { EVENT_SYSTEM_CAPTURESTART
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
20228 { WM_CAPTURECHANGED
, sent
},
20232 static void test_DoubleSetCapture(void)
20236 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture",
20237 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
20238 100, 100, 200, 200, 0, 0, 0, NULL
);
20239 ok (hwnd
!= 0, "Failed to create overlapped window\n");
20241 ShowWindow( hwnd
, SW_SHOW
);
20242 UpdateWindow( hwnd
);
20246 SetCapture( hwnd
);
20247 SetCapture( hwnd
);
20248 ok_sequence(DoubleSetCaptureSeq
, "SetCapture( hwnd ) twice", FALSE
);
20250 DestroyWindow(hwnd
);
20253 static const struct message WmRestoreMinimizedSeq
[] =
20255 { HCBT_ACTIVATE
, hook
},
20256 { EVENT_SYSTEM_FOREGROUND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
20257 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
},
20258 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOCLIENTSIZE
|SWP_NOCLIENTMOVE
},
20259 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
20260 { WM_NCACTIVATE
, sent
|wparam
, 0x200001 },
20261 { WM_GETTEXT
, sent
|defwinproc
|optional
},
20262 { WM_ACTIVATE
, sent
|wparam
, 0x200001 }, /* Note that activate messages are after WM_WINDOWPOSCHANGED and before WM_SYSCOMMAND */
20263 { HCBT_KEYSKIPPED
, hook
|optional
},
20264 { WM_SYSKEYUP
, sent
|optional
},
20265 { WM_SYSCOMMAND
, sent
|wparam
, SC_RESTORE
},
20266 { HCBT_SYSCOMMAND
, hook
|wparam
, SC_RESTORE
},
20267 { HCBT_SYSCOMMAND
, hook
|wparam
|optional
, SC_RESTORE
},
20268 { HCBT_MINMAX
, hook
},
20269 { HCBT_MINMAX
, hook
|optional
},
20270 { WM_QUERYOPEN
, sent
|defwinproc
},
20271 { WM_QUERYOPEN
, sent
|optional
},
20272 { WM_GETTEXT
, sent
|defwinproc
|optional
},
20273 { WM_WINDOWPOSCHANGING
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
20274 { WM_GETMINMAXINFO
, sent
|defwinproc
},
20275 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
, 1 },
20276 { EVENT_OBJECT_REORDER
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
20277 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
20278 { WM_GETTEXT
, sent
|defwinproc
|optional
},
20279 { WM_ERASEBKGND
, sent
|defwinproc
},
20280 { WM_WINDOWPOSCHANGED
, sent
|wparam
|defwinproc
, SWP_FRAMECHANGED
|SWP_NOCOPYBITS
|SWP_STATECHANGED
},
20281 { WM_MOVE
, sent
|defwinproc
},
20282 { WM_SIZE
, sent
|defwinproc
},
20283 { EVENT_OBJECT_LOCATIONCHANGE
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
20284 { EVENT_SYSTEM_MINIMIZEEND
, winevent_hook
|wparam
|lparam
|msg_todo
, 0, 0 },
20285 { WM_NCCALCSIZE
, sent
|wparam
|defwinproc
|optional
, 1 },
20286 { WM_NCPAINT
, sent
|wparam
|defwinproc
|optional
, 1 },
20287 { WM_ERASEBKGND
, sent
|defwinproc
|optional
},
20288 { HCBT_SETFOCUS
, hook
},
20289 { EVENT_OBJECT_FOCUS
, winevent_hook
|wparam
|lparam
, OBJID_CLIENT
, 0 },
20290 { WM_SETFOCUS
, sent
|defwinproc
},
20291 { WM_ACTIVATE
, sent
|wparam
|defwinproc
, 1 },
20292 { WM_PAINT
, sent
| optional
},
20293 { WM_SETFOCUS
, sent
|defwinproc
|optional
},
20294 { HCBT_KEYSKIPPED
, hook
|optional
},
20295 { WM_KEYUP
, sent
|optional
},
20296 { HCBT_KEYSKIPPED
, hook
|optional
},
20297 { WM_SYSKEYUP
, sent
|optional
},
20298 { HCBT_KEYSKIPPED
, hook
|optional
},
20299 { WM_KEYUP
, sent
|optional
},
20300 { HCBT_KEYSKIPPED
, hook
|optional
},
20301 { WM_SYSKEYUP
, sent
|optional
},
20302 { HCBT_KEYSKIPPED
, hook
|optional
},
20303 { WM_KEYUP
, sent
|optional
},
20304 { WM_PAINT
, sent
| optional
},
20308 static void test_restore_messages(void)
20314 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, 100,
20315 100, 200, 200, 0, 0, 0, NULL
);
20316 ok (hwnd
!= 0, "Failed to create overlapped window\n");
20317 SetForegroundWindow(hwnd
);
20318 ShowWindow(hwnd
, SW_MINIMIZE
);
20322 for (i
= 0; i
< 5; i
++)
20324 /* Send Alt+Tab to restore test window from minimized state */
20325 ip
.type
= INPUT_KEYBOARD
;
20326 ip
.ki
.wVk
= VK_MENU
;
20327 SendInput(1, &ip
, sizeof(INPUT
));
20328 ip
.ki
.wVk
= VK_TAB
;
20329 SendInput(1, &ip
, sizeof(INPUT
));
20330 ip
.ki
.wVk
= VK_MENU
;
20331 ip
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
20332 SendInput(1, &ip
, sizeof(INPUT
));
20333 ip
.ki
.wVk
= VK_TAB
;
20334 ip
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
20335 SendInput(1, &ip
, sizeof(INPUT
));
20337 if (!IsIconic(hwnd
))
20341 if (IsIconic(hwnd
))
20343 skip("Alt+Tab failed to bring up test window.\n");
20346 ok_sequence(WmRestoreMinimizedSeq
, "Restore minimized window", TRUE
);
20349 DestroyWindow(hwnd
);
20352 static void test_invalid_window(void)
20357 SetLastError(0xdeadbeef);
20358 ret
= GetMessageA(&msg
, (HWND
)0xdeadbeef, 0, 0);
20359 ok(ret
== -1, "wrong ret %d\n", ret
);
20360 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError());
20362 SetLastError(0xdeadbeef);
20363 ret
= PeekMessageA(&msg
, (HWND
)0xdeadbeef, 0, 0, PM_REMOVE
);
20364 ok(!ret
, "wrong ret %d\n", ret
);
20365 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError());
20368 static void test_button_style(void)
20370 DWORD type
, expected_type
;
20375 for (i
= BS_PUSHBUTTON
; i
<= BS_DEFCOMMANDLINK
; ++i
)
20377 button
= CreateWindowA(WC_BUTTONA
, "test", i
, 0, 0, 50, 50, NULL
, 0, 0, NULL
);
20378 ok(button
!= NULL
, "Expected button not null.\n");
20380 type
= GetWindowLongW(button
, GWL_STYLE
) & BS_TYPEMASK
;
20381 expected_type
= (i
== BS_USERBUTTON
? BS_PUSHBUTTON
: i
);
20382 ok(type
== expected_type
, "Expected type %#lx, got %#lx.\n", expected_type
, type
);
20384 for (j
= BS_PUSHBUTTON
; j
<= BS_DEFCOMMANDLINK
; ++j
)
20386 ret
= SendMessageA(button
, BM_SETSTYLE
, j
, FALSE
);
20387 ok(ret
== 0, "Expected %#x, got %#Ix.\n", 0, ret
);
20389 type
= GetWindowLongW(button
, GWL_STYLE
) & BS_TYPEMASK
;
20392 ok(type
== expected_type
, "Original type %#lx, expected new type %#lx, got %#lx.\n", i
,
20393 expected_type
, type
);
20395 DestroyWindow(button
);
20399 static LRESULT WINAPI
test_create_name_procW( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
20406 CREATESTRUCTW
*cs
= (CREATESTRUCTW
*)lparam
;
20407 memcpy( cs
->lpCreateParams
, cs
->lpszName
, 3 * sizeof(WCHAR
) );
20411 if (winetest_debug
> 1) trace("%s\n", debugstr_w((const WCHAR
*)lparam
));
20415 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
20418 static void test_create_name(void)
20420 WNDCLASSW clsW
= { 0 };
20424 clsW
.lpfnWndProc
= test_create_name_procW
;
20425 clsW
.lpszClassName
= L
"TestCreateNameClassW";
20426 RegisterClassW( &clsW
);
20428 hwnd
= CreateWindowExW( 0, L
"TestCreateNameClassW", L
"\xffff\x6162",
20429 WS_POPUP
, 0,0,0,0,0,0,0, name_buf
);
20430 ok( hwnd
!= NULL
, "CreateWindowEx failed: %lu\n", GetLastError() );
20431 ok(!memcmp(name_buf
, L
"\xffff\x6162", 2 * sizeof(WCHAR
)),
20432 "name param = %s\n", debugstr_wn(name_buf
, 2));
20433 DestroyWindow( hwnd
);
20435 hwnd
= CreateWindowExA( 0, "TestCreateNameClassW", "\xff\0\x61\x60",
20436 WS_POPUP
, 0,0,0,0,0,0,0, name_buf
);
20437 ok( hwnd
!= NULL
, "CreateWindowEx failed: %lu\n", GetLastError() );
20438 ok(!memcmp(name_buf
, L
"\xffff\x6100", 2 * sizeof(WCHAR
)),
20439 "name param = %s\n", debugstr_wn(name_buf
, 2));
20440 DestroyWindow( hwnd
);
20442 UnregisterClassW( L
"TestCreateNameClassW", NULL
);
20445 static LRESULT WINAPI
changed_window_proc( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
20447 if (msg
== WM_USER
) return 3;
20448 return DefWindowProcW( hwnd
, msg
, wparam
, lparam
);
20451 static LRESULT WINAPI
call_window_proc_hook( INT code
, WPARAM wparam
, LPARAM lparam
)
20453 CWPSTRUCT
*cwp
= (CWPSTRUCT
*)lparam
;
20455 ok( cwp
->message
== WM_USER
, "message = %u\n", cwp
->message
);
20456 SetWindowLongPtrW( cwp
->hwnd
, GWLP_WNDPROC
, (LONG_PTR
)changed_window_proc
);
20457 return CallNextHookEx( NULL
, code
, wparam
, lparam
);
20460 static void test_hook_changing_window_proc(void)
20466 hwnd
= CreateWindowExW( 0, L
"static", NULL
, WS_POPUP
, 0,0,0,0,GetDesktopWindow(),0,0, NULL
);
20467 hook
= SetWindowsHookExW( WH_CALLWNDPROC
, call_window_proc_hook
, NULL
, GetCurrentThreadId() );
20468 ok( hook
!= NULL
, "SetWindowsHookExW failed: %lu\n", GetLastError() );
20470 res
= SendMessageW( hwnd
, WM_USER
, 1, 2 );
20471 ok( res
== 3, "SendMessageW(WM_USER) returned %Iu\n", res
);
20473 UnhookWindowsHookEx( hook
);
20474 DestroyWindow( hwnd
);
20481 BOOL (WINAPI
*pIsWinEventHookInstalled
)(DWORD
)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
20484 argc
= winetest_get_mainargs( &test_argv
);
20488 /* Child process. */
20489 sscanf (test_argv
[2], "%d", (unsigned int *) &arg
);
20490 do_wait_idle_child( arg
);
20494 InitializeCriticalSection( &sequence_cs
);
20498 register_classes();
20500 if (pSetWinEventHook
)
20502 hEvent_hook
= pSetWinEventHook(EVENT_MIN
, EVENT_MAX
,
20503 GetModuleHandleA(0), win_event_proc
,
20504 0, GetCurrentThreadId(),
20505 WINEVENT_INCONTEXT
);
20506 if (pIsWinEventHookInstalled
&& hEvent_hook
)
20509 for (event
= EVENT_MIN
; event
<= EVENT_MAX
; event
++)
20510 ok(pIsWinEventHookInstalled(event
), "IsWinEventHookInstalled(%u) failed\n", event
);
20513 if (!hEvent_hook
) win_skip( "no win event hook support\n" );
20515 cbt_hook_thread_id
= winevent_hook_thread_id
= GetCurrentThreadId();
20516 hCBT_hook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
20517 if (!hCBT_hook
) win_skip( "cannot set global hook, will skip hook tests\n" );
20520 test_SendMessage_other_thread();
20521 test_setparent_status();
20522 test_InSendMessage();
20525 test_PostMessage();
20528 test_PeekMessage();
20529 test_PeekMessage2();
20530 test_PeekMessage3();
20531 test_WaitForInputIdle( test_argv
[0] );
20532 test_scrollwindowex();
20534 test_setwindowpos();
20536 invisible_parent_tests();
20537 test_mdi_messages();
20538 test_button_messages();
20539 test_button_bm_get_set_image();
20540 test_button_style();
20541 test_autoradio_BM_CLICK();
20542 test_autoradio_kbd_move();
20543 test_static_messages();
20544 test_listbox_messages();
20545 test_combobox_messages();
20546 test_wmime_keydown_message();
20547 test_paint_messages();
20548 run_in_temp_desktop(test_swp_paint_regions
);
20549 run_in_temp_desktop(test_swp_paint_region_on_show
);
20550 run_in_temp_desktop(test_swp_paint_region_on_extend_zerosize
);
20551 run_in_temp_desktop(test_hvredraw
);
20552 test_interthread_messages();
20553 test_message_conversion();
20554 test_accelerators();
20556 test_timers_no_wnd();
20557 test_timers_exceptions();
20561 test_recursive_hook();
20563 test_recursive_messages();
20564 test_DestroyWindow();
20565 test_DispatchMessage();
20566 test_SendMessageTimeout();
20567 test_edit_messages();
20568 test_quit_message();
20569 test_notify_message();
20570 test_SetActiveWindow();
20571 test_restore_messages();
20572 test_invalid_window();
20573 test_menu_messages();
20574 test_paintingloop();
20576 if (!pTrackMouseEvent
)
20577 win_skip("TrackMouseEvent is not available\n");
20579 test_TrackMouseEvent();
20581 test_SetWindowRgn();
20583 test_dialog_messages();
20585 test_nullCallback();
20586 test_dbcs_wm_char();
20587 test_unicode_wm_char();
20589 test_desktop_winproc();
20590 test_clipboard_viewers();
20593 test_layered_window();
20594 test_TrackPopupMenu();
20595 test_TrackPopupMenuEmpty();
20596 test_DoubleSetCapture();
20597 test_create_name();
20598 test_hook_changing_window_proc();
20599 /* keep it the last test, under Windows it tends to break the tests
20600 * which rely on active/foreground windows being correct.
20602 test_SetForegroundWindow();
20604 UnhookWindowsHookEx(hCBT_hook
);
20605 if (pUnhookWinEvent
&& hEvent_hook
)
20607 ret
= pUnhookWinEvent(hEvent_hook
);
20608 ok( ret
, "UnhookWinEvent error %ld\n", GetLastError());
20609 SetLastError(0xdeadbeef);
20610 ok(!pUnhookWinEvent(hEvent_hook
), "UnhookWinEvent succeeded\n");
20611 ok(GetLastError() == ERROR_INVALID_HANDLE
|| /* Win2k */
20612 GetLastError() == 0xdeadbeef, /* Win9x */
20613 "unexpected error %ld\n", GetLastError());
20615 DeleteCriticalSection( &sequence_cs
);